From gintas at codespeak.net Fri Jul 1 15:26:06 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 15:26:06 +0200 (CEST) Subject: [pypy-svn] r14027 - in pypy/dist/pypy: annotation documentation interpreter Message-ID: <20050701132606.312B927B4D@code1.codespeak.net> Author: gintas Date: Fri Jul 1 15:26:05 2005 New Revision: 14027 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/documentation/architecture.txt pypy/dist/pypy/documentation/coding-guide.txt pypy/dist/pypy/documentation/contributor.txt pypy/dist/pypy/documentation/faq.txt pypy/dist/pypy/documentation/svn-help.txt pypy/dist/pypy/documentation/translation.txt pypy/dist/pypy/interpreter/function.py Log: Removed trailing whitespace, fixed typos, wrapped long lines. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Fri Jul 1 15:26:05 2005 @@ -305,7 +305,7 @@ getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() if s_item == SomeImpossibleValue(): - return immutablevalue("") + return immutablevalue("") return SomeString() def iter(str): @@ -330,7 +330,7 @@ def len(chr): return immutablevalue(1) - def method_isspace(chr): + def method_isspace(chr): return SomeBool() class __extend__(SomeUnicodeCodePoint): Modified: pypy/dist/pypy/documentation/architecture.txt ============================================================================== --- pypy/dist/pypy/documentation/architecture.txt (original) +++ pypy/dist/pypy/documentation/architecture.txt Fri Jul 1 15:26:05 2005 @@ -351,7 +351,7 @@ order for our translation and type inference mechanisms to work effectively, we need to restrict the dynamism of our interpreter-level Python code at some point. However, in the start-up phase, we are -completly free to use all kind of nice python constructs, including +completely free to use all kind of nice python constructs, including metaclasses and execution of dynamically constructed strings. However, when the initialization phase (mainly, the function ``objspace.initialize()``) finishes, all code objects involved need to @@ -367,7 +367,7 @@ of values, and an exitswitch to one, two or multiple links which connect each basic block to other basic blocks. -The flow graphs are fed as input into the Annotator. The Annotator, +The flow graphs are fed as input into the Annotator. The Annotator, given entry point types, infers the types of values that flow through the program variables. Here, the definition of `RPython`_ comes again into play: RPython code is restricted in such a way that the @@ -383,7 +383,7 @@ definition will probably continue to shift marginally as we improve it. The actual low-level code (and, in fact, also other high-level code) is -emitted by "visiting" the type-annotated flow graph. Currently, we have +emitted by "visiting" the type-annotated flow graph. Currently we have a C-producing backend, and an LLVM-producing backend. The former also accepts non-annotated or partially-annotated graphs, which allow us to test it on a larger class of programs than what the Annotator can (or Modified: pypy/dist/pypy/documentation/coding-guide.txt ============================================================================== --- pypy/dist/pypy/documentation/coding-guide.txt (original) +++ pypy/dist/pypy/documentation/coding-guide.txt Fri Jul 1 15:26:05 2005 @@ -1,24 +1,25 @@ ===================================== -PyPy - Coding Guide +PyPy - Coding Guide ===================================== .. contents:: .. sectnum:: -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. +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. -.. _`RPython`: +.. _`RPython`: Restricted Python ================== -We are writing a Python interpreter in Python, using Python's well known ability -to step behind the algorithmic problems as language. At first glance, one might -think this achieves nothing but a better understanding how the interpreter works. -This alone would make it worth doing, but we have much larger goals. +We are writing a Python interpreter in Python, using Python's well known +ability to step behind the algorithmic problems as language. At first glance, +one might think this achieves nothing but a better understanding how the +interpreter works. This alone would make it worth doing, but we have much +larger goals. CPython vs. PyPy @@ -29,36 +30,36 @@ also aim at writing a more flexible interpreter at C level but but we want to use Python to give an alternative description of the interpreter. -The clear advantage is that such a description is shorter and simpler to -read, and many implementation details vanish. The drawback of this approach is +The clear advantage is that such a description is shorter and simpler to +read, and many implementation details vanish. The drawback of this approach is that this interpreter will be unbearably slow as long as it is run on top of CPython. To get to a useful interpreter again, we need to translate our high-level description of Python to a lower level one. One rather straight-forward way is to do a whole program analysis of the PyPy -interpreter and create a C source, again. There are many other ways, -but let's stick with this somewhat canonical approach. +interpreter and create a C source, again. There are many other ways, +but let's stick with this somewhat canonical approach. -our runtime interpreter is "restricted python" +our runtime interpreter is "restricted python" ---------------------------------------------- In order to make a C code generator feasible we restrict ourselves to a subset of the Python language, and we adhere to some rules which make -translation to lower level languages more obvious. +translation to lower level languages more obvious. Unlike source-to-source translations (like e.g. Starkiller_) we start translation from live python code objects which constitute our Python interpreter. When doing its work of interpreting bytecode our Python -implementation must behave in a static way often referenced as -"RPythonic". +implementation must behave in a static way often referenced as +"RPythonic". .. _Starkiller: http://www.python.org/pycon/dc2004/papers/1/paper.pdf However, when the PyPy interpreter is started as a Python program, it can use all of the Python language until it reaches interpretation runtime. That is, during initialization our program is free to use the -full dynamism of Python, including dynamic code generation. +full dynamism of Python, including dynamic code generation. An example can be found in the current implementation which is quite elegant: For the definition of all the opcodes of the Python @@ -74,19 +75,19 @@ during translation, a whole program analysis ("type inference") is performed, which makes use of the restrictions defined in RPython. This enables the code generator to emit efficient machine level replacements -for pure integer objects, for instance. +for pure integer objects, for instance. -.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py +.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py RPython Definition, not ----------------------- -The list and exact details of the "RPython" restrictions are a somewhat +The list and exact details of the "RPython" restrictions are a somewhat evolving topic. In particular, we have no formal language definition -as we find it more practical to discuss and evolve the set of +as we find it more practical to discuss and evolve the set of restrictions while working on the whole program analysis. If you have any questions about the restrictions below then please feel -free to mail us at pypy-dev at codespeak net. +free to mail us at pypy-dev at codespeak net. .. _`wrapped object`: coding-guide.html#wrapping-rules @@ -94,7 +95,7 @@ ------------------------- **variables** - + variables should contain values of at most one type as described in `Object restrictions`_ at each control flow point, that means for example that joining control paths using the same variable to @@ -103,16 +104,16 @@ and class instances is allowed. **constants** - + all module globals are considered constants. **control structures** - + all allowed **range** - - does not create an array. It is only allowed in for loops. The step argument + + does not create an array. It is only allowed in for loops. The step argument must be a constant. **definitions** @@ -135,55 +136,55 @@ We are using **integer, float, string, boolean** - + avoid string methods and complex operations like slicing with a step **tuples** - - no variable-length tuples; use them to store or return pairs or n-tuples of + + no variable-length tuples; use them to store or return pairs or n-tuples of values. Each combination of types for elements and length constitute a separate and not mixable type. **lists** - - lists are used as an allocated array; list.append() does naive resizing, so as + + lists are used as an allocated array; list.append() does naive resizing, so as far as possible use list comprehensions (see below). list.extend() or the += operator are allowed and efficient. Unless there is really a use case for it, repetition is limited to initialization purposes: '[single_value] * length'. **dicts** - + dicts with string keys only (preferably the kind of strings that are usually interned in CPython, i.e. short strings that look like identifiers). The implementation could safely decide that all dict keys should be interned. **list comprehensions** - - may be used to create allocated, initialized array. the array size must be + + may be used to create allocated, initialized array. the array size must be computable in advance, which implies that we don't allow an if clause. **functions** -+ statically called functions may use defaults and a variable number of - arguments (which may be passed as a list instead of a tuple, so write code that - does not depend on it being a tuple). - -+ dynamic dispatch enforces use of very simple signatures, equal for all - functions to be called in that context. At the moment, this occurs in the opcode - dispatch, only. ++ statically called functions may use defaults and a variable number of + arguments (which may be passed as a list instead of a tuple, so write code + that does not depend on it being a tuple). + ++ dynamic dispatch enforces use of very simple signatures, equal for all + functions to be called in that context. At the moment, this occurs in the + opcode dispatch, only. **builtin functions** - A few builtin functions will be used, while this set is not defined + A few builtin functions will be used, while this set is not defined completely, yet. Some builtin functions are special forms: **len** -+ may be used with basic types that have a length. But len is a special form ++ may be used with basic types that have a length. But len is a special form that is recognized by the compiler. -+ If a certain structure is never touched by len, the compiler might save the ++ If a certain structure is never touched by len, the compiler might save the length field from the underlying structure. ``int, float, ord, chr``... are available as simple conversion functions. @@ -198,8 +199,8 @@ **objects** - wrapped objects are borrowed from the object space. Just like in CPython, code - that needs e.g. a dictionary can use a wrapped dict and the object space + wrapped objects are borrowed from the object space. Just like in CPython, + code that needs e.g. a dictionary can use a wrapped dict and the object space operations on it. This layout makes the number of types to take care about quite limited. @@ -208,13 +209,13 @@ Integer Types ------------------------- -While implementing the integer type, we stumbled over the problem, that +While implementing the integer type, we stumbled over the problem, that integers are quite in flux in CPython right now. Starting on Python 2.2, -integers mutate into longs on overflow. However, shifting to the left truncates -up to 2.3 but extends to longs as well in 2.4. By contrast, we need a way to -perform wrap-around machine-sized arithmetic by default, while still being -able to check for overflow when we need it explicitly. Moreover, we need a -consistent behavior before and after translation. +integers mutate into longs on overflow. However, shifting to the left +truncates up to 2.3 but extends to longs as well in 2.4. By contrast, we need +a way to perform wrap-around machine-sized arithmetic by default, while still +being able to check for overflow when we need it explicitly. Moreover, we need +a consistent behavior before and after translation. We use normal integers for signed arithmetic. It means that before translation we get longs in case of overflow, and after translation we get a @@ -226,7 +227,7 @@ This special function should only be used with a single arithmetic operation as its argument, e.g. ``z = ovfcheck(x+y)``. Its intended meaning is to perform the given operation in overflow-checking mode. - + At run-time, in Python, the ovfcheck() function itself checks the result and raises OverflowError if it is a ``long``. But the code generators use ovfcheck() as a hint: they replace the whole ``ovfcheck(x+y)`` expression @@ -245,7 +246,7 @@ This function is used for wrap-around arithmetic. It returns the lower bits of its argument, masking away anything that doesn't fit in a C "signed long int". - Its purpose is, in Python, to convert from a Python ``long`` that resulted from a + Its purpose is, in Python, to convert from a Python ``long`` that resulted from a previous operation back to a Python ``int``. The code generators ignore intmask() entirely, as they are doing wrap-around signed arithmetic all the time by default anyway. (We have no equivalent of the "int" versus "long int" @@ -311,35 +312,46 @@ Exceptions explicitly raised or re-raised will always be generated. -PyPy is debuggable on top of CPython ------------------------------------- +PyPy is debuggable on top of CPython +------------------------------------ PyPy has the advantage that it is runnable on standard CPython. That means, we can run all of PyPy with all exception handling enabled, so we might catch cases where we failed to adhere to our implicit assertions. -.. _`wrapping rules`: +.. _`wrapping rules`: Wrapping rules ============== -PyPy is made of Python source code at two levels: there is on the one hand *application-level code* that looks like normal Python code, and that implements some functionalities as one would expect from Python code (e.g. one can give a pure Python implementation of some built-in functions like ``zip()``). There is also *interpreter-level code* for the functionalities that must more directly manipulate interpreter data and objects (e.g. the main loop of the interpreter, and the various object spaces). - -Application-level code doesn't see object spaces explicitly: it runs using an object space to support the objects it manipulates, but this is implicit. There is no need for particular conventions for application-level code. The sequel is only about interpreter-level code. (Ideally, no application-level variable should be called ``space`` or ``w_xxx`` to avoid confusion.) +PyPy is made of Python source code at two levels: there is on the one hand +*application-level code* that looks like normal Python code, and that +implements some functionalities as one would expect from Python code (e.g. one +can give a pure Python implementation of some built-in functions like +``zip()``). There is also *interpreter-level code* for the functionalities +that must more directly manipulate interpreter data and objects (e.g. the main +loop of the interpreter, and the various object spaces). + +Application-level code doesn't see object spaces explicitly: it runs using an +object space to support the objects it manipulates, but this is implicit. +There is no need for particular conventions for application-level code. The +sequel is only about interpreter-level code. (Ideally, no application-level +variable should be called ``space`` or ``w_xxx`` to avoid confusion.) Naming conventions ------------------ * ``space``: the object space is only visible at - interpreter-level code, where it is by convention passed around by the name ``space``. + interpreter-level code, where it is by convention passed around by the name + ``space``. * ``w_xxx``: any object seen by application-level code is an object explicitly managed by the object space. From the interpreter-level point of view, this is called a *wrapped* object. The ``w_`` prefix is used for any type of - application-level object. + application-level object. * ``xxx_w``: an interpreter-level container for wrapped objects, for example a list or a dict containing wrapped @@ -375,7 +387,8 @@ Building ``w_xxx`` objects -------------------------- -From the core interpreter, wrapped objects are usually built as the result of an object space operation. The ways to directly create a wrapped object are: +From the core interpreter, wrapped objects are usually built as the result of +an object space operation. The ways to directly create a wrapped object are: * ``space.wrap(x)``: returns a wrapped object containing the value ``x``. Only works if ``x`` is either a simple value @@ -510,32 +523,32 @@ application-level classes. -.. _`modules`: +.. _`modules`: -Modules in PyPy -=============== +Modules in PyPy +=============== -Modules visible from application programs are imported from +Modules visible from application programs are imported from interpreter or application level files. PyPy reuses almost all python modules of CPython's standard library, currently from version 2.3.4. We sometimes need to `modify modules`_ and - more often - regression tests -because they rely on implementation details of CPython. +because they rely on implementation details of CPython. If we don't just modify an original CPython module but need to rewrite it from scratch we put it into `pypy/lib/`_ as a pure application level -module. +module. When we need access to interpreter-level objects we put the module into `pypy/module`_. Such modules use a `mixed module mechanism`_ which makes it convenient to use both interpreter- and applicationlevel parts for the implementation. Note that there is no extra facility for -pure-interpreter level modules because we haven't needed it so far. +pure-interpreter level modules because we haven't needed it so far. -Determining the location of a module implementation ---------------------------------------------------- +Determining the location of a module implementation +--------------------------------------------------- -You can interactively find out where a module comes from, -here are examples for the possible locations:: +You can interactively find out where a module comes from, +here are examples for the possible locations:: >>>> import sys >>>> sys.__file__ @@ -556,21 +569,21 @@ '/home/hpk/pypy-dist/lib-python/2.3.4/os.py' >>>> -Module directories / Import order +Module directories / Import order --------------------------------- -Here is the order in which PyPy looks up Python modules: +Here is the order in which PyPy looks up Python modules: + +*pypy/modules* -*pypy/modules* + mixed interpreter/app-level builtin modules, such as + the ``sys`` and ``__builtin__`` module. - mixed interpreter/app-level builtin modules, such as - the ``sys`` and ``__builtin__`` module. +*contents of PYTHONPATH* -*contents of PYTHONPATH* - - lookup application level modules in each of the ``:`` separated - list of directories, specified in the ``PYTHONPATH`` environment - variable. + lookup application level modules in each of the ``:`` separated + list of directories, specified in the ``PYTHONPATH`` environment + variable. *pypy/lib/* @@ -582,93 +595,94 @@ *lib-python/2.3.4/* - The unmodified CPython library. **Never ever checkin anything here**. + The unmodified CPython library. **Never ever checkin anything here**. -.. _`modify modules`: +.. _`modify modules`: -Modifying a CPython library module or regression test -------------------------------------------------------- +Modifying a CPython library module or regression test +------------------------------------------------------- -Although PyPy is very compatible with CPython we sometimes need -to change modules contained in our copy of the standard library, -often due to the fact that PyPy works with all new-style classes -by default and CPython has a number of places where it relies -on some classes being old-style. +Although PyPy is very compatible with CPython we sometimes need +to change modules contained in our copy of the standard library, +often due to the fact that PyPy works with all new-style classes +by default and CPython has a number of places where it relies +on some classes being old-style. If you want to change a module or test contained in ``lib-python/2.3.4`` -then make sure that you copy the file to our ``lib-python/modified-2.3.4`` -directory first. In subversion commandline terms this reads:: +then make sure that you copy the file to our ``lib-python/modified-2.3.4`` +directory first. In subversion commandline terms this reads:: - svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/ + svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/ -and subsequently you edit and commit ``lib-python/modified-2.3.4/somemodule.py``. -This copying operation is important because it keeps the original -CPython tree clean and makes it obvious what we had to change. +and subsequently you edit and commit +``lib-python/modified-2.3.4/somemodule.py``. This copying operation is +important because it keeps the original CPython tree clean and makes it +obvious what we had to change. -.. _`mixed module mechanism`: -.. _`mixed modules`: +.. _`mixed module mechanism`: +.. _`mixed modules`: -Implementing a mixed interpreter/application level Module ---------------------------------------------------------- +Implementing a mixed interpreter/application level Module +--------------------------------------------------------- -If a module needs to access PyPy's interpreter level -then it is implemented as a mixed module. +If a module needs to access PyPy's interpreter level +then it is implemented as a mixed module. Mixed modules are directories in `pypy/module`_ with an `__init__.py` file containing specifications where each name in a module comes from. Only specified names will be exported to a Mixed Module's applevel -namespace. +namespace. application level definitions ............................. -Application level specifications are found in the `appleveldefs` -dictionary found in ``__init__.py`` files of directories in ``pypy/module``. -For example, in `pypy/module/__builtin__/__init__.py`_ you find the following -entry specifying where ``__builtin__.locals`` comes from:: +Application level specifications are found in the `appleveldefs` +dictionary found in ``__init__.py`` files of directories in ``pypy/module``. +For example, in `pypy/module/__builtin__/__init__.py`_ you find the following +entry specifying where ``__builtin__.locals`` comes from:: ... 'locals' : 'app_inspect.locals', ... -The ``app_`` prefix indicates that the submodule ``app_inspect`` is -interpreted at application level and the wrapped function value for ``locals`` -will be extracted accordingly. +The ``app_`` prefix indicates that the submodule ``app_inspect`` is +interpreted at application level and the wrapped function value for ``locals`` +will be extracted accordingly. interpreter level definitions ............................. -Interpreter level specifications are found in the ``interpleveldefs`` -dictionary found in ``__init__.py`` files of directories in ``pypy/module``. -For example, in `pypy/module/__builtin__/__init__.py`_ the following -entry specifies where ``__builtin__.len`` comes from:: +Interpreter level specifications are found in the ``interpleveldefs`` +dictionary found in ``__init__.py`` files of directories in ``pypy/module``. +For example, in `pypy/module/__builtin__/__init__.py`_ the following +entry specifies where ``__builtin__.len`` comes from:: ... 'len' : 'operation.len', ... -The ``operation`` submodule lives at interpreter level and ``len`` +The ``operation`` submodule lives at interpreter level and ``len`` is expected to be exposable to application level. Here is -the definition for ``operation.len()``:: +the definition for ``operation.len()``:: def len(space, w_obj): "len(object) -> integer\n\nReturn the number of items of a sequence or mapping." return space.len(w_obj) Exposed interpreter level functions usually take a ``space`` argument -and some wrapped values (see `wrapping rules`_) . +and some wrapped values (see `wrapping rules`_) . -You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: -namely an expression in parentheses to specify an interpreter level -expression directly (instead of pulling it indirectly from a file):: +You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: +namely an expression in parentheses to specify an interpreter level +expression directly (instead of pulling it indirectly from a file):: ... 'None' : '(space.w_None)', 'False' : '(space.w_False)', - ... + ... The interpreter level expression has a ``space`` binding when -it is executed. +it is executed. Testing modules in ``pypy/lib`` -------------------------------- @@ -677,50 +691,50 @@ ("py.test" or "python ../../test_all.py") to run tests against the pypy/lib hierarchy. Note, that tests in `pypy/lib/test2`_ are allowed and encouraged to let their tests run at interpreter level although -`pypy/lib/`_ modules eventually live at PyPy's application level. -This allows us to quickly test our python-coded reimplementations -against CPython. +`pypy/lib/`_ modules eventually live at PyPy's application level. +This allows us to quickly test our python-coded reimplementations +against CPython. .. _`pypy/lib/test2`: http://codespeak.net/svn/pypy/dist/pypy/lib/test2 Testing modules in ``pypy/module`` ---------------------------------- -Simply change to ``pypy/module`` or to a subdirectory and `run the -tests as usual`_. +Simply change to ``pypy/module`` or to a subdirectory and `run the +tests as usual`_. Testing modules in ``lib-python`` ----------------------------------- -In order to let CPython's regression tests run against PyPy -you can switch to the `lib-python/`_ directory and run -the testing tool in order to start compliance tests. -(XXX check windows compatibility for producing test reports). +In order to let CPython's regression tests run against PyPy +you can switch to the `lib-python/`_ directory and run +the testing tool in order to start compliance tests. +(XXX check windows compatibility for producing test reports). -Naming conventions and directory layout +Naming conventions and directory layout =========================================== -Directory and File Naming +Directory and File Naming ------------------------- - directories/modules/namespaces are always **lowercase** - never use plural names in directory and file names -- ``__init__.py`` is usually empty except for - ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. +- ``__init__.py`` is usually empty except for + ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. - don't use more than 4 directory nesting levels -- keep filenames concise and completion-friendly. +- keep filenames concise and completion-friendly. Naming of python objects ------------------------ - class names are **CamelCase** -- functions/methods are lowercase and ``_`` separated +- functions/methods are lowercase and ``_`` separated - objectspace classes are spelled ``XyzObjSpace``. e.g. @@ -736,25 +750,25 @@ ----------------------------------------------------- - write good log messages because several people - are reading the diffs. + are reading the diffs. - if you add (text/py) files to the repository then please run - pypy/tool/fixeol in that directory. This will make sure - that the property 'svn:eol-style' is set to native which + pypy/tool/fixeol in that directory. This will make sure + that the property 'svn:eol-style' is set to native which allows checkin/checkout in native line-ending format. - branching (aka "svn copy") of source code should usually happen at ``svn/pypy/dist`` level in order to have a full self-contained pypy checkout for each branch. For branching - a ``try1`` branch you would for example do:: + a ``try1`` branch you would for example do:: svn cp http://codespeak.net/svn/pypy/dist \ - http://codespeak.net/svn/pypy/branch/try1 + http://codespeak.net/svn/pypy/branch/try1 - This allows to checkout the ``try1`` branch and receive a - self-contained working-copy for the branch. Note that - branching/copying is a cheap operation with subversion, as it - takes constant time irrespective of the size of the tree. + This allows to checkout the ``try1`` branch and receive a + self-contained working-copy for the branch. Note that + branching/copying is a cheap operation with subversion, as it + takes constant time irrespective of the size of the tree. - To learn more about how to use subversion read `this document`_. @@ -762,41 +776,41 @@ -.. _`using development tracker`: +.. _`using development tracker`: Using the development bug/feature tracker ========================================= -We have a `development tracker`_, based on Richard Jones' -`roundup`_ application. You can file bugs, -feature requests or see what's going on -for the next milestone, both from an E-Mail and from a -web interface. +We have a `development tracker`_, based on Richard Jones' +`roundup`_ application. You can file bugs, +feature requests or see what's going on +for the next milestone, both from an E-Mail and from a +web interface. use your codespeak login or register ------------------------------------- +------------------------------------ If you already committed to the PyPy source code, chances are that you can simply use your codespeak login that -you use for subversion or for shell access. +you use for subversion or for shell access. If you are not a commiter then you can still `register with -the tracker`_ easily. +the tracker`_ easily. modifying Issues from svn commit messages ------------------------------------------ +----------------------------------------- -If you are committing something related to -an issue in the development tracker you -can correlate your login message to a tracker -item by following these rules: +If you are committing something related to +an issue in the development tracker you +can correlate your login message to a tracker +item by following these rules: -- put the content of ``issueN STATUS`` on a single - new line +- put the content of ``issueN STATUS`` on a single + new line -- `N` must be an existing issue number from the `development tracker`_. +- `N` must be an existing issue number from the `development tracker`_. -- STATUS is one of:: +- STATUS is one of:: unread chatting @@ -811,10 +825,10 @@ .. _`roundup`: http://roundup.sf.net -.. _`testing in PyPy`: +.. _`testing in PyPy`: Testing in PyPy -=============== +=============== Our tests are based on the new `py.test`_ tool which lets you write unittests without boilerplate. All tests of modules @@ -829,55 +843,55 @@ Both types of tests need an `objectspace`_ they can run with (the interpreter dispatches operations on objects to an objectspace). If you run a test you -can usually give the '-o' switch to select an object space. E.g. '-o thunk' -will select the thunk object space. The default is the `Standard Object Space`_ -which aims to implement unmodified Python semantics. +can usually give the '-o' switch to select an object space. E.g. '-o thunk' +will select the thunk object space. The default is the `Standard Object Space`_ +which aims to implement unmodified Python semantics. .. _`standard object space`: objspace.html#standard-object-space -.. _`objectspace`: architecture.html#objectspace -.. _`py.test`: http://codespeak.net/py/current/doc/test.html +.. _`objectspace`: architecture.html#objectspace +.. _`py.test`: http://codespeak.net/py/current/doc/test.html + +Interpreter level tests +----------------------- -Interpreter level tests ------------------------ +You can write test functions and methods like this:: -You can write test functions and methods like this:: + def test_something(space): + # use space ... - def test_something(space): - # use space ... - - class TestSomething: - def test_some(self): - # use 'self.space' here + class TestSomething: + def test_some(self): + # use 'self.space' here Note that the prefix `test` for test functions and `Test` for test classes is mandatory. In both cases you can import Python modules at module global level and use plain 'assert' statements thanks to the -usage of the `py.test`_ tool. +usage of the `py.test`_ tool. -Application Level tests ------------------------ +Application Level tests +----------------------- For testing the conformance and well-behavedness of PyPy it -is often sufficient to write "normal" application-level +is often sufficient to write "normal" application-level Python code that doesn't need to be aware of any particular coding style or restrictions. If we have a choice we often use application level tests which usually look like this:: def app_test_something(): - # application level test code + # application level test code - class AppTestSomething: - def test_this(self): - # application level test code + class AppTestSomething: + def test_this(self): + # application level test code These application level test functions will run on top -of PyPy, i.e. they have no access to interpreter details. +of PyPy, i.e. they have no access to interpreter details. You cannot use imported modules from global level because they are imported at interpreter-level while you test code runs at application level. If you need to use modules -you have to import them within the test function. +you have to import them within the test function. -.. _`run the tests as usual`: +.. _`run the tests as usual`: Command line tool test_all -------------------------- @@ -886,65 +900,65 @@ python test_all.py -which is a synonym for the general `py.test`_ utility -located in the ``pypy`` directory. For switches to -modify test execution pass the ``-h`` option. +which is a synonym for the general `py.test`_ utility +located in the ``pypy`` directory. For switches to +modify test execution pass the ``-h`` option. Test conventions ---------------- - adding features requires adding appropriate tests. (It often even makes sense to first write the tests so that you are sure that they - actually can fail.) + actually can fail.) -- All over the pypy source code there are test/ directories +- All over the pypy source code there are test/ directories which contain unittests. Such scripts can usually be executed - directly or are collectively run by pypy/test_all.py + directly or are collectively run by pypy/test_all.py - each test directory needs a copy of pypy/tool/autopath.py which upon import will make sure that sys.path contains the directory - where 'pypy' is in. + where 'pypy' is in. -.. _`change documentation and website`: +.. _`change documentation and website`: -Changing documentation and website -================================== +Changing documentation and website +================================== -documentation/website files in your local checkout +documentation/website files in your local checkout --------------------------------------------------- -Most of the PyPy's documentation and website is kept in -`pypy/documentation` and `pypy/documentation/website` respectively. -You can simply edit or add '.txt' files which contain ReST-markuped +Most of the PyPy's documentation and website is kept in +`pypy/documentation` and `pypy/documentation/website` respectively. +You can simply edit or add '.txt' files which contain ReST-markuped files. Here is a `ReST quickstart`_ but you can also just look -at the existing documentation and see how things work. +at the existing documentation and see how things work. .. _`ReST quickstart`: http://docutils.sourceforge.net/docs/rst/quickref.html Automatically test documentation/website changes ------------------------------------------------ -.. _`docutils home page`: -.. _`docutils`: http://docutils.sourceforge.net/ +.. _`docutils home page`: +.. _`docutils`: http://docutils.sourceforge.net/ -We automatically check referential integrity and ReST-conformance. In order to -run the tests you need docutils_ installed. Then go to the local checkout -of the documentation directory and run the tests:: +We automatically check referential integrity and ReST-conformance. In order to +run the tests you need docutils_ installed. Then go to the local checkout +of the documentation directory and run the tests:: - cd .../pypy/documentation - python ../test_all.py + cd .../pypy/documentation + python ../test_all.py -If you see no failures chances are high that your modifications at least +If you see no failures chances are high that your modifications at least don't produce ReST-errors or wrong local references. A side effect of running -the tests is that you have `.html` files in the documentation directory -which you can point your browser to! +the tests is that you have `.html` files in the documentation directory +which you can point your browser to! -Additionally, if you also want to check for remote references inside -the documentation issue:: +Additionally, if you also want to check for remote references inside +the documentation issue:: - python ../test_all.py --checkremote + python ../test_all.py --checkremote -which will check that remote URLs are reachable. +which will check that remote URLs are reachable. .. include:: _ref.txt Modified: pypy/dist/pypy/documentation/contributor.txt ============================================================================== --- pypy/dist/pypy/documentation/contributor.txt (original) +++ pypy/dist/pypy/documentation/contributor.txt Fri Jul 1 15:26:05 2005 @@ -1,10 +1,10 @@ -Contributors to PyPy -==================== +Contributors to PyPy +==================== -Here is a list of developers who have committed to the PyPy source -code base, ordered by number of commits (which is certainly not a very -appropriate measure but it's something):: +Here is a list of developers who have committed to the PyPy source +code base, ordered by number of commits (which is certainly not a very +appropriate measure but it's something):: Armin Rigo Samuele Pedroni Modified: pypy/dist/pypy/documentation/faq.txt ============================================================================== --- pypy/dist/pypy/documentation/faq.txt (original) +++ pypy/dist/pypy/documentation/faq.txt Fri Jul 1 15:26:05 2005 @@ -1,13 +1,12 @@ -Frequently Asked Questions -========================== +Frequently Asked Questions +========================== -How fast is PyPy? +How fast is PyPy? As of June 2005, PyPy still runs on top of CPython and thus - is slower by a factor of 2000 compared to CPython. We don't + is slower by a factor of 2000 compared to CPython. We don't know yet how fast it will be once we complete our translation - efforts, aimed at a first static self-contained low-level - translated version. - + efforts, aimed at a first static self-contained low-level + translated version. Modified: pypy/dist/pypy/documentation/svn-help.txt ============================================================================== --- pypy/dist/pypy/documentation/svn-help.txt (original) +++ pypy/dist/pypy/documentation/svn-help.txt Fri Jul 1 15:26:05 2005 @@ -1,9 +1,9 @@ -Installing subversion for PyPy -============================== +Installing subversion for PyPy +============================== -Jens-Uwe Mager has prepared some installation files which should -help you to install subversion on your computer. +Jens-Uwe Mager has prepared some installation files which should +help you to install subversion on your computer. + Download Unix source tarball or prepackaged versions_ for MacOS, Windows, FreeBSD and Linux @@ -12,7 +12,7 @@ * See Microsoft website_ if you have .DLL issues. * Windows Installer file for Tortoise SVN (like Tortoise CVS) GUI_ - (Pick the UNICODE version for Windows 2000 and XP and + (Pick the UNICODE version for Windows 2000 and XP and see Win_ 2000, NT if you have problems loading it.) + Local copy of MacOS_ X binary tar ball @@ -28,7 +28,7 @@ **Download and install the appropriate installation file of subversion above.** -For linux: +For linux: download the tarball. unzip and untar it. Then type *./configure*. Then, as root, *make* followed by *make install*. Voil? ... a subversion client. @@ -87,7 +87,7 @@ Transmitting file data . Committed revision 631. -Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made! +Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made! .. _`svn-commit archives`: http://codespeak.net/pipermail/pypy-svn/ @@ -158,4 +158,4 @@ .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 .. _backports: http://www.backports.org .. _online: http://codespeak.net/svn/pypy/dist/ -.. _coding-guide: coding-guide.html +.. _coding-guide: coding-guide.html Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Fri Jul 1 15:26:05 2005 @@ -29,7 +29,7 @@ 2. The `Flow Object Space`_ processes the input program, turning each function independently into a `control flow graph`_ data structure - recording sequences of basic operations in + recording sequences of basic operations in static single assignment form `SSA`_. 3. Optionally, the Annotator_ performs global type inference on the @@ -67,56 +67,56 @@ (INCOMPLETE DRAFT) -We describe below how a control flow graph can be "annotated" to -discover the types of the objects. This annotation pass is a form of -type inference. It is done after control flow graphs are built by the -FlowObjSpace, but before these graphs are translated into low-level code +We describe below how a control flow graph can be "annotated" to +discover the types of the objects. This annotation pass is a form of +type inference. It is done after control flow graphs are built by the +FlowObjSpace, but before these graphs are translated into low-level code (e.g. C/Lisp/Pyrex). Model ------------------------ -The major goal of the annotator is to "annotate" each variable that -appears in a flow graph. An "annotation" describes all the possible -Python objects that this variable could contain at run-time, based on a +The major goal of the annotator is to "annotate" each variable that +appears in a flow graph. An "annotation" describes all the possible +Python objects that this variable could contain at run-time, based on a whole-program analysis of all the flow graphs --- one per function. -An "annotation" is an instance of ``SomeObject``. There are subclasses -that are meant to represent specific families of objects. Note that -these classes are all meant to be instantiated; the classes ``SomeXxx`` +An "annotation" is an instance of ``SomeObject``. There are subclasses +that are meant to represent specific families of objects. Note that +these classes are all meant to be instantiated; the classes ``SomeXxx`` themselves are not the annotations. Here is an overview (see ``pypy.annotation.model``): -* ``SomeObject`` is the base class. An instance ``SomeObject()`` - represents any Python object. It is used for the case where we don't - have enough information to be more precise. In practice, the presence - of ``SomeObject()`` means that we have to make the annotated source code +* ``SomeObject`` is the base class. An instance ``SomeObject()`` + represents any Python object. It is used for the case where we don't + have enough information to be more precise. In practice, the presence + of ``SomeObject()`` means that we have to make the annotated source code simpler or the annotator smarter. -* ``SomeInteger()`` represents any integer. +* ``SomeInteger()`` represents any integer. ``SomeInteger(nonneg=True)`` represent a non-negative integer (``>=0``). -* ``SomeString()`` represents any string; ``SomeChar()`` a string of +* ``SomeString()`` represents any string; ``SomeChar()`` a string of length 1. -* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``. The - elements in this tuple are themselves constrained by the given list of - annotations. For example, ``SomeTuple([SomeInteger(), SomeString()])`` +* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``. The + elements in this tuple are themselves constrained by the given list of + annotations. For example, ``SomeTuple([SomeInteger(), SomeString()])`` represents a tuple with two items: an integer and a string. -There are more complex subclasses of ``SomeObject`` that we describe in +There are more complex subclasses of ``SomeObject`` that we describe in more details below. -All the ``SomeXxx`` instances can optionally have a ``const`` attribute, -which means that we know exactly which Python object the Variable will +All the ``SomeXxx`` instances can optionally have a ``const`` attribute, +which means that we know exactly which Python object the Variable will contain. -All the ``SomeXxx`` instances are supposed to be immutable. The -annotator manages a dictionary mapping Variables (which appear in flow -graphs) to ``SomeXxx`` instances; if it needs to revise its belief about -what a Variable can contain, it does so by updating this dictionary, not +All the ``SomeXxx`` instances are supposed to be immutable. The +annotator manages a dictionary mapping Variables (which appear in flow +graphs) to ``SomeXxx`` instances; if it needs to revise its belief about +what a Variable can contain, it does so by updating this dictionary, not the ``SomeXxx`` instance. @@ -124,18 +124,18 @@ Annotator -------------------------- -The annotator itself (``pypy.translator.annrpython``) works by -propagating the annotations forward in the flow graphs, starting at some -entry point function, possibly with explicitely provided annotations -about the entry point's input arguments. It considers each operation in -the flow graph in turn. Each operation takes a few input arguments -(Variables and Constants) and produce a single result (a Variable). -Depending on the input argument's annotations, an annotation about the -operation result is produced. The exact rules to do this are provided -by the whole ``pypy.annotation`` subdirectory, which defines all the -cases in detail according to the R-Python semantics. For example, if -the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are -annotated with ``SomeInteger()``, then v3 also receives the annotation +The annotator itself (``pypy.translator.annrpython``) works by +propagating the annotations forward in the flow graphs, starting at some +entry point function, possibly with explicitely provided annotations +about the entry point's input arguments. It considers each operation in +the flow graph in turn. Each operation takes a few input arguments +(Variables and Constants) and produce a single result (a Variable). +Depending on the input argument's annotations, an annotation about the +operation result is produced. The exact rules to do this are provided +by the whole ``pypy.annotation`` subdirectory, which defines all the +cases in detail according to the R-Python semantics. For example, if +the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are +annotated with ``SomeInteger()``, then v3 also receives the annotation ``SomeInteger()``. So for example the function:: def f(n): @@ -145,22 +145,22 @@ start ----------. | - V + V +-------------------+ | v2 = add(v1, 1) | +-------------------+ | `---> return block -If the annotator is told that v1 is ``SomeInteger()``, then it will -deduce that v2 (and hence the function's return value) is +If the annotator is told that v1 is ``SomeInteger()``, then it will +deduce that v2 (and hence the function's return value) is ``SomeInteger()``. .. _above: -This step-by-step annotation phase proceeds through all the operations -in a block, and then along the links between the blocks of the flow -graph. If there are loops in the flow graph, then the links will close +This step-by-step annotation phase proceeds through all the operations +in a block, and then along the links between the blocks of the flow +graph. If there are loops in the flow graph, then the links will close back to already-seen blocks, as in:: def g(n): @@ -189,60 +189,60 @@ | m3 = sub(n3, 1) |---' +--------------------+ -Be sure to follow the variable renaming that occurs systematically -across each link in a flow graph. In the above example the Variables -have been given names similar to the name of the original variables in -the source code (the FlowObjSpace tries to do this too) but keep in mind +Be sure to follow the variable renaming that occurs systematically +across each link in a flow graph. In the above example the Variables +have been given names similar to the name of the original variables in +the source code (the FlowObjSpace tries to do this too) but keep in mind that all Variables are different: n1, n2, i2, v2, n3, i3, j3, m3. -Assume that we call the annotator with an input annotation of -``SomeInteger()`` for n1. Following the links from the start, the -annotator will first believe that the Variable i2, whose value comes -from the constant 0 of the first link, must always be zero. It will -thus use the annotation ``SomeInteger(const=0)`` for i2. Then it will -propagate the annotations through both blocks, and find that v2 is -``SomeBool()`` and all other variables are ``SomeInteger()``. In -particular, the annotation of j3 is different from the annotation of the -Variable i2 into which it is copied (via the back-link). More -precisely, j3 is ``SomeInteger()`` but i2 is the more specific -``SomeInteger(const=0)``. This means that the assumption that i2 must -always be zero is found to be wrong. At this point, the annotation of -i2 is *generalized* to include both the existing and the new annotation. -(This is the purpose of ``pypy.annotation.model.unionof()``). Then +Assume that we call the annotator with an input annotation of +``SomeInteger()`` for n1. Following the links from the start, the +annotator will first believe that the Variable i2, whose value comes +from the constant 0 of the first link, must always be zero. It will +thus use the annotation ``SomeInteger(const=0)`` for i2. Then it will +propagate the annotations through both blocks, and find that v2 is +``SomeBool()`` and all other variables are ``SomeInteger()``. In +particular, the annotation of j3 is different from the annotation of the +Variable i2 into which it is copied (via the back-link). More +precisely, j3 is ``SomeInteger()`` but i2 is the more specific +``SomeInteger(const=0)``. This means that the assumption that i2 must +always be zero is found to be wrong. At this point, the annotation of +i2 is *generalized* to include both the existing and the new annotation. +(This is the purpose of ``pypy.annotation.model.unionof()``). Then these more general annotations must again be propagated forward. -This process of successive generalizations continues until the -annotations stabilize. In the above example, it is sufficient to -re-analyse the first block once, but in general it can take several -iterations to reach a fixpoint. Annotations may also be propagated from -one flow graph to another and back repeatedly, across ``call`` -operations. The overall model should ensure that this process -eventually terminates under reasonable conditions. Note that as long as -the process is not finished, the annotations given to the Variables are -wrong, in the sense that they are too specific; at run-time, the -Variables will possibly contain Python objects outside the set defined +This process of successive generalizations continues until the +annotations stabilize. In the above example, it is sufficient to +re-analyse the first block once, but in general it can take several +iterations to reach a fixpoint. Annotations may also be propagated from +one flow graph to another and back repeatedly, across ``call`` +operations. The overall model should ensure that this process +eventually terminates under reasonable conditions. Note that as long as +the process is not finished, the annotations given to the Variables are +wrong, in the sense that they are too specific; at run-time, the +Variables will possibly contain Python objects outside the set defined by the annotation, and the annotator doesn't know it yet. Description of the available types ----------------------------------------------- -The reference and the details for the annotation model is found in the -module ``pypy.annotation.model``. We describe below the issues related +The reference and the details for the annotation model is found in the +module ``pypy.annotation.model``. We describe below the issues related to the various kinds of annotations. Simple Types ++++++++++++ -``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands +``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands for the obvious corresponding set of immutable Python objects. Tuples ++++++ -``SomeTuple`` only considers tuples of known length. We don't try to +``SomeTuple`` only considers tuples of known length. We don't try to handle tuples of varying length (the program should use lists instead). @@ -337,46 +337,46 @@ User-defined Classes and Instances ++++++++++++++++++++++++++++++++++ -``SomeInstance`` stands for an instance of the given class or any -subclass of it. For each user-defined class seen by the annotator, we -maintain a ClassDef (``pypy.annotation.classdef``) describing the -attributes of the instances of the class; essentially, a ClassDef gives -the set of all class-level and instance-level attributes, and for each +``SomeInstance`` stands for an instance of the given class or any +subclass of it. For each user-defined class seen by the annotator, we +maintain a ClassDef (``pypy.annotation.classdef``) describing the +attributes of the instances of the class; essentially, a ClassDef gives +the set of all class-level and instance-level attributes, and for each one, a corresponding ``SomeXxx`` annotation. -Instance-level attributes are discovered progressively as the annotation +Instance-level attributes are discovered progressively as the annotation progresses. Assignments like:: inst.attr = value -update the ClassDef of the given instance to record that the given +update the ClassDef of the given instance to record that the given attribute exists and can be as general as the given value. -For every attribute, the ClassDef also records all the positions where -the attribute is *read*. If, at some later time, we discover an -assignment that forces the annotation about the attribute to be -generalized, then all the places that read the attribute so far are -marked as invalid and the annotator will have to restart its analysis +For every attribute, the ClassDef also records all the positions where +the attribute is *read*. If, at some later time, we discover an +assignment that forces the annotation about the attribute to be +generalized, then all the places that read the attribute so far are +marked as invalid and the annotator will have to restart its analysis from there. -The distinction between instance-level and class-level attributes is -thin; class-level attributes are essentially considered as initial -values for instance-level attributes. Methods are not special in this -respect, except that they are bound to the instance (i.e. ``self = -SomeInstance(cls)``) when considered as the initial value for the +The distinction between instance-level and class-level attributes is +thin; class-level attributes are essentially considered as initial +values for instance-level attributes. Methods are not special in this +respect, except that they are bound to the instance (i.e. ``self = +SomeInstance(cls)``) when considered as the initial value for the instance. -The inheritance rules are as follows: the union of two ``SomeInstance`` -annotations is the ``SomeInstance`` of the most precise common base -class. If an attribute is considered (i.e. read or written) through a -``SomeInstance`` of a parent class, then we assume that all subclasses -also have the same attribute, and that the same annotation applies to -them all (so code like ``return self.x`` in a method of a parent class -forces the parent class and all its subclasses to have an attribute -``x``, whose annotation is general enough to contain all the values that -all the subclasses might want to store in ``x``). However, distinct -subclasses can have attributes of the same names with different, -unrelated annotations if they are not used in a general way through the +The inheritance rules are as follows: the union of two ``SomeInstance`` +annotations is the ``SomeInstance`` of the most precise common base +class. If an attribute is considered (i.e. read or written) through a +``SomeInstance`` of a parent class, then we assume that all subclasses +also have the same attribute, and that the same annotation applies to +them all (so code like ``return self.x`` in a method of a parent class +forces the parent class and all its subclasses to have an attribute +``x``, whose annotation is general enough to contain all the values that +all the subclasses might want to store in ``x``). However, distinct +subclasses can have attributes of the same names with different, +unrelated annotations if they are not used in a general way through the parent class. @@ -443,24 +443,24 @@ Overview -------- -The RPython Typer is the bridge between the Annotator_ and the low-level code -generators. The annotator computes types (or "annotations") that are -high-level, in the sense that they describe RPython types like lists or -instances of user-defined classes. In general, though, to emit code we need -to represent these high-level annotations into the low-level model of the -target language; for C, this means structures and pointers and arrays. The -Typer both determines the appropriate low-level type for each annotation, and -tries to replace *all* operations in the control flow graphs with one or a few -low-level operations. Just like low-level types, there is only a fairly -restricted set of low-level operations, along the lines of reading or writing +The RPython Typer is the bridge between the Annotator_ and the low-level code +generators. The annotator computes types (or "annotations") that are +high-level, in the sense that they describe RPython types like lists or +instances of user-defined classes. In general, though, to emit code we need +to represent these high-level annotations into the low-level model of the +target language; for C, this means structures and pointers and arrays. The +Typer both determines the appropriate low-level type for each annotation, and +tries to replace *all* operations in the control flow graphs with one or a few +low-level operations. Just like low-level types, there is only a fairly +restricted set of low-level operations, along the lines of reading or writing from or to a field of a structure. -In theory, this step is optional; some code generators might be able to read -directly the high-level types. However, we expect that case to be the -exception. "Compiling" high-level types into low-level ones is rather more -messy than one would expect. This was the motivation for making this step -explicit and isolated in a single place. After Typing, the graphs can only -contain very few operations, which makes the job of the code generators much +In theory, this step is optional; some code generators might be able to read +directly the high-level types. However, we expect that case to be the +exception. "Compiling" high-level types into low-level ones is rather more +messy than one would expect. This was the motivation for making this step +explicit and isolated in a single place. After Typing, the graphs can only +contain very few operations, which makes the job of the code generators much simpler. @@ -481,77 +481,77 @@ v3 = int_add(v1, v2) -where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. -This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 -(which might be instances of Variable or possibly Constant). In our model, -this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the -purpose of replacing the operation called ``add`` with ``int_add`` is that -code generators no longer have to worry about what kind of addition (or +where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. +This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 +(which might be instances of Variable or possibly Constant). In our model, +this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the +purpose of replacing the operation called ``add`` with ``int_add`` is that +code generators no longer have to worry about what kind of addition (or concatenation maybe?) it means. The process in more details --------------------------- -The RPython Typer has a structure similar to that of the Annotator_: both -consider each block of the flow graphs in turn, and perform some analysis on -each operation. In both cases the analysis of an operation depends on the -annotations of its input arguments. This is reflected in the usage of the same -``__extend__`` syntax in the source files (compare e.g. +The RPython Typer has a structure similar to that of the Annotator_: both +consider each block of the flow graphs in turn, and perform some analysis on +each operation. In both cases the analysis of an operation depends on the +annotations of its input arguments. This is reflected in the usage of the same +``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rint.py`_). -The analogy stops here, though: while it runs, the Annotator is in the middle -of computing the annotations, so it might need to reflow and generalize until -a fixpoint is reached. The Typer, by contrast, works on the final annotations -that the Annotator computed, without changing them, assuming that they are -globally consistent. There is no need to reflow: the Typer considers each -block only once. And unlike the Annotator, the Typer completely modifies the +The analogy stops here, though: while it runs, the Annotator is in the middle +of computing the annotations, so it might need to reflow and generalize until +a fixpoint is reached. The Typer, by contrast, works on the final annotations +that the Annotator computed, without changing them, assuming that they are +globally consistent. There is no need to reflow: the Typer considers each +block only once. And unlike the Annotator, the Typer completely modifies the flow graph, by replacing each operation with some low-level operations. -In addition to replacing operations, the RTyper creates a ``concretetype`` -attribute on all Variables and Constants in the flow graphs, which tells code -generators which type to use for each of them. This attribute is a +In addition to replacing operations, the RTyper creates a ``concretetype`` +attribute on all Variables and Constants in the flow graphs, which tells code +generators which type to use for each of them. This attribute is a `low-level type`_, as described below. Representations --------------- -Representations -- the Repr classes -- are the most important internal classes -used by the RTyper. (They are internal in the sense that they are an -"implementation detail" and their instances just go away after the RTyper is -finished; the code generators should only use the ``concretetype`` attributes, +Representations -- the Repr classes -- are the most important internal classes +used by the RTyper. (They are internal in the sense that they are an +"implementation detail" and their instances just go away after the RTyper is +finished; the code generators should only use the ``concretetype`` attributes, which are not Repr instances but `low-level types`_.) -A representation contains all the logic about mapping a specific SomeXxx() -annotation to a specific low-level type. For the time being, the RTyper -assumes that each SomeXxx() instance needs only one "canonical" representation. -For example, all variables annotated with SomeInteger() will correspond to the -``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, -variables annotated SomeList() can correspond either to a structure holding an -array of items of the correct type, or -- if the list in question is just a +A representation contains all the logic about mapping a specific SomeXxx() +annotation to a specific low-level type. For the time being, the RTyper +assumes that each SomeXxx() instance needs only one "canonical" representation. +For example, all variables annotated with SomeInteger() will correspond to the +``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, +variables annotated SomeList() can correspond either to a structure holding an +array of items of the correct type, or -- if the list in question is just a range() with a constant step -- a structure with just start and stop fields. -This example shows that two representations may need very different low-level -implementations for the same high-level operations. This is the reason for +This example shows that two representations may need very different low-level +implementations for the same high-level operations. This is the reason for turning representations into explicit objects. -The base Repr class is defined in `rpython/rmodel.py`_. Most of the -``rpython/r*.py`` files define one or a few subclasses of Repr. The method -getrepr() of the RTyper will build and cache a single Repr instance per -SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the +The base Repr class is defined in `rpython/rmodel.py`_. Most of the +``rpython/r*.py`` files define one or a few subclasses of Repr. The method +getrepr() of the RTyper will build and cache a single Repr instance per +SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the same Repr instance. -The key attribute of a Repr instance is called ``lowleveltype``, which is what -gets copied into the attribute ``concretetype`` of the Variables that have been -given this representation. The RTyper also computes a ``concretetype`` for -Constants, to match the way they are used in the low-level operations (for -example, ``int_add(x, 1)`` requires a ``Constant(1)`` with -``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a +The key attribute of a Repr instance is called ``lowleveltype``, which is what +gets copied into the attribute ``concretetype`` of the Variables that have been +given this representation. The RTyper also computes a ``concretetype`` for +Constants, to match the way they are used in the low-level operations (for +example, ``int_add(x, 1)`` requires a ``Constant(1)`` with +``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time). -In addition to ``lowleveltype``, each Repr subclass provides a set of methods -called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` +In addition to ``lowleveltype``, each Repr subclass provides a set of methods +called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` is turned into low-level operations. @@ -560,29 +560,29 @@ Low-Level Types --------------- -The RPython Typer uses a standard low-level model which we believe can -correspond rather directly to various target languages from C to LLVM to Java. +The RPython Typer uses a standard low-level model which we believe can +correspond rather directly to various target languages from C to LLVM to Java. This model is implemented in the first part of `rpython/lltype.py`_. -The second part of `rpython/lltype.py`_ is a runnable implementation of these -types, for testing purposes. It allows us to write and test plain Python code -using a malloc() function to obtain and manipulate structures and arrays. -This is useful for example to implement and test RPython types like 'list' with +The second part of `rpython/lltype.py`_ is a runnable implementation of these +types, for testing purposes. It allows us to write and test plain Python code +using a malloc() function to obtain and manipulate structures and arrays. +This is useful for example to implement and test RPython types like 'list' with its operations and methods. -The basic assumption is that Variables (i.e. local variables and function -arguments and return value) all contain "simple" values: basically, just -integers or pointers. All the "container" data structures (struct and array) -are allocated in the heap, and they are always manipulated via pointers. +The basic assumption is that Variables (i.e. local variables and function +arguments and return value) all contain "simple" values: basically, just +integers or pointers. All the "container" data structures (struct and array) +are allocated in the heap, and they are always manipulated via pointers. (There is no equivalent to the C notion of local variable of a ``struct`` type.) -Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you -have some older version, the ``lltype`` module might be called ``lltypes`` and +Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you +have some older version, the ``lltype`` module might be called ``lltypes`` and you may need to add or remove a few ``Gc`` prefixes here and there):: >>> from pypy.rpython.lltype import * -Here are a few primitive low-level types, and the typeOf() function to figure +Here are a few primitive low-level types, and the typeOf() function to figure them out:: >>> Signed @@ -594,19 +594,19 @@ >>> typeOf('x') -Let's say that we want to build a type "point", which is a structure with two +Let's say that we want to build a type "point", which is a structure with two integer fields "x" and "y":: >>> POINT = GcStruct('point', ('x', Signed), ('y', Signed)) >>> POINT -The structure is a ``GcStruct``, which means a structure that can be allocated -in the heap and eventually freed by some garbage collector. (For platforms -where we use reference counting, think about ``GcStruct`` as a struct with an +The structure is a ``GcStruct``, which means a structure that can be allocated +in the heap and eventually freed by some garbage collector. (For platforms +where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.) -Giving a name ('point') to the GcStruct is only for clarity: it is used in the +Giving a name ('point') to the GcStruct is only for clarity: it is used in the representation. >>> p = malloc(POINT) @@ -618,22 +618,22 @@ >>> p -``malloc()`` allocates a structure from the heap, initalizes it to 0 -(currently), and returns a pointer to it. The point of all this is to work with -a very limited, easily controllable set of types, and define implementations of -types like list in this elementary world. The ``malloc()`` function is a kind -of placeholder, which must eventually be provided by the code generator for the +``malloc()`` allocates a structure from the heap, initalizes it to 0 +(currently), and returns a pointer to it. The point of all this is to work with +a very limited, easily controllable set of types, and define implementations of +types like list in this elementary world. The ``malloc()`` function is a kind +of placeholder, which must eventually be provided by the code generator for the target platform; but as we have just seen its Python implementation in ` -rpython/lltype.py`_ works too, which is primarily useful for testing, +rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc. -The argument to ``malloc()`` is the structure type directly, but it returns a +The argument to ``malloc()`` is the structure type directly, but it returns a pointer to the structure, as ``typeOf()`` tells you:: >>> typeOf(p) -For the purpose of creating structures with pointers to other structures, we can +For the purpose of creating structures with pointers to other structures, we can declare pointer types explicitely:: >>> typeOf(p) == Ptr(POINT) @@ -647,7 +647,7 @@ >>> b.p2.y 42 -The world of low-level types is more complicated than integers and GcStructs, +The world of low-level types is more complicated than integers and GcStructs, though. The next pages are a reference guide. @@ -682,26 +682,26 @@ MyStructType = Struct('somename', ('field1', Type1), ('field2', Type2)...) MyStructType = GcStruct('somename', ('field1', Type1), ('field2', Type2)...) -This declares a structure (or a Pascal ``record``) containing the specified -named fields with the given types. The field names cannot start with an -underscore. As noted above, you cannot directly manipulate structure objects, +This declares a structure (or a Pascal ``record``) containing the specified +named fields with the given types. The field names cannot start with an +underscore. As noted above, you cannot directly manipulate structure objects, but only pointer to structures living in the heap. -By contrast, the fields themselves can be of primitive, pointer or container -type. When a structure contains another structure as a field we say that the -latter is "inlined" in the former: the bigger structure contains the smaller one +By contrast, the fields themselves can be of primitive, pointer or container +type. When a structure contains another structure as a field we say that the +latter is "inlined" in the former: the bigger structure contains the smaller one as part of its memory layout. -A structure can also contain an inlined array (see below), but only as its last -field: in this case it is a "variable-sized" structure, whose memory layout -starts with the non-variable fields and ends with a variable number of array -items. This number is determined when a structure is allocated in the heap. +A structure can also contain an inlined array (see below), but only as its last +field: in this case it is a "variable-sized" structure, whose memory layout +starts with the non-variable fields and ends with a variable number of array +items. This number is determined when a structure is allocated in the heap. Variable-sized structures cannot be inlined in other structures. -GcStructs have a platform-specific GC header (e.g. a reference counter); only -these can be dynamically malloc()ed. The non-GC version of Struct does not have -any header, and is suitable for being embedded ("inlined") inside other -structures. As an exception, a GcStruct can be embedded as the first field of a +GcStructs have a platform-specific GC header (e.g. a reference counter); only +these can be dynamically malloc()ed. The non-GC version of Struct does not have +any header, and is suitable for being embedded ("inlined") inside other +structures. As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure. @@ -718,47 +718,47 @@ MyArrayType = Array(('field1', Type1), ('field2', Type2)...) -You can build arrays whose items are either primitive or pointer types, or +You can build arrays whose items are either primitive or pointer types, or (non-GC non-varsize) structures. -GcArrays can be malloc()ed. The length must be specified when malloc() is -called, and arrays cannot be resized; this length is stored explicitely in a +GcArrays can be malloc()ed. The length must be specified when malloc() is +called, and arrays cannot be resized; this length is stored explicitely in a header. -The non-GC version of Array can be used as the last field of a structure, to -make a variable-sized structure. The whole structure can then be malloc()ed, +The non-GC version of Array can be used as the last field of a structure, to +make a variable-sized structure. The whole structure can then be malloc()ed, and the length of the array is specified at this time. Pointer Types +++++++++++++ -As in C, pointers provide the indirection needed to make a reference modifiable -or sharable. Pointers can only point to a structure, an array, a function -(see below) or a PyObject (see below). Pointers to primitive types, if needed, -must be done by pointing to a structure with a single field of the required +As in C, pointers provide the indirection needed to make a reference modifiable +or sharable. Pointers can only point to a structure, an array, a function +(see below) or a PyObject (see below). Pointers to primitive types, if needed, +must be done by pointing to a structure with a single field of the required type. Pointer types are declared by:: Ptr(TYPE) -At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a -reference to what they are pointing to. Pointers to non-GC structures that can -go away when their container is deallocated (Struct, Array) must be handled -with care: the bigger structure of which they are part of could be freed while -the Ptr to the substructure is still in use. In general, it is a good idea to -avoid passing around pointers to inlined substructures of malloc()ed structures. -(The testing implementation of `rpython/lltype.py`_ checks to some extend that -you are not trying to use a pointer to a structure after its container has been -freed, using weak references. But pointers to non-GC structures are not -officially meant to be weak references: using them after what they point to has +At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a +reference to what they are pointing to. Pointers to non-GC structures that can +go away when their container is deallocated (Struct, Array) must be handled +with care: the bigger structure of which they are part of could be freed while +the Ptr to the substructure is still in use. In general, it is a good idea to +avoid passing around pointers to inlined substructures of malloc()ed structures. +(The testing implementation of `rpython/lltype.py`_ checks to some extend that +you are not trying to use a pointer to a structure after its container has been +freed, using weak references. But pointers to non-GC structures are not +officially meant to be weak references: using them after what they point to has been freed just crashes.) -The malloc() operation allocates and returns a Ptr to a new GC structure or -array. In a refcounting implementation, malloc() would allocate enough space -for a reference counter before the actual structure, and initialize it to 1. -Note that the testing implementation also allows malloc() to allocate a non-GC -structure or array with a keyword argument ``immortal=True``. Its purpose is to -declare and initialize prebuilt data structures which the code generators will +The malloc() operation allocates and returns a Ptr to a new GC structure or +array. In a refcounting implementation, malloc() would allocate enough space +for a reference counter before the actual structure, and initialize it to 1. +Note that the testing implementation also allows malloc() to allocate a non-GC +structure or array with a keyword argument ``immortal=True``. Its purpose is to +declare and initialize prebuilt data structures which the code generators will turn into static immortal non-GC'ed data. @@ -769,15 +769,15 @@ MyFuncType = FuncType([Type1, Type2, ...], ResultType) -declares a function type taking arguments of the given types and returning a -result of the given type. All these types must be primitives or pointers. The -function type itself is considered to be a "container" type: if you wish, a -function contains the bytes that make up its executable code. As with +declares a function type taking arguments of the given types and returning a +result of the given type. All these types must be primitives or pointers. The +function type itself is considered to be a "container" type: if you wish, a +function contains the bytes that make up its executable code. As with structures and arrays, they can only be manipulated through pointers. -The testing implementation allows you to "create" functions by calling -``functionptr(TYPE, name, **attrs)``. The extra attributes describe the -function in a way that isn't fully specified now, but the following attributes +The testing implementation allows you to "create" functions by calling +``functionptr(TYPE, name, **attrs)``. The extra attributes describe the +function in a way that isn't fully specified now, but the following attributes *might* be present: :_callable: a Python callable, typically a function object. @@ -787,16 +787,16 @@ The PyObject Type +++++++++++++++++ -This is a special type, for compatibility with CPython: it stands for a -structure compatible with PyObject. This is also a "container" type (thinking -about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated -via a Ptr. A typed graph can still contain generic space operations (add, -getitem, etc.) provided they are applied on objects whose low-level type is -``Ptr(PyObject)``. In fact, code generators that support this should consider -that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. +This is a special type, for compatibility with CPython: it stands for a +structure compatible with PyObject. This is also a "container" type (thinking +about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated +via a Ptr. A typed graph can still contain generic space operations (add, +getitem, etc.) provided they are applied on objects whose low-level type is +``Ptr(PyObject)``. In fact, code generators that support this should consider +that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. In this way, they can generate the correct code for fully-untyped flow graphs. -The testing implementation allows you to "create" PyObjects by calling +The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``. @@ -813,21 +813,21 @@ Implementing RPython types -------------------------- -As hinted above, the RPython types (e.g. 'list') are implemented in some -"restricted-restricted Python" format by manipulating only low-level types, as -provided by the testing implementation of malloc() and friends. What occurs -then is that the same (tested!) very-low-level Python code -- which looks really -just like C -- is then transformed into a flow graph and integrated with the -rest of the user program. In other words, we replace an operation like ``add`` -between two variables annotated as SomeList, with a ``direct_call`` operation +As hinted above, the RPython types (e.g. 'list') are implemented in some +"restricted-restricted Python" format by manipulating only low-level types, as +provided by the testing implementation of malloc() and friends. What occurs +then is that the same (tested!) very-low-level Python code -- which looks really +just like C -- is then transformed into a flow graph and integrated with the +rest of the user program. In other words, we replace an operation like ``add`` +between two variables annotated as SomeList, with a ``direct_call`` operation invoking this very-low-level list concatenation. -This list concatenation flow graph is then annotated as usual, with one -difference: the annotator has to be taught about malloc() and the way the -pointer thus obtained can be manipulated. This generates a flow graph which is -hopefully completely annotated with SomePtr() annotation. Introduced just for -this case, SomePtr maps directly to a low-level pointer type. This is the only -change needed to the Annotator to allow it to perform type inference of our +This list concatenation flow graph is then annotated as usual, with one +difference: the annotator has to be taught about malloc() and the way the +pointer thus obtained can be manipulated. This generates a flow graph which is +hopefully completely annotated with SomePtr() annotation. Introduced just for +this case, SomePtr maps directly to a low-level pointer type. This is the only +change needed to the Annotator to allow it to perform type inference of our very-low-level snippets of code. See for example `rpython/rlist.py`_. @@ -846,15 +846,15 @@ Overview -------- -The task of GenC is to convert a flow graph into C code. By itself, GenC does -not use the annotations in the graph. It can actually convert unannotated -graphs to C. However, to make use of the annotations if they are present, an -extra pass is needed: the `RPython Typer`_, whose task is to modify the flow -graph according to the annotations, replacing operations with lower-level C-ish +The task of GenC is to convert a flow graph into C code. By itself, GenC does +not use the annotations in the graph. It can actually convert unannotated +graphs to C. However, to make use of the annotations if they are present, an +extra pass is needed: the `RPython Typer`_, whose task is to modify the flow +graph according to the annotations, replacing operations with lower-level C-ish equivalents. -XXX GenC is currently in the process of being updated to use the RPython Typer. -More documentation needed when this is done. But the basic principle of creating +XXX GenC is currently in the process of being updated to use the RPython Typer. +More documentation needed when this is done. But the basic principle of creating code from flowgraphs is similar to the `Python back-end`_. @@ -903,7 +903,7 @@ generates LLVM code that allocates enough memory for an instance of the class and then (if the class or a base class has an ``__init__`` method) tells the ``FuncRepr`` of the appropriate ``__init__`` method to generate the code for -the call to it. +the call to it. Every representation object has some other representations it depends on: A ``ListRepr`` of lists instances of a class depends on the ``ClassRepr`` of @@ -1000,10 +1000,10 @@ Motivation ---------- -PyPy often makes use of `application-level`_ helper methods. -The idea of the 'geninterplevel' backend is to automatically transform -such application level implementations to their equivalent representation -at interpreter level. Then, the RPython to C translation hopefully can +PyPy often makes use of `application-level`_ helper methods. +The idea of the 'geninterplevel' backend is to automatically transform +such application level implementations to their equivalent representation +at interpreter level. Then, the RPython to C translation hopefully can produce more efficient code than always re-interpreting these methods. One property of translation from application level Python to @@ -1040,26 +1040,26 @@ .. _implementation: http://codespeak.net/svn/pypy/dist/pypy/translator/geninterplevel.py -Let's try the little example from above_. You might want to look at the -flowgraph that it produces. Here, we directly run the Python translation -and look at the generated source. See also the header section of the implementation_ +Let's try the little example from above_. You might want to look at the +flowgraph that it produces. Here, we directly run the Python translation +and look at the generated source. See also the header section of the implementation_ for the interface:: >>> from pypy.translator.geninterplevel import translate_as_module >>> entrypoint, source = translate_as_module(""" - ... + ... ... def g(n): ... i = 0 ... while n: ... i = i + n ... n = n - 1 ... return i - ... + ... ... """) - + This call has invoked a PyPy interpreter running on FlowObjspace, recorded every possible codepath into a flowgraph, and then rendered the following source code:: - + >>> print source #!/bin/env python # -*- coding: LATIN-1 -*- Modified: pypy/dist/pypy/interpreter/function.py ============================================================================== --- pypy/dist/pypy/interpreter/function.py (original) +++ pypy/dist/pypy/interpreter/function.py Fri Jul 1 15:26:05 2005 @@ -16,7 +16,7 @@ """A function is a code object captured with some environment: an object space, a dictionary of globals, default arguments, and an arbitrary 'closure' passed to the code object.""" - + def __init__(self, space, code, w_globals=None, defs_w=[], closure=None, forcename=None): self.space = space self.name = forcename or code.co_name @@ -76,7 +76,7 @@ if not isinstance(code, PyCode) or len(code.co_freevars) == 0: raise OperationError(space.w_ValueError, space.wrap("no closure needed")) elif len(code.co_freevars) != n: - raise OperationError(space.w_ValueError, space.wrap("closure is wrong size")) + raise OperationError(space.w_ValueError, space.wrap("closure is wrong size")) closure = [] for w_cell in closure_w: cell = space.interpclass_w(w_cell) @@ -98,7 +98,7 @@ if not values_w: return space.w_None return space.newtuple(values_w) - + def fset_func_defaults(space, self, w_defaults): if not space.is_true( space.isinstance( w_defaults, space.w_tuple ) ): raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object") ) @@ -125,10 +125,10 @@ else: self.w_module = space.w_None return self.w_module - + def fset___module__(space, self, w_module): self.w_module = w_module - + def fdel___module__(space, self): self.w_module = space.w_None @@ -140,7 +140,7 @@ if not isinstance(code, Code ): raise OperationError( space.w_TypeError, space.wrap("func_code must be set to a code object") ) self.code = code - + def fget_func_closure(space, self): if self.closure is not None: w_res = space.newtuple( [ space.wrap(i) for i in self.closure ] ) @@ -171,7 +171,7 @@ return space.type(w_obj) raise -class Method(Wrappable): +class Method(Wrappable): """A method is a function bound to a specific instance or class.""" def __init__(self, space, w_function, w_instance, w_class): @@ -179,7 +179,7 @@ self.w_function = w_function self.w_instance = w_instance # or None self.w_class = w_class # possibly space.w_None - + def descr_method__new__(space, w_subtype, w_function, w_instance, w_class=None): if space.is_w( w_instance, space.w_None ): w_instance = None @@ -218,7 +218,7 @@ instname += " " instdescr = "%sinstance" %instname msg = ("unbound method %s() must be called with %s" - "instance as first argument (got %s instead)") % (myname, clsdescr, instdescr) + "instance as first argument (got %s instead)") % (myname, clsdescr, instdescr) raise OperationError(space.w_TypeError, space.wrap(msg)) return space.call_args(self.w_function, args) @@ -241,17 +241,17 @@ def descr_method_call(self, __args__): return self.call_args(__args__) - def descr_method_repr(self): + def descr_method_repr(self): space = self.space name = self.w_function.getname(self.space, '?') - # XXX do we handle all cases sanely here? - if space.is_w(self.w_class, space.w_None): - w_class = space.type(self.w_instance) - else: - w_class = self.w_class + # XXX do we handle all cases sanely here? + if space.is_w(self.w_class, space.w_None): + w_class = space.type(self.w_instance) + else: + w_class = self.w_class typename = w_class.getname(self.space, '?') - if self.w_instance is None: - s = "" %(name, typename) + if self.w_instance is None: + s = "" %(name, typename) return space.wrap(s) else: info = "method %s of %s object" % (name, typename) From ac at codespeak.net Fri Jul 1 17:20:53 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 1 Jul 2005 17:20:53 +0200 (CEST) Subject: [pypy-svn] r14032 - pypy/dist/pypy/objspace/std Message-ID: <20050701152053.E238027B51@code1.codespeak.net> Author: ac Date: Fri Jul 1 17:20:53 2005 New Revision: 14032 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Do not special case buffer objects to work with faked codec module. Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Fri Jul 1 17:20:53 2005 @@ -46,9 +46,6 @@ import codecs, sys def unicode_from_encoded_object(obj, encoding, errors): - # Fix later for buffer - if type(obj).__name__ == 'buffer': - obj = str(obj) if encoding is None: encoding = sys.getdefaultencoding() decoder = codecs.getdecoder(encoding) From arigo at codespeak.net Fri Jul 1 17:31:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 17:31:05 +0200 (CEST) Subject: [pypy-svn] r14033 - pypy/branch/dist-2.4.1 Message-ID: <20050701153105.ADB4F27B51@code1.codespeak.net> Author: arigo Date: Fri Jul 1 17:31:03 2005 New Revision: 14033 Added: pypy/branch/dist-2.4.1/ - copied from r14032, pypy/dist/ Log: Create the branch for experimenting with a 2.4-emulating version of PyPy. From arigo at codespeak.net Fri Jul 1 17:33:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 17:33:37 +0200 (CEST) Subject: [pypy-svn] r14034 - pypy/branch/dist-2.4.1/lib-python/2.4.1 Message-ID: <20050701153337.9493B27B51@code1.codespeak.net> Author: arigo Date: Fri Jul 1 17:33:34 2005 New Revision: 14034 Added: pypy/branch/dist-2.4.1/lib-python/2.4.1/ - copied from r14033, vendor/cpython/Python-r241/dist/src/Lib/ Log: Copied the Lib of Python 2.4.1 into the PyPy branch. From gintas at codespeak.net Fri Jul 1 17:35:03 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 17:35:03 +0200 (CEST) Subject: [pypy-svn] r14035 - pypy/dist/pypy/documentation Message-ID: <20050701153503.59DB827B51@code1.codespeak.net> Author: gintas Date: Fri Jul 1 17:35:03 2005 New Revision: 14035 Modified: pypy/dist/pypy/documentation/architecture.txt pypy/dist/pypy/documentation/objspace.txt Log: Fixed typos. Modified: pypy/dist/pypy/documentation/architecture.txt ============================================================================== --- pypy/dist/pypy/documentation/architecture.txt (original) +++ pypy/dist/pypy/documentation/architecture.txt Fri Jul 1 17:35:03 2005 @@ -105,7 +105,7 @@ Please note that we are using the term *interpreter* most often in reference to the *plain interpreter* which just knows enough to read, dispatch and implement *bytecodes* thus shuffling objects around on the -stack and between namespaces. The (plain) interpreter is completly +stack and between namespaces. The (plain) interpreter is completely ignorant of how to access, modify or construct objects and their structure and thus delegates such operations to a so called `Object Space`_. Modified: pypy/dist/pypy/documentation/objspace.txt ============================================================================== --- pypy/dist/pypy/documentation/objspace.txt (original) +++ pypy/dist/pypy/documentation/objspace.txt Fri Jul 1 17:35:03 2005 @@ -354,7 +354,7 @@ :args: list of arguments. Each one is a Constant or a Variable seen previously in the basic block. :result: a *new* Variable into which the result is to be stored. - Note that operations usually cannot implicitely raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. + Note that operations usually cannot implicitly raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. Variable From hpk at codespeak.net Fri Jul 1 17:43:56 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 1 Jul 2005 17:43:56 +0200 (CEST) Subject: [pypy-svn] r14036 - pypy/extradoc/sprintinfo Message-ID: <20050701154356.1DE1427B4D@code1.codespeak.net> Author: hpk Date: Fri Jul 1 17:43:54 2005 New Revision: 14036 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: work planning at the beginning of post-ep sprint Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Fri Jul 1 17:43:54 2005 @@ -6,20 +6,30 @@ 1st-3rd July (both including) we sprint at Chalmers from 10am-open - 4th first half is "break" time, afternoon 3pm is meeting time at - LAURA's house (not chalmers anymore) on G?tabergsgatan 22. + 4th July is "break" time, afternoon visiting sites together? + + 5th July sprint from 10am-open at Laura's house + (Goetabergsgatan 22) + -7th sprint continues from 10am-open at laura's house + +3rd July evening: Going to Hitchhikers Guide? + - 5th-7th sprint continues from 10am-open at laura's house 1st July start at 10am:: - holger starts the session - introduction to PyPy high level architecture (Armin or Holger?) + - introduction to Annotation + RTyping? (Samuele or Armin) working on examples + - introduction to LLVM2 + status Carl, holger + + - status of Parser efforts + - introduction to GenC + status Armin @@ -29,21 +39,40 @@ we decide about pairing at the venue (after everybody tells what he/she is interested in). These are the people expected currently:: - Armin Rigo - Samuele Pedroni - Niklaus Haldimann - Carl Friedrich Bolz - Eric van Riet Paap - Holger Krekel - Richard Emslie - Bert Freudenberg - Adrien Di Mascio - Ludovic Aubry - Anders Chrigstroem - Christian Tismer - Jacob Hallen - Laura Creighton - Beatrice Duering + + Gustavo Niemeyer until 2nd (including) + Adrien Di Mascio until 4th (including) + + Eric van Riet Paap until 8th + Carl Friedrich Bolz until 5th afternoon + Richard Emslie whole-time + + Gintas M. until 2nd (including) + Marius Gedminas until 2nd (including) + Mikael Jansson until 3rd (probably) + + Armin Rigo whole-time + Niklaus Haldimann until 4th (including) + Ludovic Aubry until 4th (including) + Anders Chrigstroem whole-time (likely) + Anders Qvist whole-time (likely) + Ignas M. until 2nd (including) + + Bert Freudenberg whole-time + Holger Krekel whole-time + + Jacob Hallen whole-time + Christian Tismer whole-time + + Laura Creighton whole-time + + Samuele Pedroni whole-time + + + Beatrice Duering (visiting, 5th-) + Rob Collins until 2nd afternoon + #Joe Wrigley until 2nd morning + Volker Gietz 2nd only Translation tasks @@ -87,9 +116,14 @@ - objspace/std/floatobject.py needs some clean-ups: look for XXX, for %reimplement% and for all try:except: blocks. + Move to Python 2.4.1 ----------------------- +subcoach: Armin +Niklaus, Gintas, Ignas, Arre, Anders, Mikael + + experiment in a branch with using Python 2.4 semantics and the standard library @@ -115,19 +149,27 @@ * (hard) find a way to generate c_api calls with automated conversions from ll-strings to c-like strings -* fix Windows-related issues, '%'-formatting rounding errors, - add missing docstrings on app-level built-in types and functions, +* fix Windows-related issues + +* '%'-formatting rounding errors ( '%.3f' % (2.999999,)) + +* add missing docstrings on app-level built-in types and functions, etc. -* GC discussion in the middle of the sprint (kickoff Carl Friedrich) +* GC discussion in the middle of the sprint (kickoff Carl Friedrich) + 3rd Rewriting important C functionality in Python -------------------------------------------------- -* integrate the parser module, trying to make it RPython - conformant; +* parsing/compiling (Adrien, Gustavo) -* re module reimplementation kickoff + * translate to C (fix annotation problems by either + tweaking the code or extending the annotator on + a case-by-case basis) + * move towards a rpython compliant (translatable) compiler + +* _sre module reimplementation kickoff * rewrite in Python a C module you are familiar with (partial list of missing/incomplete modules: os, math, array, @@ -135,6 +177,18 @@ * implement Python 2.3's import hook extensions (zip-imports etc.) -* weakrefs (but this requires discussion and planning on pypy-dev +* (hard) weakrefs (but this requires discussion and planning on pypy-dev before the sprint! feel free to start such a discussion, though.) + +LLVM Backend +------------------- + +- implement variable sized structs (Richard, Eric / Carl) + +- support function pointers + +- implement exceptions (Carl, Ludovic) + +- try to integrate Boehm GC + From arigo at codespeak.net Fri Jul 1 17:49:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 17:49:01 +0200 (CEST) Subject: [pypy-svn] r14037 - in pypy/branch/dist-2.4.1: lib-python/modified-2.4.1 pypy/module/sys Message-ID: <20050701154901.9D28427B51@code1.codespeak.net> Author: arigo Date: Fri Jul 1 17:48:56 2005 New Revision: 14037 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/ Modified: pypy/branch/dist-2.4.1/pypy/module/sys/__init__.py pypy/branch/dist-2.4.1/pypy/module/sys/state.py Log: Working on the 2.4.1 port. Modified: pypy/branch/dist-2.4.1/pypy/module/sys/__init__.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/sys/__init__.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/sys/__init__.py Fri Jul 1 17:48:56 2005 @@ -51,9 +51,9 @@ 'executable' : 'space.wrap("py.py")', 'copyright' : 'space.wrap("MIT-License")', 'api_version' : 'space.wrap(1012)', - 'version_info' : 'space.wrap((2,3,4, "alpha", 42))', - 'version' : 'space.wrap("2.3.4 (pypy1 build)")', - 'hexversion' : 'space.wrap(0x020304a0)', + 'version_info' : 'space.wrap((2,4,1, "alpha", 42))', + 'version' : 'space.wrap("2.4.1 (pypy1 build)")', + 'hexversion' : 'space.wrap(0x020401a0)', 'ps1' : 'space.wrap(">>>>")', 'ps2' : 'space.wrap("....")', Modified: pypy/branch/dist-2.4.1/pypy/module/sys/state.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/sys/state.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/sys/state.py Fri Jul 1 17:48:56 2005 @@ -59,9 +59,9 @@ from pypy.interpreter import autopath srcdir = os.path.dirname(autopath.pypydir) python_std_lib = os.path.normpath( - os.path.join(autopath.pypydir, os.pardir,'lib-python', '2.3.4')) + os.path.join(autopath.pypydir, os.pardir,'lib-python', '2.4.1')) python_std_lib_modified = os.path.normpath( - os.path.join(autopath.pypydir, os.pardir,'lib-python', 'modified-2.3.4')) + os.path.join(autopath.pypydir, os.pardir,'lib-python', 'modified-2.4.1')) pypy_lib = os.path.join(autopath.pypydir, 'lib') assert os.path.exists(python_std_lib) From arigo at codespeak.net Fri Jul 1 17:52:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 17:52:46 +0200 (CEST) Subject: [pypy-svn] r14038 - pypy/branch/dist-2.4.1/pypy/tool/pytest Message-ID: <20050701155246.D592627B51@code1.codespeak.net> Author: arigo Date: Fri Jul 1 17:52:45 2005 New Revision: 14038 Modified: pypy/branch/dist-2.4.1/pypy/tool/pytest/confpath.py Log: Forgot some '2.3.4' around. Modified: pypy/branch/dist-2.4.1/pypy/tool/pytest/confpath.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/tool/pytest/confpath.py (original) +++ pypy/branch/dist-2.4.1/pypy/tool/pytest/confpath.py Fri Jul 1 17:52:45 2005 @@ -7,5 +7,5 @@ testresultdir = distdir.join('testresult') assert pypydir.check(dir=1) libpythondir = distdir.join('lib-python') -regrtestdir = libpythondir.join('2.3.4', 'test') -modregrtestdir = libpythondir.join('modified-2.3.4', 'test') +regrtestdir = libpythondir.join('2.4.1', 'test') +modregrtestdir = libpythondir.join('modified-2.4.1', 'test') From gintas at codespeak.net Fri Jul 1 18:04:32 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 18:04:32 +0200 (CEST) Subject: [pypy-svn] r14039 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1 Message-ID: <20050701160432.48AFE27B51@code1.codespeak.net> Author: gintas Date: Fri Jul 1 18:04:31 2005 New Revision: 14039 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/types.py - copied, changed from r14038, pypy/branch/dist-2.4.1/lib-python/2.4.1/types.py Log: Added an override for types.py. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/types.py (from r14038, pypy/branch/dist-2.4.1/lib-python/2.4.1/types.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/types.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/types.py Fri Jul 1 18:04:31 2005 @@ -54,10 +54,10 @@ class _C: def _m(self): pass -ClassType = type(_C) +ClassType = _classobj # PyPy-specific, from __builtin__ UnboundMethodType = type(_C._m) # Same as MethodType _x = _C() -InstanceType = type(_x) +InstanceType = _instance # PyPy-specific, from __builtin__ MethodType = type(_x._m) BuiltinFunctionType = type(len) From adim at codespeak.net Fri Jul 1 18:24:51 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 18:24:51 +0200 (CEST) Subject: [pypy-svn] r14040 - pypy/dist/pypy/translator/goal Message-ID: <20050701162451.48D5727B51@code1.codespeak.net> Author: adim Date: Fri Jul 1 18:24:50 2005 New Revision: 14040 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: added an option to avoid redirection to translation-snapshot directory Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jul 1 18:24:50 2005 @@ -25,6 +25,8 @@ -no-d Disable recording of debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed + -no-snapshot + Don't redirect imports to the translation snapshot -save filename saves the translator to a file. The file type can either be .py or .zip (recommended). @@ -34,32 +36,33 @@ """ import autopath, sys, os -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -basedir = autopath.this_dir +if '-no-snapshot' not in sys.argv: + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + basedir = autopath.this_dir -pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') + pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') -if not os.path.isdir(pypy_translation_snapshot_dir): - print """ -Translation is performed on a specific revision of PyPy which lives on -a branch. This needs to be checked out into translator/goal with: + if not os.path.isdir(pypy_translation_snapshot_dir): + print """ + Translation is performed on a specific revision of PyPy which lives on + a branch. This needs to be checked out into translator/goal with: -svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot -"""[1:] - sys.exit(2) + svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot + """[1:] + sys.exit(2) -# override imports from pypy head with imports from pypy-translation-snapshot -import pypy -pypy.__path__.insert(0, pypy_translation_snapshot_dir) + # override imports from pypy head with imports from pypy-translation-snapshot + import pypy + pypy.__path__.insert(0, pypy_translation_snapshot_dir) -# complement imports from pypy.objspace (from pypy-translation-snapshot) -# with pypy head objspace/ -import pypy.objspace -pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) + # complement imports from pypy.objspace (from pypy-translation-snapshot) + # with pypy head objspace/ + import pypy.objspace + pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) -print "imports redirected to pypy-translation-snapshot." + print "imports redirected to pypy-translation-snapshot." -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx import threading, pdb @@ -258,6 +261,7 @@ '-no-o': False, '-tcc': False, '-no-d': False, + '-no-snapshot' : False, '-load': False, '-save': False, '-fork': False, From adim at codespeak.net Fri Jul 1 18:29:13 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 18:29:13 +0200 (CEST) Subject: [pypy-svn] r14041 - in pypy/branch/pycompiler/translator: . c c/test genc goal llvm llvm/test llvm2 llvm2/test pickle pickle/attic test tool tool/pygame Message-ID: <20050701162913.D48DD27B51@code1.codespeak.net> Author: adim Date: Fri Jul 1 18:28:54 2005 New Revision: 14041 Added: pypy/branch/pycompiler/translator/backendoptimization.py - copied unchanged from r14039, pypy/dist/pypy/translator/backendoptimization.py pypy/branch/pycompiler/translator/c/char_include.h - copied unchanged from r14039, pypy/dist/pypy/translator/c/char_include.h pypy/branch/pycompiler/translator/c/external.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/external.py pypy/branch/pycompiler/translator/c/float_include.h - copied unchanged from r14039, pypy/dist/pypy/translator/c/float_include.h pypy/branch/pycompiler/translator/c/g_debuginfo.h - copied unchanged from r14039, pypy/dist/pypy/translator/c/g_debuginfo.h pypy/branch/pycompiler/translator/c/g_exception.h - copied unchanged from r14039, pypy/dist/pypy/translator/c/g_exception.h pypy/branch/pycompiler/translator/c/mkuint.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/mkuint.py pypy/branch/pycompiler/translator/c/symboltable.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/symboltable.py pypy/branch/pycompiler/translator/c/test/test_annotated.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_annotated.py pypy/branch/pycompiler/translator/c/test/test_backendoptimized.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_backendoptimized.py pypy/branch/pycompiler/translator/c/test/test_exception.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_exception.py pypy/branch/pycompiler/translator/c/test/test_lltyped.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_lltyped.py pypy/branch/pycompiler/translator/c/test/test_notype.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_notype.py pypy/branch/pycompiler/translator/c/test/test_operation.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_operation.py pypy/branch/pycompiler/translator/c/test/test_support.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_support.py pypy/branch/pycompiler/translator/c/test/test_symboltable.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_symboltable.py pypy/branch/pycompiler/translator/c/test/test_typed.py - copied unchanged from r14039, pypy/dist/pypy/translator/c/test/test_typed.py pypy/branch/pycompiler/translator/c/unichar_include.h - copied unchanged from r14039, pypy/dist/pypy/translator/c/unichar_include.h pypy/branch/pycompiler/translator/goal/richards.py - copied unchanged from r14039, pypy/dist/pypy/translator/goal/richards.py pypy/branch/pycompiler/translator/goal/targetrichards.py - copied unchanged from r14039, pypy/dist/pypy/translator/goal/targetrichards.py pypy/branch/pycompiler/translator/goal/targetrpystonex.py - copied unchanged from r14039, pypy/dist/pypy/translator/goal/targetrpystonex.py pypy/branch/pycompiler/translator/goal/unixcheckpoint.py - copied unchanged from r14039, pypy/dist/pypy/translator/goal/unixcheckpoint.py pypy/branch/pycompiler/translator/llvm2/ (props changed) - copied from r14039, pypy/dist/pypy/translator/llvm2/ pypy/branch/pycompiler/translator/llvm2/__init__.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/__init__.py pypy/branch/pycompiler/translator/llvm2/build_llvm_module.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/branch/pycompiler/translator/llvm2/cfgtransform.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/cfgtransform.py pypy/branch/pycompiler/translator/llvm2/codewriter.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/codewriter.py pypy/branch/pycompiler/translator/llvm2/database.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/database.py pypy/branch/pycompiler/translator/llvm2/funcnode.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/funcnode.py pypy/branch/pycompiler/translator/llvm2/genllvm.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/genllvm.py pypy/branch/pycompiler/translator/llvm2/log.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/log.py pypy/branch/pycompiler/translator/llvm2/pyxwrapper.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/branch/pycompiler/translator/llvm2/structnode.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/structnode.py pypy/branch/pycompiler/translator/llvm2/test/ (props changed) - copied from r14039, pypy/dist/pypy/translator/llvm2/test/ pypy/branch/pycompiler/translator/llvm2/test/__init__.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/test/__init__.py pypy/branch/pycompiler/translator/llvm2/test/llvmsnippet.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/branch/pycompiler/translator/llvm2/test/test_genllvm.py - copied unchanged from r14039, pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Removed: pypy/branch/pycompiler/translator/genc/ pypy/branch/pycompiler/translator/goal/targetpypy0.py pypy/branch/pycompiler/translator/goal/targetpypy1.py pypy/branch/pycompiler/translator/goal/targetrpystone2.py pypy/branch/pycompiler/translator/tool/flowtrace.py pypy/branch/pycompiler/translator/typer.py Modified: pypy/branch/pycompiler/translator/ann_override.py pypy/branch/pycompiler/translator/annrpython.py pypy/branch/pycompiler/translator/c/database.py pypy/branch/pycompiler/translator/c/funcgen.py pypy/branch/pycompiler/translator/c/g_include.h pypy/branch/pycompiler/translator/c/g_module.h pypy/branch/pycompiler/translator/c/g_support.h pypy/branch/pycompiler/translator/c/genc.py pypy/branch/pycompiler/translator/c/int_include.h pypy/branch/pycompiler/translator/c/ll_include.h pypy/branch/pycompiler/translator/c/node.py pypy/branch/pycompiler/translator/c/primitive.py pypy/branch/pycompiler/translator/c/pyobj_include.h pypy/branch/pycompiler/translator/c/support.py pypy/branch/pycompiler/translator/c/test/test_database.py pypy/branch/pycompiler/translator/c/test/test_genc.py pypy/branch/pycompiler/translator/c/wrapper.py pypy/branch/pycompiler/translator/geninterplevel.py pypy/branch/pycompiler/translator/goal/query.py pypy/branch/pycompiler/translator/goal/targetpypymain.py pypy/branch/pycompiler/translator/goal/targetrpystone.py pypy/branch/pycompiler/translator/goal/translate_pypy.py pypy/branch/pycompiler/translator/llvm/build_llvm_module.py pypy/branch/pycompiler/translator/llvm/llvmbc.py pypy/branch/pycompiler/translator/llvm/pointerrepr.py (props changed) pypy/branch/pycompiler/translator/llvm/reprmap.py (props changed) pypy/branch/pycompiler/translator/llvm/test/llvmsnippet.py pypy/branch/pycompiler/translator/llvm/test/test_genllvm.py pypy/branch/pycompiler/translator/llvm/typerepr.py pypy/branch/pycompiler/translator/pickle/__init__.py (props changed) pypy/branch/pycompiler/translator/pickle/attic/ (props changed) pypy/branch/pycompiler/translator/pickle/genpickle.py pypy/branch/pycompiler/translator/pickle/loader.py pypy/branch/pycompiler/translator/pickle/main.py pypy/branch/pycompiler/translator/pickle/writer.py pypy/branch/pycompiler/translator/simplify.py pypy/branch/pycompiler/translator/test/rpystone.py pypy/branch/pycompiler/translator/test/snippet.py pypy/branch/pycompiler/translator/test/test_annrpython.py pypy/branch/pycompiler/translator/test/test_backends.py (props changed) pypy/branch/pycompiler/translator/test/test_cltrans.py pypy/branch/pycompiler/translator/tool/graphpage.py pypy/branch/pycompiler/translator/tool/pygame/drawgraph.py pypy/branch/pycompiler/translator/tool/pygame/graphclient.py pypy/branch/pycompiler/translator/transform.py pypy/branch/pycompiler/translator/translator.py Log: updated branch with last version of trunk svn merge -r14039:140409 http://codespeak.net/svn/pypy/dist/pypy Modified: pypy/branch/pycompiler/translator/ann_override.py ============================================================================== --- pypy/branch/pycompiler/translator/ann_override.py (original) +++ pypy/branch/pycompiler/translator/ann_override.py Fri Jul 1 18:28:54 2005 @@ -1,15 +1,13 @@ # overrides for annotation specific to PyPy codebase from pypy.annotation.policy import AnnotatorPolicy -from pypy.annotation.bookkeeper import getbookkeeper +# for some reason, model must be imported first, +# or we create a cycle. from pypy.annotation import model as annmodel +from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation import specialize class PyPyAnnotatorPolicy(AnnotatorPolicy): - def override__ignore(pol, *args): - bk = getbookkeeper() - return bk.immutablevalue(None) - def override__instantiate(pol, clspbc): assert isinstance(clspbc, annmodel.SomePBC) clsdef = None @@ -34,6 +32,3 @@ from pypy.interpreter import pycode clsdef = getbookkeeper().getclassdef(pycode.PyCode) return annmodel.SomeInstance(clsdef) - - specialize__arg1 = staticmethod(specialize.argvalue(1)) - specialize__argtype1 = staticmethod(specialize.argtype(1)) Modified: pypy/branch/pycompiler/translator/annrpython.py ============================================================================== --- pypy/branch/pycompiler/translator/annrpython.py (original) +++ pypy/branch/pycompiler/translator/annrpython.py Fri Jul 1 18:28:54 2005 @@ -1,25 +1,20 @@ from __future__ import generators from types import FunctionType, ClassType -from pypy.tool.ansi_print import ansi_print +from pypy.tool.ansi_print import ansi_log from pypy.annotation import model as annmodel from pypy.annotation.model import pair from pypy.annotation.bookkeeper import Bookkeeper from pypy.objspace.flow.model import Variable, Constant from pypy.objspace.flow.model import SpaceOperation, FunctionGraph from pypy.objspace.flow.model import last_exception, checkgraph +import py +log = py.log.Producer("annrpython") +py.log.setconsumer("annrpython", ansi_log) class AnnotatorError(Exception): pass -class BasicAnnotatorPolicy: - - def specialize(pol, bookkeeper, spaceop, func, args, mono): - return None, None - - def compute_at_fixpoint(pol, annotator): - annotator.bookkeeper.compute_at_fixpoint() - class RPythonAnnotator: """Block annotator for RPython. @@ -52,7 +47,8 @@ self.frozen = False # user-supplied annotation logic for functions we don't want to flow into if policy is None: - self.policy = BasicAnnotatorPolicy() + from pypy.annotation.policy import AnnotatorPolicy + self.policy = AnnotatorPolicy() else: self.policy = policy @@ -96,8 +92,9 @@ # make input arguments and set their type input_arg_types = list(input_arg_types) nbarg = len(flowgraph.getargs()) - while len(input_arg_types) < nbarg: - input_arg_types.append(object) + if len(input_arg_types) != nbarg: + raise TypeError("flowgraph %s expects %d args, got %d" %( + flowgraph.name, nbarg, len(input_arg_types))) inputcells = [] for t in input_arg_types: if not isinstance(t, annmodel.SomeObject): @@ -233,15 +230,13 @@ self.bindings[arg] = s_value if annmodel.DEBUG: if arg in self.return_bindings: - ansi_print("%s -> %s" % (self.whereami((self.return_bindings[arg], - None, None)), - s_value), - esc="1") # bold + log.bold("%s -> %s" % + (self.whereami((self.return_bindings[arg], None, None)), + s_value)) if arg in self.return_bindings and s_value == annmodel.SomeObject(): - ansi_print("*** WARNING: %s result degenerated to SomeObject" % - self.whereami((self.return_bindings[arg],None, None)), - esc="31") # RED + log.red("*** WARNING: %s result degenerated to SomeObject" % + self.whereami((self.return_bindings[arg],None, None))) self.binding_caused_by[arg] = called_from @@ -595,6 +590,7 @@ # XXX "contains" clash with SomeObject method def consider_op_contains(self, seq, elem): + self.bookkeeper.count("contains", seq) return annmodel.SomeBool() def consider_op_newtuple(self, *args): @@ -611,6 +607,7 @@ return self.bookkeeper.newdict(*items_s) def consider_op_newslice(self, start, stop, step): + self.bookkeeper.count('newslice', start, stop, step) return annmodel.SomeSlice(start, stop, step) Modified: pypy/branch/pycompiler/translator/c/database.py ============================================================================== --- pypy/branch/pycompiler/translator/c/database.py (original) +++ pypy/branch/pycompiler/translator/c/database.py Fri Jul 1 18:28:54 2005 @@ -1,6 +1,7 @@ from pypy.rpython.lltype import Primitive, Ptr, typeOf from pypy.rpython.lltype import Struct, Array, FuncType, PyObject, Void -from pypy.rpython.lltype import ContainerType +from pypy.rpython.lltype import ContainerType, pyobjectptr, OpaqueType, GcStruct +from pypy.rpython.rmodel import getfunctionptr from pypy.objspace.flow.model import Constant from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue @@ -14,6 +15,7 @@ class LowLevelDatabase: def __init__(self, translator=None): + self.translator = translator self.structdefnodes = {} self.structdeflist = [] self.containernodes = {} @@ -67,6 +69,11 @@ argtypes.append(cdecl(argtype, argname)) argtypes = ', '.join(argtypes) or 'void' return resulttype.replace('@', '(@)(%s)' % argtypes) + elif isinstance(T, OpaqueType): + if T.tag == 'RuntimeTypeInfo': + return 'void (@)(void *)' # void dealloc_xx(struct xx *) + else: + raise Exception("don't know about opaque type %r" % (T,)) else: raise Exception("don't know about type %r" % (T,)) @@ -105,6 +112,8 @@ def cincrefstmt(self, expr, T): if isinstance(T, Ptr) and T._needsgc(): + if expr == 'NULL': # hum + return '' if T.TO == PyObject: return 'Py_XINCREF(%s);' % expr else: @@ -144,3 +153,51 @@ for node in self.containerlist: if node.globalcontainer: yield node + + def get_lltype_of_exception_value(self): + if self.translator is not None and self.translator.rtyper is not None: + exceptiondata = self.translator.rtyper.getexceptiondata() + return exceptiondata.lltype_of_exception_value + else: + return Ptr(PyObject) + + def pre_include_code_lines(self): + # generate some #defines that go before the #include to control + # what g_exception.h does + if self.translator is not None and self.translator.rtyper is not None: + exceptiondata = self.translator.rtyper.getexceptiondata() + + TYPE = exceptiondata.lltype_of_exception_type + assert isinstance(TYPE, Ptr) + typename = self.gettype(TYPE) + yield '#define RPYTHON_EXCEPTION_VTABLE %s' % cdecl(typename, '') + + TYPE = exceptiondata.lltype_of_exception_value + assert isinstance(TYPE, Ptr) + typename = self.gettype(TYPE) + yield '#define RPYTHON_EXCEPTION %s' % cdecl(typename, '') + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_exception_match) + fnname = self.get(fnptr) + yield '#define RPYTHON_EXCEPTION_MATCH %s' % (fnname,) + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_type_of_exc_inst) + fnname = self.get(fnptr) + yield '#define RPYTHON_TYPE_OF_EXC_INST %s' % (fnname,) + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_pyexcclass2exc) + fnname = self.get(fnptr) + yield '#define RPYTHON_PYEXCCLASS2EXC %s' % (fnname,) + + for pyexccls in exceptiondata.standardexceptions: + exc_llvalue = exceptiondata.ll_pyexcclass2exc( + pyobjectptr(pyexccls)) + # strange naming here because the macro name must be + # a substring of PyExc_%s + yield '#define Exc_%s\t%s' % ( + pyexccls.__name__, self.get(exc_llvalue)) + + self.complete() # because of the get() and gettype() above Modified: pypy/branch/pycompiler/translator/c/funcgen.py ============================================================================== --- pypy/branch/pycompiler/translator/c/funcgen.py (original) +++ pypy/branch/pycompiler/translator/c/funcgen.py Fri Jul 1 18:28:54 2005 @@ -1,11 +1,10 @@ from __future__ import generators from pypy.translator.c.support import cdecl, ErrorValue -from pypy.translator.c.support import llvalue_from_constant +from pypy.translator.c.support import llvalue_from_constant, gen_assignments from pypy.objspace.flow.model import Variable, Constant, Block -from pypy.objspace.flow.model import traverse, uniqueitems, last_exception +from pypy.objspace.flow.model import traverse, last_exception from pypy.rpython.lltype import Ptr, PyObject, Void, Bool from pypy.rpython.lltype import pyobjectptr, Struct, Array -from pypy.translator.unsimplify import remove_direct_loops PyObjPtr = Ptr(PyObject) @@ -16,55 +15,71 @@ from a flow graph. """ - def __init__(self, graph, db): + def __init__(self, graph, db, cpython_exc=False): self.graph = graph - remove_direct_loops(None, graph) self.db = db - self.lltypemap = self.collecttypes() - self.typemap = {} - for v, T in self.lltypemap.items(): - self.typemap[v] = db.gettype(T) - - def collecttypes(self): + self.cpython_exc = cpython_exc + # # collect all variables and constants used in the body, # and get their types now - result = [] + # + # NOTE: cannot use dictionaries with Constants has keys, because + # Constants may hash and compare equal but have different lltypes + mix = [] + self.more_ll_values = [] def visit(block): if isinstance(block, Block): - result.extend(block.inputargs) + mix.extend(block.inputargs) for op in block.operations: - result.extend(op.args) - result.append(op.result) + mix.extend(op.args) + mix.append(op.result) for link in block.exits: - result.extend(link.getextravars()) - result.extend(link.args) - result.append(Constant(link.exitcase)) - traverse(visit, self.graph) - resultvar = self.graph.getreturnvar() - lltypemap = {resultvar: Void} # default value, normally overridden - for v in uniqueitems(result): - # xxx what kind of pointer for constants? - T = getattr(v, 'concretetype', PyObjPtr) - lltypemap[v] = T - return lltypemap + mix.extend(link.getextravars()) + mix.extend(link.args) + mix.append(Constant(link.exitcase)) + if hasattr(link, 'llexitcase'): + self.more_ll_values.append(link.llexitcase) + traverse(visit, graph) + resultvar = graph.getreturnvar() + + self.lltypes = { + # default, normally overridden: + id(resultvar): (resultvar, Void, db.gettype(Void)), + } + for v in mix: + T = getattr(v, 'concretetype', PyObjPtr) + typename = db.gettype(T) + self.lltypes[id(v)] = v, T, typename def argnames(self): return [v.name for v in self.graph.getargs()] def allvariables(self): - return [v for v in self.typemap if isinstance(v, Variable)] + return [v for v, T, typename in self.lltypes.values() + if isinstance(v, Variable)] def allconstants(self): - return [v for v in self.typemap if isinstance(v, Constant)] + return [c for c, T, typename in self.lltypes.values() + if isinstance(c, Constant)] def allconstantvalues(self): - for v in self.typemap: - if isinstance(v, Constant): - yield llvalue_from_constant(v) + for c, T, typename in self.lltypes.values(): + if isinstance(c, Constant): + yield llvalue_from_constant(c) + for llvalue in self.more_ll_values: + yield llvalue + + def lltypemap(self, v): + v, T, typename = self.lltypes[id(v)] + return T + + def lltypename(self, v): + v, T, typename = self.lltypes[id(v)] + return typename - def expr(self, v): + def expr(self, v, special_case_void=True): if isinstance(v, Variable): - if self.lltypemap[v] == Void: + if self.lltypemap(v) == Void and special_case_void: return '/* nothing */' else: return v.name @@ -74,22 +89,36 @@ raise TypeError, "expr(%r)" % (v,) def error_return_value(self): - returnlltype = self.lltypemap[self.graph.getreturnvar()] + returnlltype = self.lltypemap(self.graph.getreturnvar()) return self.db.get(ErrorValue(returnlltype)) + def return_with_error(self): + if self.cpython_exc: + lltype_of_exception_value = self.db.get_lltype_of_exception_value() + exc_value_typename = self.db.gettype(lltype_of_exception_value) + assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr + yield '{' + yield '\t%s;' % cdecl(exc_value_typename, 'vanishing_exc_value') + yield '\tConvertExceptionToCPython(vanishing_exc_value);' + yield '\t%s' % self.db.cdecrefstmt('vanishing_exc_value', lltype_of_exception_value) + yield '}' + yield 'return %s; ' % self.error_return_value() + # ____________________________________________________________ def cfunction_declarations(self): # declare the local variables, excluding the function arguments - inputargset = {} + seen = {} for a in self.graph.getargs(): - inputargset[a] = True + seen[a.name] = True result_by_name = [] for v in self.allvariables(): - if v not in inputargset: - result = cdecl(self.typemap[v], v.name) + ';' - if self.lltypemap[v] == Void: + name = v.name + if name not in seen: + seen[name] = True + result = cdecl(self.lltypename(v), name) + ';' + if self.lltypemap(v) == Void: result = '/*%s*/' % result result_by_name.append((v._name, result)) result_by_name.sort() @@ -116,24 +145,36 @@ for v in to_release: linklocalvars[v] = self.expr(v) has_ref = linklocalvars.copy() + assignments = [] + increfs = [] for a1, a2 in zip(link.args, link.target.inputargs): - if self.lltypemap[a2] == Void: + if self.lltypemap(a2) == Void: continue if a1 in linklocalvars: src = linklocalvars[a1] else: src = self.expr(a1) - line = '%s = %s;' % (self.expr(a2), src) + dest = self.expr(a2) + assignments.append((self.lltypename(a2), dest, src)) if a1 in has_ref: del has_ref[a1] else: - assert self.lltypemap[a1] == self.lltypemap[a2] - line += '\t' + self.cincref(a2) - yield line + assert self.lltypemap(a1) == self.lltypemap(a2) + line = self.cincref(a2) + if line: + increfs.append(line) + # warning, the order below is delicate to get right: + # 1. decref the old variables that are not passed over for v in has_ref: line = self.cdecref(v, linklocalvars[v]) if line: yield line + # 2. perform the assignments with collision-avoidance + for line in gen_assignments(assignments): + yield line + # 3. incref the new variables if needed + for line in increfs: + yield line yield 'goto block%d;' % blocknum[link.target] # collect all blocks @@ -169,8 +210,9 @@ # exceptional return block exc_cls = self.expr(block.inputargs[0]) exc_value = self.expr(block.inputargs[1]) - yield 'PyErr_Restore(%s, %s, NULL);' % (exc_cls, exc_value) - yield 'return %s;' % self.error_return_value() + yield 'RaiseException(%s, %s);' % (exc_cls, exc_value) + for line in self.return_with_error(): + yield line else: # regular return block retval = self.expr(block.inputargs[0]) @@ -197,31 +239,40 @@ yield '' for link in block.exits[1:]: assert issubclass(link.exitcase, Exception) - yield 'if (PyErr_ExceptionMatches(%s)) {' % ( - self.db.get(pyobjectptr(link.exitcase)),) - yield '\tPyObject *exc_cls, *exc_value, *exc_tb;' - yield '\tPyErr_Fetch(&exc_cls, &exc_value, &exc_tb);' - yield '\tif (exc_value == NULL) {' - yield '\t\texc_value = Py_None;' - yield '\t\tPy_INCREF(Py_None);' - yield '\t}' - yield '\tPy_XDECREF(exc_tb);' + try: + etype = link.llexitcase + except AttributeError: + etype = pyobjectptr(link.exitcase) + T1 = PyObjPtr + T2 = PyObjPtr + else: + assert hasattr(link.last_exception, 'concretetype') + assert hasattr(link.last_exc_value, 'concretetype') + T1 = link.last_exception.concretetype + T2 = link.last_exc_value.concretetype + typ1 = self.db.gettype(T1) + typ2 = self.db.gettype(T2) + yield 'if (MatchException(%s)) {' % (self.db.get(etype),) + yield '\t%s;' % cdecl(typ1, 'exc_cls') + yield '\t%s;' % cdecl(typ2, 'exc_value') + yield '\tFetchException(exc_cls, exc_value, %s);' % ( + cdecl(typ2, '')) d = {} if isinstance(link.last_exception, Variable): d[link.last_exception] = 'exc_cls' else: - yield '\tPy_XDECREF(exc_cls);' + yield '\t' + self.db.cdecrefstmt('exc_cls', T1) if isinstance(link.last_exc_value, Variable): d[link.last_exc_value] = 'exc_value' else: - yield '\tPy_XDECREF(exc_value);' + yield '\t' + self.db.cdecrefstmt('exc_value', T2) for op in gen_link(link, d): yield '\t' + op yield '}' err_reachable = True else: # block ending in a switch on a value - TYPE = self.lltypemap[block.exitswitch] + TYPE = self.lltypemap(block.exitswitch) for link in block.exits[:-1]: assert link.exitcase in (False, True) expr = self.expr(block.exitswitch) @@ -257,7 +308,8 @@ yield 'err%d_%d:' % (blocknum[block], len(to_release)) err_reachable = True if err_reachable: - yield 'return %s;' % self.error_return_value() + for line in self.return_with_error(): + yield line # ____________________________________________________________ @@ -302,22 +354,23 @@ def OP_DIRECT_CALL(self, op, err): # skip 'void' arguments - args = [self.expr(v) for v in op.args if self.lltypemap[v] != Void] - if self.lltypemap[op.result] == Void: + args = [self.expr(v) for v in op.args if self.lltypemap(v) != Void] + if self.lltypemap(op.result) == Void: # skip assignment of 'void' return value - return '%s(%s); if (PyErr_Occurred()) FAIL(%s)' % ( + return '%s(%s); if (ExceptionOccurred()) FAIL(%s)' % ( args[0], ', '.join(args[1:]), err) else: r = self.expr(op.result) - return '%s = %s(%s); if (PyErr_Occurred()) FAIL(%s)' % ( + return '%s = %s(%s); if (ExceptionOccurred()) FAIL(%s)' % ( r, args[0], ', '.join(args[1:]), err) # low-level operations def generic_get(self, op, sourceexpr): - newvalue = self.expr(op.result) + T = self.lltypemap(op.result) + newvalue = self.expr(op.result, special_case_void=False) result = ['%s = %s;' % (newvalue, sourceexpr)] # need to adjust the refcount of the result - T = self.lltypemap[op.result] + increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) @@ -327,17 +380,17 @@ return result def generic_set(self, op, targetexpr): - newvalue = self.expr(op.args[2]) + newvalue = self.expr(op.args[2], special_case_void=False) result = ['%s = %s;' % (targetexpr, newvalue)] # need to adjust some refcounts - T = self.lltypemap[op.args[2]] + T = self.lltypemap(op.args[2]) decrefstmt = self.db.cdecrefstmt('prev', T) increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) if decrefstmt: result.insert(0, '{ %s = %s;' % ( - cdecl(self.typemap[op.args[2]], 'prev'), + cdecl(self.lltypename(op.args[2]), 'prev'), targetexpr)) result.append(decrefstmt) result.append('}') @@ -348,7 +401,7 @@ def OP_GETFIELD(self, op, err, ampersand=''): assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO + STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) fieldname = structdef.c_struct_field_name(op.args[1].value) return self.generic_get(op, '%s%s->%s' % (ampersand, @@ -357,7 +410,7 @@ def OP_SETFIELD(self, op, err): assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO + STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) fieldname = structdef.c_struct_field_name(op.args[1].value) return self.generic_set(op, '%s->%s' % (self.expr(op.args[0]), @@ -386,7 +439,10 @@ def OP_PTR_NONZERO(self, op, err): return '%s = (%s != NULL);' % (self.expr(op.result), self.expr(op.args[0])) - + def OP_PTR_ISZERO(self, op, err): + return '%s = (%s == NULL);' % (self.expr(op.result), + self.expr(op.args[0])) + def OP_PTR_EQ(self, op, err): return '%s = (%s == %s);' % (self.expr(op.result), self.expr(op.args[0]), @@ -398,7 +454,7 @@ self.expr(op.args[1])) def OP_MALLOC(self, op, err): - TYPE = self.lltypemap[op.result].TO + TYPE = self.lltypemap(op.result).TO typename = self.db.gettype(TYPE) eresult = self.expr(op.result) result = ['OP_ZERO_MALLOC(sizeof(%s), %s, %s)' % (cdecl(typename, ''), @@ -410,7 +466,7 @@ return '\t'.join(result) def OP_MALLOC_VARSIZE(self, op, err): - TYPE = self.lltypemap[op.result].TO + TYPE = self.lltypemap(op.result).TO typename = self.db.gettype(TYPE) lenfld = 'length' nodedef = self.db.gettypedefnode(TYPE) @@ -439,7 +495,7 @@ return '\t'.join(result) def OP_CAST_POINTER(self, op, err): - TYPE = self.lltypemap[op.result] + TYPE = self.lltypemap(op.result) typename = self.db.gettype(TYPE) result = [] result.append('%s = (%s)%s;' % (self.expr(op.result), @@ -452,8 +508,8 @@ def OP_SAME_AS(self, op, err): result = [] - assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] - if self.lltypemap[op.result] != Void: + assert self.lltypemap(op.args[0]) == self.lltypemap(op.result) + if self.lltypemap(op.result) != Void: result.append('%s = %s;' % (self.expr(op.result), self.expr(op.args[0]))) line = self.cincref(op.result) @@ -462,9 +518,9 @@ return '\t'.join(result) def cincref(self, v): - T = self.lltypemap[v] + T = self.lltypemap(v) return self.db.cincrefstmt(v.name, T) def cdecref(self, v, expr=None): - T = self.lltypemap[v] + T = self.lltypemap(v) return self.db.cdecrefstmt(expr or v.name, T) Modified: pypy/branch/pycompiler/translator/c/g_include.h ============================================================================== --- pypy/branch/pycompiler/translator/c/g_include.h (original) +++ pypy/branch/pycompiler/translator/c/g_include.h Fri Jul 1 18:28:54 2005 @@ -10,10 +10,14 @@ #include "marshal.h" #include "eval.h" +#include "g_exception.h" #include "g_trace.h" #include "g_support.h" #include "g_module.h" #include "int_include.h" +#include "char_include.h" +#include "unichar_include.h" +#include "float_include.h" #include "ll_include.h" #include "pyobj_include.h" Modified: pypy/branch/pycompiler/translator/c/g_module.h ============================================================================== --- pypy/branch/pycompiler/translator/c/g_module.h (original) +++ pypy/branch/pycompiler/translator/c/g_module.h Fri Jul 1 18:28:54 2005 @@ -2,26 +2,34 @@ /************************************************************/ /*** C header subsection: CPython-extension-module-ness ***/ - -#ifndef COUNT_OP_MALLOCS -# define MODULE_INITFUNC(modname) \ - static PyMethodDef my_methods[] = { (char *)NULL, (PyCFunction)NULL }; \ - PyMODINIT_FUNC init##modname(void) +#ifdef COUNT_OP_MALLOCS +# define METHODDEF_MALLOC_COUNTERS \ + { "malloc_counters", malloc_counters, METH_VARARGS }, #else -# define MODULE_INITFUNC(modname) \ - static PyMethodDef my_methods[] = { \ - { "malloc_counters", malloc_counters }, \ - { (char *)NULL, (PyCFunction)NULL } }; \ - PyMODINIT_FUNC init##modname(void) +# define METHODDEF_MALLOC_COUNTERS /* nothing */ #endif -#define SETUP_MODULE(modname) \ +#define METHODDEF_DEBUGINFO /* nothing, unless overridden by g_debuginfo.h */ + +#define MODULE_INITFUNC(modname) \ + static PyMethodDef my_methods[] = { \ + METHODDEF_MALLOC_COUNTERS \ + METHODDEF_DEBUGINFO \ + { (char *)NULL, (PyCFunction)NULL } }; \ + PyMODINIT_FUNC init##modname(void) + +#define SETUP_MODULE(modname) \ PyObject *m = Py_InitModule(#modname, my_methods); \ PyModule_AddStringConstant(m, "__sourcefile__", __FILE__); \ this_module_globals = PyModule_GetDict(m); \ PyGenCFunction_Type.tp_base = &PyCFunction_Type; \ PyType_Ready(&PyGenCFunction_Type); \ - if (setup_globalfunctions(globalfunctiondefs) < 0) \ + RPythonError = PyErr_NewException(#modname ".RPythonError", \ + NULL, NULL); \ + if (RPythonError == NULL) \ + return; \ + PyModule_AddObject(m, "RPythonError", RPythonError); \ + if (setup_globalfunctions(globalfunctiondefs, #modname) < 0) \ return; \ if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \ return; \ @@ -62,12 +70,15 @@ return 0; } -static int setup_globalfunctions(globalfunctiondef_t* def) +static int setup_globalfunctions(globalfunctiondef_t* def, char* modname) { PyObject* fn; + PyObject* modname_o = PyString_FromString(modname); + if (modname_o == NULL) + return -1; for (; def->p != NULL; def++) { - fn = PyCFunction_New(&def->ml, NULL); + fn = PyCFunction_NewEx(&def->ml, NULL, modname_o); if (fn == NULL) return -1; fn->ob_type = &PyGenCFunction_Type; Modified: pypy/branch/pycompiler/translator/c/g_support.h ============================================================================== --- pypy/branch/pycompiler/translator/c/g_support.h (original) +++ pypy/branch/pycompiler/translator/c/g_support.h Fri Jul 1 18:28:54 2005 @@ -11,12 +11,13 @@ #define FAIL_EXCEPTION(err, exc, msg) \ { \ - PyErr_SetString(exc, msg); \ + RaiseSimpleException(exc, msg); \ FAIL(err) \ } -#define FAIL_OVF(err, msg) FAIL_EXCEPTION(err, PyExc_OverflowError, msg) -#define FAIL_VAL(err, msg) FAIL_EXCEPTION(err, PyExc_ValueError, msg) -#define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, PyExc_ZeroDivisionError, msg) +#define FAIL_OVF(err, msg) FAIL_EXCEPTION(err, Exc_OverflowError, msg) +#define FAIL_VAL(err, msg) FAIL_EXCEPTION(err, Exc_ValueError, msg) +#define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, Exc_ZeroDivisionError, msg) +#define CFAIL(err) { ConvertExceptionFromCPython(); FAIL(err) } /* we need a subclass of 'builtin_function_or_method' which can be used as methods: builtin function objects that can be bound on instances */ @@ -368,5 +369,9 @@ return PyTuple_SetItem(tuple, index, o); } -#define PyString_FromStringAndSize_Hack(s, size) \ - PyString_FromStringAndSize((char*)(s), size) +#define PyString_FromLLCharArrayAndSize(itemsarray, size) \ + PyString_FromStringAndSize(itemsarray->items, size) + +#define PyString_ToLLCharArray(s, itemsarray) \ + memcpy(itemsarray->items, PyString_AS_STRING(s), \ + itemsarray->length) Modified: pypy/branch/pycompiler/translator/c/genc.py ============================================================================== --- pypy/branch/pycompiler/translator/c/genc.py (original) +++ pypy/branch/pycompiler/translator/c/genc.py Fri Jul 1 18:28:54 2005 @@ -16,7 +16,8 @@ return db, pf -def genc(translator, targetdir=None, modulename=None, compile=True): +def genc(translator, targetdir=None, modulename=None, compile=True, + symtable=True): """Generate C code starting at the translator's entry point. The files are written to the targetdir if specified. If 'compile' is True, compile and return the new module. @@ -31,18 +32,26 @@ elif isinstance(targetdir, str): targetdir = py.path.local(targetdir) targetdir.ensure(dir=1) + if symtable: + from pypy.translator.c.symboltable import SymbolTable + symboltable = SymbolTable() + else: + symboltable = None cfile = gen_source(db, modulename, targetdir, # defines={'COUNT_OP_MALLOCS': 1}, - exports = {translator.entrypoint.func_name: pf}) + exports = {translator.entrypoint.func_name: pf}, + symboltable = symboltable) if not compile: return cfile m = make_module_from_c(cfile, include_dirs = [autopath.this_dir]) + symboltable.attach(m) # hopefully temporary hack return m # ____________________________________________________________ def gen_readable_parts_of_main_c_file(f, database): + lines = list(database.pre_include_code_lines()) # # All declarations # @@ -53,9 +62,6 @@ for node in database.structdeflist: for line in node.definition(phase=1): print >> f, line - for node in database.structdeflist: - for line in node.definition(phase=2): - print >> f, line print >> f print >> f, '/***********************************************************/' print >> f, '/*** Forward declarations ***/' @@ -63,13 +69,23 @@ for node in database.globalcontainers(): for line in node.forward_declaration(): print >> f, line + # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' - blank = True + print >> f + for line in lines: + print >> f, line + print >> f, '#include "g_include.h"' + print >> f + blank = False + for node in database.structdeflist: + for line in node.definition(phase=2): + print >> f, line + blank = True for node in database.globalcontainers(): if blank: print >> f @@ -79,7 +95,8 @@ blank = True -def gen_source(database, modulename, targetdir, defines={}, exports={}): +def gen_source(database, modulename, targetdir, defines={}, exports={}, + symboltable=None): if isinstance(targetdir, str): targetdir = py.path.local(targetdir) filename = targetdir.join(modulename + '.c') @@ -90,7 +107,15 @@ # for key, value in defines.items(): print >> f, '#define %s %s' % (key, value) - print >> f, '#include "g_include.h"' + print >> f, '#include "Python.h"' + includes = {} + for node in database.globalcontainers(): + for include in node.includes: + includes[include] = True + includes = includes.keys() + includes.sort() + for include in includes: + print >> f, '#include <%s>' % (include,) # # 1) All declarations @@ -99,6 +124,27 @@ gen_readable_parts_of_main_c_file(f, database) # + # Debugging info + # + if symboltable: + print >> f + print >> f, '/*******************************************************/' + print >> f, '/*** Debugging info ***/' + print >> f + print >> f, 'static int debuginfo_offsets[] = {' + for node in database.structdeflist: + for expr in symboltable.generate_type_info(database, node): + print >> f, '\t%s,' % expr + print >> f, '\t0 };' + print >> f, 'static void *debuginfo_globals[] = {' + for node in database.globalcontainers(): + if not isinstance(node, PyObjectNode): + result = symboltable.generate_global_info(database, node) + print >> f, '\t%s,' % (result,) + print >> f, '\tNULL };' + print >> f, '#include "g_debuginfo.h"' + + # # PyObject support (strange) code # pyobjmaker = database.pyobjmaker Modified: pypy/branch/pycompiler/translator/c/int_include.h ============================================================================== --- pypy/branch/pycompiler/translator/c/int_include.h (original) +++ pypy/branch/pycompiler/translator/c/int_include.h Fri Jul 1 18:28:54 2005 @@ -4,60 +4,56 @@ /*** unary operations ***/ -#define OP_INCREF_int(x) /* nothing */ -#define OP_DECREF_int(x) /* nothing */ -#define CONV_TO_OBJ_int PyInt_FromLong -#define CONV_FROM_OBJ_int PyInt_AS_LONG - #define OP_INT_IS_TRUE(x,r,err) OP_INT_NE(x,0,r,err) -#define OP_INT_INVERT(x,r,err) r = ~((long)(x)); +#define OP_INT_INVERT(x,r,err) r = ~((x)); #define OP_INT_POS(x,r,err) r = x; -#define OP_INT_NEG(x,r,err) r = -((long)x); +#define OP_INT_NEG(x,r,err) r = -(x); #define OP_INT_NEG_OVF(x,r,err) \ OP_INT_NEG(x,r,err) \ - if ((long)(x) >= 0 || (long)(x) != -(long)(x)); \ + if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer negate") -#define OP_INT_ABS(x,r,err) r = (long)(x) >= 0 ? x : -((long)x); +#define OP_INT_ABS(x,r,err) r = (x) >= 0 ? x : -(x); +#define OP_UINT_ABS(x,r,err) r = (x); #define OP_INT_ABS_OVF(x,r,err) \ OP_INT_ABS(x,r,err) \ - if ((long)(x) >= 0 || (long)(x) != -(long)(x)); \ + if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer absolute") /*** binary operations ***/ -#define OP_INT_EQ(x,y,r,err) r = ((long)(x) == (long)(y)); -#define OP_INT_NE(x,y,r,err) r = ((long)(x) != (long)(y)); -#define OP_INT_LE(x,y,r,err) r = ((long)(x) <= (long)(y)); -#define OP_INT_GT(x,y,r,err) r = ((long)(x) > (long)(y)); -#define OP_INT_LT(x,y,r,err) r = ((long)(x) < (long)(y)); -#define OP_INT_GE(x,y,r,err) r = ((long)(x) >= (long)(y)); +#define OP_INT_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_INT_NE(x,y,r,err) r = ((x) != (y)); +#define OP_INT_LE(x,y,r,err) r = ((x) <= (y)); +#define OP_INT_GT(x,y,r,err) r = ((x) > (y)); +#define OP_INT_LT(x,y,r,err) r = ((x) < (y)); +#define OP_INT_GE(x,y,r,err) r = ((x) >= (y)); #define OP_INT_CMP(x,y,r,err) \ - r = (((long)(x) > (long)(y)) - ((long)(x) < (long)(y))) + r = (((x) > (y)) - ((x) < (y))) /* addition, subtraction */ -#define OP_INT_ADD(x,y,r,err) r = (long)(x) + (long)(y); +#define OP_INT_ADD(x,y,r,err) r = (x) + (y); #define OP_INT_ADD_OVF(x,y,r,err) \ OP_INT_ADD(x,y,r,err) \ - if ((r^((long)x)) >= 0 || (r^((long)y)) >= 0); \ + if ((r^(x)) >= 0 || (r^(y)) >= 0); \ else FAIL_OVF(err, "integer addition") -#define OP_INT_SUB(x,y,r,err) r = (long)(x) - (long)(y); +#define OP_INT_SUB(x,y,r,err) r = (x) - (y); #define OP_INT_SUB_OVF(x,y,r,err) \ OP_INT_SUB(x,y,r,err) \ - if ((r^(long)(x)) >= 0 || (r^~(long)(y)) >= 0); \ + if ((r^(x)) >= 0 || (r^~(y)) >= 0); \ else FAIL_OVF(err, "integer subtraction") -#define OP_INT_MUL(x,y,r,err) r = (long)(x) * (long)(y); +#define OP_INT_MUL(x,y,r,err) r = (x) * (y); #ifndef HAVE_LONG_LONG @@ -70,7 +66,7 @@ #define OP_INT_MUL_OVF(x,y,r,err) \ { \ PY_LONG_LONG lr = (PY_LONG_LONG)(x) * (PY_LONG_LONG)(y); \ - r = (long)lr; \ + r = lr; \ if ((PY_LONG_LONG)r == lr); \ else FAIL_OVF(err, "integer multiplication") \ } @@ -78,68 +74,112 @@ /* shifting */ -#define OP_INT_RSHIFT(x,y,r,err) \ - if ((long)(y) < LONG_BIT) \ - r = Py_ARITHMETIC_RIGHT_SHIFT(long, (long)(x), (long)(y)); \ - else r = (long)(x) < 0 ? -1 : 0; - -#define OP_INT_RSHIFT_VAL(x,y,r,err) \ - if ((long)(y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") - -#define OP_INT_LSHIFT(x,y,r,err) \ - if ((long)(y) < LONG_BIT) \ - r = (long)(x) << (long)(y); \ - else r = 0; - -#define OP_INT_LSHIFT_VAL(x,y,r,err) \ - if ((long)(y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") +/* NB. shifting has same limitations as C: the shift count must be + >= 0 and < LONG_BITS. */ +#define OP_INT_RSHIFT(x,y,r,err) r = Py_ARITHMETIC_RIGHT_SHIFT(long, x, y); +#define OP_UINT_RSHIFT(x,y,r,err) r = (x) >> (y); + +#define OP_INT_LSHIFT(x,y,r,err) r = (x) << (y); +#define OP_UINT_LSHIFT(x,y,r,err) r = (x) << (y); #define OP_INT_LSHIFT_OVF(x,y,r,err) \ OP_INT_LSHIFT(x,y,r,err) \ - if ((long)(x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (long)(y))) \ + if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") + +/* for reference, the safe value-checking version of the above macros + (not really used at the moment) */ + +/* #define OP_INT_RSHIFT(x,y,r,err) \ */ +/* if ((y) < LONG_BIT) \ */ +/* r = Py_ARITHMETIC_RIGHT_SHIFT(long, (x), (y)); \ */ +/* else r = (x) < 0 ? -1 : 0; */ + +/* #define OP_INT_RSHIFT_VAL(x,y,r,err) \ */ +/* if ((y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ + +/* #define OP_INT_LSHIFT(x,y,r,err) \ */ +/* if ((y) < LONG_BIT) \ */ +/* r = (x) << (y); \ */ +/* else r = 0; */ + +/* #define OP_INT_LSHIFT_VAL(x,y,r,err) \ */ +/* if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ + +/* #define OP_INT_LSHIFT_OVF(x,y,r,err) \ */ +/* OP_INT_LSHIFT(x,y,r,err) \ */ +/* if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ */ +/* FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ /* floor division */ -#define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); +#define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); +#define OP_UINT_FLOORDIV(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_FLOORDIV_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && (long)(x) == -(long)(x)) \ + if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer division") \ OP_INT_FLOORDIV(x,y,r,err) #define OP_INT_FLOORDIV_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_FLOORDIV(x,y,r,err) } \ + if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ else FAIL_ZER(err, "integer division") - +#define OP_UINT_FLOORDIV_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; + #define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ + if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer division") /* modulus */ #define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); +#define OP_UINT_MOD(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_MOD_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && (long)x == -(long)(x)) \ + if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer modulo") \ OP_INT_MOD(x,y,r,err); #define OP_INT_MOD_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_MOD(x,y,r,err) } \ + if ((y)) { OP_INT_MOD(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") - +#define OP_UINT_MOD_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; + #define OP_INT_MOD_OVF_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_MOD_OVF(x,y,r,err) } \ + if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") +/* bit operations */ + +#define OP_INT_AND(x,y,r,err) r = (x) & (y); +#define OP_INT_OR( x,y,r,err) r = (x) | (y); +#define OP_INT_XOR(x,y,r,err) r = (x) ^ (y); + +/*** conversions ***/ + +#define OP_CAST_BOOL_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_BOOL_TO_UINT(x,r,err) r = (unsigned long)(x); +#define OP_CAST_UINT_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_INT_TO_UINT(x,r,err) r = (unsigned long)(x); +#define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); +#define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ + +#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (x); +#define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (Py_UCS4)(x); + +/* bool operations */ + +#define OP_BOOL_NOT(x, r, err) r = !(x); + /* _________________ certain implementations __________________ */ #ifndef HAVE_LONG_LONG @@ -197,4 +237,31 @@ if (p_rem) *p_rem = xmody; return xdivy; -} \ No newline at end of file +} +/* no editing below this point */ +/* following lines are generated by mkuint.py */ + +#define OP_UINT_IS_TRUE OP_INT_IS_TRUE +#define OP_UINT_INVERT OP_INT_INVERT +#define OP_UINT_POS OP_INT_POS +#define OP_UINT_NEG OP_INT_NEG +/* skipping OP_UINT_ABS */ +#define OP_UINT_EQ OP_INT_EQ +#define OP_UINT_NE OP_INT_NE +#define OP_UINT_LE OP_INT_LE +#define OP_UINT_GT OP_INT_GT +#define OP_UINT_LT OP_INT_LT +#define OP_UINT_GE OP_INT_GE +#define OP_UINT_CMP OP_INT_CMP +#define OP_UINT_ADD OP_INT_ADD +#define OP_UINT_SUB OP_INT_SUB +#define OP_UINT_MUL OP_INT_MUL +/* skipping OP_UINT_RSHIFT */ +/* skipping OP_UINT_LSHIFT */ +/* skipping OP_UINT_FLOORDIV */ +/* skipping OP_UINT_FLOORDIV_ZER */ +/* skipping OP_UINT_MOD */ +/* skipping OP_UINT_MOD_ZER */ +#define OP_UINT_AND OP_INT_AND +#define OP_UINT_OR OP_INT_OR +#define OP_UINT_XOR OP_INT_XOR Modified: pypy/branch/pycompiler/translator/c/ll_include.h ============================================================================== --- pypy/branch/pycompiler/translator/c/ll_include.h (original) +++ pypy/branch/pycompiler/translator/c/ll_include.h Fri Jul 1 18:28:54 2005 @@ -3,11 +3,16 @@ /*** C header subsection: operations on LowLevelTypes ***/ -#define OP_ZERO_MALLOC(size, r, err) { \ - r = (void*) PyObject_Malloc(size); \ - if (r == NULL) { PyErr_NoMemory(); FAIL(err) } \ - memset((void*) r, 0, size); \ - COUNT_MALLOC \ +/* XXX hack to initialize the refcount of global structures: officially, + we need a value equal to the number of references to this global from + other globals, plus one. This upper bound "approximation" will do... */ +#define REFCOUNT_IMMORTAL (INT_MAX/2) + +#define OP_ZERO_MALLOC(size, r, err) { \ + r = (void*) PyObject_Malloc(size); \ + if (r == NULL) FAIL_EXCEPTION(err, Exc_MemoryError, "out of memory")\ + memset((void*) r, 0, size); \ + COUNT_MALLOC \ } #define OP_FREE(p) { PyObject_Free(p); COUNT_FREE } Modified: pypy/branch/pycompiler/translator/c/node.py ============================================================================== --- pypy/branch/pycompiler/translator/c/node.py (original) +++ pypy/branch/pycompiler/translator/c/node.py Fri Jul 1 18:28:54 2005 @@ -1,8 +1,10 @@ from __future__ import generators from pypy.rpython.lltype import Struct, Array, FuncType, PyObjectType, typeOf from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType -from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void +from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void, OpaqueType +from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo from pypy.translator.c.funcgen import FunctionCodeGenerator +from pypy.translator.c.external import CExternalFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType @@ -19,10 +21,12 @@ class StructDefNode: refcount = None deallocator = None + static_deallocator = None def __init__(self, db, STRUCT, varlength=1): self.db = db self.STRUCT = STRUCT + self.LLTYPE = STRUCT self.varlength = varlength def setup(self): @@ -56,11 +60,40 @@ firstfieldname, firstfieldtype = self.fields[0] firstdefnode = db.gettypedefnode(T) self.refcount = '%s.%s' % (firstfieldname, firstdefnode.refcount) + # check here that there is enough run-time type information to + # handle this case + getRuntimeTypeInfo(STRUCT) + getRuntimeTypeInfo(T) - # is a specific deallocator needed? - if self.refcount and varlength == 1 and list(self.deallocator_lines('')): + # do we need deallocator(s)? + if self.refcount and varlength == 1: self.deallocator = db.namespace.uniquename('dealloc_'+self.name) + # are two deallocators needed (a dynamic one for DECREF, which checks + # the real type of the structure and calls the static deallocator) ? + rtti = None + if isinstance(STRUCT, GcStruct): + try: + rtti = getRuntimeTypeInfo(STRUCT) + except ValueError: + pass + if rtti is not None: + self.static_deallocator = db.namespace.uniquename( + 'staticdealloc_'+self.name) + fnptr = rtti._obj.query_funcptr + if fnptr is None: + raise NotImplementedError( + "attachRuntimeTypeInfo(): please provide a function") + self.rtti_query_funcptr = db.get(fnptr) + T = typeOf(fnptr).TO.ARGS[0] + self.rtti_query_funcptr_argtype = db.gettype(T) + else: + # is a deallocator really needed, or would it be empty? + if list(self.deallocator_lines('')): + self.static_deallocator = self.deallocator + else: + self.deallocator = None + def c_struct_field_name(self, name): return self.prefix + name @@ -82,12 +115,29 @@ line = '/* %s */' % line yield '\t' + line yield '};' - elif phase == 2 and self.deallocator: - yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) - for line in self.deallocator_lines('p->'): - yield '\t' + line - yield '\tOP_FREE(p);' - yield '}' + if self.deallocator: + yield 'void %s(struct %s *);' % (self.deallocator, self.name) + + elif phase == 2: + if self.static_deallocator: + yield 'void %s(struct %s *p) {' % (self.static_deallocator, + self.name) + for line in self.deallocator_lines('p->'): + yield '\t' + line + yield '\tOP_FREE(p);' + yield '}' + if self.deallocator and self.deallocator != self.static_deallocator: + yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) + yield '\tvoid (*staticdealloc) (void *);' + # the refcount should be 0; temporarily bump it to 1 + yield '\tp->%s = 1;' % (self.refcount,) + # cast 'p' to the type expected by the rtti_query function + yield '\tstaticdealloc = %s((%s) p);' % ( + self.rtti_query_funcptr, + cdecl(self.rtti_query_funcptr_argtype, '')) + yield '\tif (!--p->%s)' % (self.refcount,) + yield '\t\tstaticdealloc(p);' + yield '}' def deallocator_lines(self, prefix): STRUCT = self.STRUCT @@ -99,6 +149,17 @@ FIELD_T): yield line + def debug_offsets(self): + # generate number exprs giving the offset of the elements in the struct + STRUCT = self.STRUCT + for name in STRUCT._names: + FIELD_T = self.c_struct_field_type(name) + if FIELD_T == Void: + yield '-1' + else: + cname = self.c_struct_field_name(name) + yield 'offsetof(struct %s, %s)' % (self.name, cname) + class ArrayDefNode: refcount = None @@ -107,6 +168,7 @@ def __init__(self, db, ARRAY, varlength=1): self.db = db self.ARRAY = ARRAY + self.LLTYPE = ARRAY self.varlength = varlength def setup(self): @@ -176,6 +238,16 @@ yield '\t}' yield '}' + def debug_offsets(self): + # generate three offsets for debugging inspection + yield 'offsetof(struct %s, length)' % (self.name,) + if self.ARRAY.OF != Void: + yield 'offsetof(struct %s, items[0])' % (self.name,) + yield 'offsetof(struct %s, items[1])' % (self.name,) + else: + yield '-1' + yield '-1' + def generic_dealloc(db, expr, T): if isinstance(T, Ptr) and T._needsgc(): @@ -191,6 +263,7 @@ class ContainerNode: + includes = () def __init__(self, db, T, obj): self.db = db @@ -248,7 +321,7 @@ def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): - yield '\t1,' + yield '\tREFCOUNT_IMMORTAL,' defnode = self.db.gettypedefnode(self.T) for name in self.T._names: value = getattr(self.obj, name) @@ -274,8 +347,8 @@ def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): - yield '\t1,' - if self.T.OF == Void: + yield '\tREFCOUNT_IMMORTAL,' + if self.T.OF == Void or len(self.obj.items) == 0: yield '\t%d' % len(self.obj.items) yield '}' else: @@ -318,26 +391,40 @@ globalcontainer = True def __init__(self, db, T, obj): - graph = obj.graph # only user-defined functions with graphs for now - self.funcgen = FunctionCodeGenerator(graph, db) + self.funcgen = select_function_code_generator(obj, db) self.db = db self.T = T self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) - argnames = self.funcgen.argnames() - self.implementationtypename = db.gettype(T, argnames=argnames) - self.name = db.namespace.uniquename('g_' + self.basename()) + if self.funcgen: + argnames = self.funcgen.argnames() + self.implementationtypename = db.gettype(T, argnames=argnames) + if hasattr(obj, 'includes'): + self.includes = obj.includes + self.name = self.basename() + else: + self.name = db.namespace.uniquename('g_' + self.basename()) self.ptrname = self.name def basename(self): return self.obj._name def enum_dependencies(self): + if self.funcgen is None: + return [] return self.funcgen.allconstantvalues() + def forward_declaration(self): + if self.funcgen: + return ContainerNode.forward_declaration(self) + else: + return [] + def implementation(self): funcgen = self.funcgen + if funcgen is None: + return yield '%s {' % cdecl(self.implementationtypename, self.name) # # declare the local variables @@ -380,17 +467,34 @@ yield '}' -class CExternalFuncNode(ContainerNode): +def select_function_code_generator(fnptr, db): + if hasattr(fnptr, 'graph'): + cpython_exc = getattr(fnptr, 'exception_policy', None) == "CPython" + return FunctionCodeGenerator(fnptr.graph, db, cpython_exc) + elif getattr(fnptr, 'external', None) == 'C': + if getattr(fnptr, 'includes', None): + return None # assume no wrapper needed + else: + return CExternalFunctionCodeGenerator(fnptr, db) + else: + raise ValueError, "don't know how to generate code for %r" % (fnptr,) + + +class OpaqueNode(ContainerNode): globalcontainer = True + typename = 'void (@)(void *)' def __init__(self, db, T, obj): + assert T == RuntimeTypeInfo + assert isinstance(obj.about, GcStruct) self.db = db self.T = T self.obj = obj - #self.dependencies = {} - self.typename = db.gettype(T) #, who_asks=self) - self.name = obj._name - self.ptrname = self.name + defnode = db.gettypedefnode(obj.about) + self.implementationtypename = 'void (@)(struct %s *)' % ( + defnode.name,) + self.name = defnode.static_deallocator + self.ptrname = '((void (*)(void *)) %s)' % (self.name,) def enum_dependencies(self): return [] @@ -398,22 +502,6 @@ def implementation(self): return [] - def forward_declaration(self): - return [] - - def implementation(self): - return [] - - -def funcnodemaker(db, T, obj): - if hasattr(obj, 'graph'): - cls = FuncNode - elif getattr(obj, 'external', None) == 'C': - cls = CExternalFuncNode - else: - raise ValueError, "don't know about %r" % (obj,) - return cls(db, T, obj) - class PyObjectNode(ContainerNode): globalcontainer = True @@ -446,6 +534,7 @@ GcStruct: StructNode, Array: ArrayNode, GcArray: ArrayNode, - FuncType: funcnodemaker, + FuncType: FuncNode, + OpaqueType: OpaqueNode, PyObjectType: PyObjectNode, } Modified: pypy/branch/pycompiler/translator/c/primitive.py ============================================================================== --- pypy/branch/pycompiler/translator/c/primitive.py (original) +++ pypy/branch/pycompiler/translator/c/primitive.py Fri Jul 1 18:28:54 2005 @@ -1,3 +1,4 @@ +import sys from pypy.rpython.lltype import * # ____________________________________________________________ @@ -5,17 +6,22 @@ # Primitives def name_signed(value): - return '%d' % value + if value == -sys.maxint-1: # blame C + return '(-%dL-1L)' % sys.maxint + else: + return '%dL' % value def name_unsigned(value): assert value >= 0 - return '%d' % value + return '%dUL' % value + +def name_float(value): + return repr(value) def name_char(value): - value = value assert type(value) is str and len(value) == 1 if ' ' <= value < '\x7f': - return "'%s'" % (value.replace("'", r"\'"),) + return "'%s'" % (value.replace("\\", r"\\").replace("'", r"\'"),) else: return '%d' % ord(value) @@ -25,10 +31,17 @@ def name_void(value): return '/* nothing */' +def name_unichar(value): + assert type(value) is unicode and len(value) == 1 + return '%d' % ord(value) + + PrimitiveName = { Signed: name_signed, Unsigned: name_unsigned, + Float: name_float, Char: name_char, + UniChar: name_unichar, Bool: name_bool, Void: name_void, } @@ -36,7 +49,9 @@ PrimitiveType = { Signed: 'long @', Unsigned: 'unsigned long @', + Float: 'double @', Char: 'char @', + UniChar: 'Py_UCS4 @', Bool: 'char @', Void: 'void @', } @@ -44,7 +59,9 @@ PrimitiveErrorValue = { Signed: '-1', Unsigned: '((unsigned) -1)', + Float: '-1.0', Char: '((char) -1)', + UniChar: '((Py_UCS4) -1)', Bool: '((char) -1)', Void: '/* error */', } Modified: pypy/branch/pycompiler/translator/c/pyobj_include.h ============================================================================== --- pypy/branch/pycompiler/translator/c/pyobj_include.h (original) +++ pypy/branch/pycompiler/translator/c/pyobj_include.h Fri Jul 1 18:28:54 2005 @@ -7,13 +7,13 @@ #define op_bool(r,err,what) { \ int _retval = what; \ if (_retval < 0) { \ - FAIL(err) \ + CFAIL(err) \ } \ r = PyBool_FromLong(_retval); \ } #define op_richcmp(x,y,r,err,dir) \ - if (!(r=PyObject_RichCompare(x,y,dir))) FAIL(err) + if (!(r=PyObject_RichCompare(x,y,dir))) CFAIL(err) #define OP_LT(x,y,r,err) op_richcmp(x,y,r,err, Py_LT) #define OP_LE(x,y,r,err) op_richcmp(x,y,r,err, Py_LE) #define OP_EQ(x,y,r,err) op_richcmp(x,y,r,err, Py_EQ) @@ -29,71 +29,71 @@ #define OP_LEN(x,r,err) { \ int _retval = PyObject_Size(x); \ if (_retval < 0) { \ - FAIL(err) \ + CFAIL(err) \ } \ r = PyInt_FromLong(_retval); \ } -#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) FAIL(err) -#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) FAIL(err) -#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) FAIL(err) -#define OP_ABS(x,r,err) if (!(r=PyNumber_Absolute(x))) FAIL(err) - -#define OP_ADD(x,y,r,err) if (!(r=PyNumber_Add(x,y))) FAIL(err) -#define OP_SUB(x,y,r,err) if (!(r=PyNumber_Subtract(x,y))) FAIL(err) -#define OP_MUL(x,y,r,err) if (!(r=PyNumber_Multiply(x,y))) FAIL(err) -#define OP_TRUEDIV(x,y,r,err) if (!(r=PyNumber_TrueDivide(x,y))) FAIL(err) -#define OP_FLOORDIV(x,y,r,err) if (!(r=PyNumber_FloorDivide(x,y)))FAIL(err) -#define OP_DIV(x,y,r,err) if (!(r=PyNumber_Divide(x,y))) FAIL(err) -#define OP_MOD(x,y,r,err) if (!(r=PyNumber_Remainder(x,y))) FAIL(err) -#define OP_DIVMOD(x,y,r,err) if (!(r=PyNumber_Divmod(x,y))) FAIL(err) -#define OP_POW(x,y,z,r,err) if (!(r=PyNumber_Power(x,y,z))) FAIL(err) -#define OP_LSHIFT(x,y,r,err) if (!(r=PyNumber_Lshift(x,y))) FAIL(err) -#define OP_RSHIFT(x,y,r,err) if (!(r=PyNumber_Rshift(x,y))) FAIL(err) -#define OP_AND_(x,y,r,err) if (!(r=PyNumber_And(x,y))) FAIL(err) -#define OP_OR_(x,y,r,err) if (!(r=PyNumber_Or(x,y))) FAIL(err) -#define OP_XOR(x,y,r,err) if (!(r=PyNumber_Xor(x,y))) FAIL(err) +#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) CFAIL(err) +#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) CFAIL(err) +#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) CFAIL(err) +#define OP_ABS(x,r,err) if (!(r=PyNumber_Absolute(x))) CFAIL(err) + +#define OP_ADD(x,y,r,err) if (!(r=PyNumber_Add(x,y))) CFAIL(err) +#define OP_SUB(x,y,r,err) if (!(r=PyNumber_Subtract(x,y))) CFAIL(err) +#define OP_MUL(x,y,r,err) if (!(r=PyNumber_Multiply(x,y))) CFAIL(err) +#define OP_TRUEDIV(x,y,r,err) if (!(r=PyNumber_TrueDivide(x,y))) CFAIL(err) +#define OP_FLOORDIV(x,y,r,err) if (!(r=PyNumber_FloorDivide(x,y)))CFAIL(err) +#define OP_DIV(x,y,r,err) if (!(r=PyNumber_Divide(x,y))) CFAIL(err) +#define OP_MOD(x,y,r,err) if (!(r=PyNumber_Remainder(x,y))) CFAIL(err) +#define OP_DIVMOD(x,y,r,err) if (!(r=PyNumber_Divmod(x,y))) CFAIL(err) +#define OP_POW(x,y,z,r,err) if (!(r=PyNumber_Power(x,y,z))) CFAIL(err) +#define OP_LSHIFT(x,y,r,err) if (!(r=PyNumber_Lshift(x,y))) CFAIL(err) +#define OP_RSHIFT(x,y,r,err) if (!(r=PyNumber_Rshift(x,y))) CFAIL(err) +#define OP_AND_(x,y,r,err) if (!(r=PyNumber_And(x,y))) CFAIL(err) +#define OP_OR_(x,y,r,err) if (!(r=PyNumber_Or(x,y))) CFAIL(err) +#define OP_XOR(x,y,r,err) if (!(r=PyNumber_Xor(x,y))) CFAIL(err) #define OP_INPLACE_ADD(x,y,r,err) if (!(r=PyNumber_InPlaceAdd(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_SUB(x,y,r,err) if (!(r=PyNumber_InPlaceSubtract(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_MUL(x,y,r,err) if (!(r=PyNumber_InPlaceMultiply(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_TRUEDIV(x,y,r,err) if (!(r=PyNumber_InPlaceTrueDivide(x,y)))\ - FAIL(err) + CFAIL(err) #define OP_INPLACE_FLOORDIV(x,y,r,err)if(!(r=PyNumber_InPlaceFloorDivide(x,y)))\ - FAIL(err) + CFAIL(err) #define OP_INPLACE_DIV(x,y,r,err) if (!(r=PyNumber_InPlaceDivide(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_MOD(x,y,r,err) if (!(r=PyNumber_InPlaceRemainder(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_POW(x,y,r,err) if (!(r=PyNumber_InPlacePower(x,y,Py_None))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_LSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceLshift(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_RSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceRshift(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_AND(x,y,r,err) if (!(r=PyNumber_InPlaceAnd(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_OR(x,y,r,err) if (!(r=PyNumber_InPlaceOr(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_XOR(x,y,r,err) if (!(r=PyNumber_InPlaceXor(x,y))) \ - FAIL(err) + CFAIL(err) -#define OP_GETITEM(x,y,r,err) if (!(r=PyObject_GetItem1(x,y))) FAIL(err) -#define OP_SETITEM(x,y,z,r,err) if ((PyObject_SetItem1(x,y,z))<0) FAIL(err) \ +#define OP_GETITEM(x,y,r,err) if (!(r=PyObject_GetItem1(x,y))) CFAIL(err) +#define OP_SETITEM(x,y,z,r,err) if ((PyObject_SetItem1(x,y,z))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_DELITEM(x,y,r,err) if ((PyObject_DelItem(x,y))<0) FAIL(err) \ +#define OP_DELITEM(x,y,r,err) if ((PyObject_DelItem(x,y))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); #define OP_CONTAINS(x,y,r,err) op_bool(r,err,(PySequence_Contains(x,y))) -#define OP_GETATTR(x,y,r,err) if (!(r=PyObject_GetAttr(x,y))) FAIL(err) -#define OP_SETATTR(x,y,z,r,err) if ((PyObject_SetAttr(x,y,z))<0) FAIL(err) \ +#define OP_GETATTR(x,y,r,err) if (!(r=PyObject_GetAttr(x,y))) CFAIL(err) +#define OP_SETATTR(x,y,z,r,err) if ((PyObject_SetAttr(x,y,z))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_DELATTR(x,y,r,err) if ((PyObject_SetAttr(x,y,NULL))<0)FAIL(err) \ +#define OP_DELATTR(x,y,r,err) if ((PyObject_SetAttr(x,y,NULL))<0)CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_NEWSLICE(x,y,z,r,err) if (!(r=PySlice_New(x,y,z))) FAIL(err) +#define OP_NEWSLICE(x,y,z,r,err) if (!(r=PySlice_New(x,y,z))) CFAIL(err) #define OP_GETSLICE(x,y,z,r,err) { \ PyObject *__yo = y, *__zo = z; \ @@ -102,46 +102,46 @@ if (__zo == Py_None) __zo = NULL; \ if (!_PyEval_SliceIndex(__yo, &__y) || \ !_PyEval_SliceIndex(__zo, &__z) || \ - !(r=PySequence_GetSlice(x, __y, __z))) FAIL(err) \ + !(r=PySequence_GetSlice(x, __y, __z))) CFAIL(err) \ } #define OP_ALLOC_AND_SET(x,y,r,err) { \ /* XXX check for long/int overflow */ \ int __i, __x = PyInt_AsLong(x); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyList_New(__x))) FAIL(err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyList_New(__x))) CFAIL(err) \ for (__i=0; __i<__x; __i++) { \ Py_INCREF(y); \ PyList_SET_ITEM(r, __i, y); \ } \ } -#define OP_ITER(x,r,err) if (!(r=PyObject_GetIter(x))) FAIL(err) +#define OP_ITER(x,r,err) if (!(r=PyObject_GetIter(x))) CFAIL(err) #define OP_NEXT(x,r,err) if (!(r=PyIter_Next(x))) { \ if (!PyErr_Occurred()) PyErr_SetNone(PyExc_StopIteration); \ - FAIL(err) \ + CFAIL(err) \ } -#define OP_STR(x,r,err) if (!(r=PyObject_Str(x))) FAIL(err) -#define OP_REPR(x,r,err) if (!(r=PyObject_Repr(x))) FAIL(err) +#define OP_STR(x,r,err) if (!(r=PyObject_Str(x))) CFAIL(err) +#define OP_REPR(x,r,err) if (!(r=PyObject_Repr(x))) CFAIL(err) #define OP_ORD(s,r,err) { \ char *__c = PyString_AsString(s); \ int __len; \ - if ( !__c) FAIL(err) \ + if ( !__c) CFAIL(err) \ if ((__len = PyString_GET_SIZE(s)) != 1) { \ PyErr_Format(PyExc_TypeError, \ "ord() expected a character, but string of length %d found", \ __len); \ - FAIL(err) \ + CFAIL(err) \ } \ if (!(r = PyInt_FromLong((unsigned char)(__c[0])))) \ - FAIL(err) \ + CFAIL(err) \ } -#define OP_ID(x,r,err) if (!(r=PyLong_FromVoidPtr(x))) FAIL(err) +#define OP_ID(x,r,err) if (!(r=PyLong_FromVoidPtr(x))) CFAIL(err) #define OP_HASH(x,r,err) { \ long __hash = PyObject_Hash(x); \ - if (__hash == -1 && PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__hash))) FAIL(err) \ + if (__hash == -1 && PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__hash))) CFAIL(err) \ } #define OP_HEX(x,r,err) { \ @@ -150,9 +150,9 @@ __nb->nb_hex == NULL) { \ PyErr_SetString(PyExc_TypeError, \ "hex() argument can't be converted to hex"); \ - FAIL(err) \ + CFAIL(err) \ } \ - if (!(r = (*__nb->nb_hex)(x))) FAIL(err) \ + if (!(r = (*__nb->nb_hex)(x))) CFAIL(err) \ } #define OP_OCT(x,r,err) { \ PyNumberMethods *__nb; \ @@ -160,32 +160,32 @@ __nb->nb_oct == NULL) { \ PyErr_SetString(PyExc_TypeError, \ "oct() argument can't be converted to oct"); \ - FAIL(err) \ + CFAIL(err) \ } \ - if (!(r = (*__nb->nb_oct)(x))) FAIL(err) \ + if (!(r = (*__nb->nb_oct)(x))) CFAIL(err) \ } #define OP_INT(x,r,err) { \ long __val = PyInt_AsLong(x); \ - if (__val == -1 && PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__val))) FAIL (err) \ + if (__val == -1 && PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ } #define OP_FLOAT(x,r,err) { \ double __val = PyFloat_AsDouble(x); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyFloat_FromDouble(__val))) FAIL (err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyFloat_FromDouble(__val))) CFAIL (err) \ } #define OP_CMP(x,y,r,err) { \ int __val = PyObject_Compare(x, y); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__val))) FAIL (err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ } #define OP_SIMPLE_CALL(args,r,err) if (!(r=PyObject_CallFunctionObjArgs args)) \ - FAIL(err) -#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) FAIL(err) + CFAIL(err) +#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) CFAIL(err) /* Needs to act like getattr(x, '__class__', type(x)) */ #define OP_TYPE(x,r,err) { \ @@ -205,27 +205,17 @@ /*** operations with a variable number of arguments ***/ -#define OP_NEWLIST0(r,err) if (!(r=PyList_New(0))) FAIL(err) -#define OP_NEWLIST(args,r,err) if (!(r=PyList_Pack args)) FAIL(err) -#define OP_NEWDICT0(r,err) if (!(r=PyDict_New())) FAIL(err) -#define OP_NEWDICT(args,r,err) if (!(r=PyDict_Pack args)) FAIL(err) -#define OP_NEWTUPLE(args,r,err) if (!(r=PyTuple_Pack args)) FAIL(err) +#define OP_NEWLIST0(r,err) if (!(r=PyList_New(0))) CFAIL(err) +#define OP_NEWLIST(args,r,err) if (!(r=PyList_Pack args)) CFAIL(err) +#define OP_NEWDICT0(r,err) if (!(r=PyDict_New())) CFAIL(err) +#define OP_NEWDICT(args,r,err) if (!(r=PyDict_Pack args)) CFAIL(err) +#define OP_NEWTUPLE(args,r,err) if (!(r=PyTuple_Pack args)) CFAIL(err) /*** argument parsing ***/ #define OP_DECODE_ARG(fname, pos, name, vargs, vkwds, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, NULL))) FAIL(err) + if (!(r=decode_arg(fname, pos, name, vargs, vkwds, NULL))) CFAIL(err) #define OP_DECODE_ARG_DEF(fname, pos, name, vargs, vkwds, def, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) FAIL(err) + if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) CFAIL(err) #define OP_CHECK_NO_MORE_ARG(fname, n, vargs, r, err) \ - if (check_no_more_arg(fname, n, vargs) < 0) FAIL(err) - -/*** conversions, reference counting ***/ - -#define OP_INCREF_pyobj(o) Py_INCREF(o); -#define OP_DECREF_pyobj(o) Py_DECREF(o); -#define CONV_TO_OBJ_pyobj(o) ((void)Py_INCREF(o), o) -#define CONV_FROM_OBJ_pyobj(o) ((void)Py_INCREF(o), o) - -#define OP_INCREF_borrowedpyobj(o) /* nothing */ -#define OP_DECREF_borrowedpyobj(o) /* nothing */ + if (check_no_more_arg(fname, n, vargs) < 0) CFAIL(err) Modified: pypy/branch/pycompiler/translator/c/support.py ============================================================================== --- pypy/branch/pycompiler/translator/c/support.py (original) +++ pypy/branch/pycompiler/translator/c/support.py Fri Jul 1 18:28:54 2005 @@ -59,3 +59,43 @@ double long typedef else register union ''') + + +def gen_assignments(assignments): + # Generate a sequence of assignments that is possibly reordered + # to avoid clashes -- i.e. do the equivalent of a tuple assignment, + # reading all sources first, writing all targets next, but optimized + + allsources = [] + src2dest = {} + types = {} + assignments = list(assignments) + for typename, dest, src in assignments: + if src != dest: # ignore 'v=v;' + allsources.append(src) + src2dest.setdefault(src, []).append(dest) + types[dest] = typename + + for starting in allsources: + # starting from some starting variable, follow a chain of assignments + # 'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;' + v = starting + srcchain = [] + while src2dest.get(v): + srcchain.append(v) + v = src2dest[v].pop(0) + if v == starting: + break # loop + if not srcchain: + continue # already done in a previous chain + srcchain.reverse() # ['vn-1', ..., 'v2', 'v1', 'starting'] + code = [] + for pair in zip([v] + srcchain[:-1], srcchain): + code.append('%s = %s;' % pair) + if v == starting: + # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;' + typename = types[starting] + tmpdecl = cdecl(typename, 'tmp') + code.insert(0, '{ %s = %s;' % (tmpdecl, starting)) + code[-1] = '%s = tmp; }' % (srcchain[-2],) + yield ' '.join(code) Modified: pypy/branch/pycompiler/translator/c/test/test_database.py ============================================================================== --- pypy/branch/pycompiler/translator/c/test/test_database.py (original) +++ pypy/branch/pycompiler/translator/c/test/test_database.py Fri Jul 1 18:28:54 2005 @@ -27,7 +27,7 @@ def test_primitive(): db = LowLevelDatabase() - assert db.get(5) == '5' + assert db.get(5) == '5L' assert db.get(True) == '1' def test_struct(): @@ -236,26 +236,26 @@ db.complete() dump_on_stdout(db) -def test_nested_gcstruct(): - S1 = GcStruct('inlined', ('x', Signed), ('y', Ptr(PyObject))) - S = GcStruct('testing', ('head', S1), - ('ptr2', Ptr(S1)), - ('z', Signed)) - def ll_f(x): - ptr2 = malloc(S1) - ptr2.x = x+1 - s = malloc(S) - s.head.x = x - s.ptr2 = ptr2 - return s.head.x * s.ptr2.x - t = Translator(ll_f) - t.annotate([int]) - t.specialize() +##def test_nested_gcstruct(): +## S1 = GcStruct('inlined', ('x', Signed), ('y', Ptr(PyObject))) +## S = GcStruct('testing', ('head', S1), +## ('ptr2', Ptr(S1)), +## ('z', Signed)) +## def ll_f(x): +## ptr2 = malloc(S1) +## ptr2.x = x+1 +## s = malloc(S) +## s.head.x = x +## s.ptr2 = ptr2 +## return s.head.x * s.ptr2.x +## t = Translator(ll_f) +## t.annotate([int]) +## t.specialize() - db = LowLevelDatabase(t) - db.get(getfunctionptr(t, ll_f)) - db.complete() - dump_on_stdout(db) +## db = LowLevelDatabase(t) +## db.get(getfunctionptr(t, ll_f)) +## db.complete() +## dump_on_stdout(db) def test_array(): A = GcArray(('obj', Ptr(PyObject))) Modified: pypy/branch/pycompiler/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/pycompiler/translator/c/test/test_genc.py (original) +++ pypy/branch/pycompiler/translator/c/test/test_genc.py Fri Jul 1 18:28:54 2005 @@ -58,12 +58,12 @@ assert f1(5) == 10 assert f1(x=5) == 10 assert f1(-123) == -246 - py.test.raises(TypeError, f1, "world") # check that it's really typed - py.test.raises(TypeError, f1) - py.test.raises(TypeError, f1, 2, 3) - py.test.raises(TypeError, f1, 2, x=2) - #py.test.raises(TypeError, f1, 2, y=2) XXX missing a check at the moment assert module.malloc_counters() == (0, 0) + py.test.raises(Exception, f1, "world") # check that it's really typed + py.test.raises(Exception, f1) + py.test.raises(Exception, f1, 2, 3) + py.test.raises(Exception, f1, 2, x=2) + #py.test.raises(Exception, f1, 2, y=2) XXX missing a check at the moment def test_rlist(): @@ -142,3 +142,88 @@ assert f1(12, "hello") == "hello" mallocs, frees = module.malloc_counters() assert mallocs == frees + + +def test_runtime_type_info(): + S = GcStruct('s', ('is_actually_s1', Bool)) + S1 = GcStruct('s1', ('sub', S)) + attachRuntimeTypeInfo(S) + attachRuntimeTypeInfo(S1) + def rtti_S(p): + if p.is_actually_s1: + return getRuntimeTypeInfo(S1) + else: + return getRuntimeTypeInfo(S) + def rtti_S1(p): + return getRuntimeTypeInfo(S1) + def does_stuff(): + p = malloc(S) + p.is_actually_s1 = False + p1 = malloc(S1) + p1.sub.is_actually_s1 = True + # and no crash when p and p1 are decref'ed + return sys + t = Translator(does_stuff) + t.annotate([]) + from pypy.rpython.rtyper import RPythonTyper + rtyper = RPythonTyper(t.annotator) + rtyper.attachRuntimeTypeInfoFunc(S, rtti_S) + rtyper.attachRuntimeTypeInfoFunc(S1, rtti_S1) + rtyper.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(does_stuff)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + f1() + mallocs, frees = module.malloc_counters() + assert mallocs == frees + +def test_time_clock(): + import time + def does_stuff(): + return time.clock() + t = Translator(does_stuff) + t.annotate([]) + t.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(does_stuff)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + t0 = time.clock() + t1 = f1() + assert type(t1) is float + t2 = time.clock() + assert t0 <= t1 <= t2 + mallocs, frees = module.malloc_counters() + assert mallocs == frees + +def test_str(): + def call_str(o): + return str(o) + t = Translator(call_str) + t.annotate([object]) + t.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(call_str)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + lst = (1, [5], "'hello'", lambda x: x+1) + res = f1(lst) + assert res == str(lst) + mallocs, frees = module.malloc_counters() + assert mallocs == frees Modified: pypy/branch/pycompiler/translator/c/wrapper.py ============================================================================== --- pypy/branch/pycompiler/translator/c/wrapper.py (original) +++ pypy/branch/pycompiler/translator/c/wrapper.py Fri Jul 1 18:28:54 2005 @@ -118,4 +118,5 @@ PyObjPtr], PyObjPtr), wgraph.name, - graph = wgraph) + graph = wgraph, + exception_policy = "CPython") Modified: pypy/branch/pycompiler/translator/geninterplevel.py ============================================================================== --- pypy/branch/pycompiler/translator/geninterplevel.py (original) +++ pypy/branch/pycompiler/translator/geninterplevel.py Fri Jul 1 18:28:54 2005 @@ -57,6 +57,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments from pypy.rpython.rarithmetic import r_int, r_uint +from pypy.translator.backendoptimization import SSI_to_SSA from pypy.translator.translator import Translator from pypy.objspace.flow import FlowObjSpace @@ -77,7 +78,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.1' # bump this for substantial changes +GI_VERSION = '1.1.2' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): @@ -302,8 +303,10 @@ src = linklocalvars[a1] else: src = self.expr(a1, localscope) - left.append(self.expr(a2, localscope)) - right.append(src) + dest = self.expr(a2, localscope) + if src != dest: + left.append(dest) + right.append(src) if left: # anything at all? txt = "%s = %s" % (", ".join(left), ", ".join(right)) if len(txt) <= 65: # arbitrary @@ -1000,6 +1003,14 @@ return name # no success def gen_rpyfunction(self, func): + try: + graph = self.translator.getflowgraph(func) + except Exception, e: + print 20*"*", e + print func + raise + SSI_to_SSA(graph) + checkgraph(graph) f = self.f print >> f, "##SECTION##" # simple to split, afterwards @@ -1011,7 +1022,7 @@ func.func_code.co_firstlineno) print >> f, "##SECTION##" localscope = self.namespace.localScope() - body = list(self.rpyfunction_body(func, localscope)) + body = list(self.rpyfunction_body(graph, localscope)) name_of_defaults = [self.nameof(x, debug=('Default argument of', func)) for x in (func.func_defaults or ())] self.gen_global_declarations() @@ -1022,14 +1033,14 @@ assert cname.startswith('gfunc_') f_name = 'f_' + cname[6:] - # collect all the local variables - graph = self.translator.getflowgraph(func) - localslst = [] - def visit(node): - if isinstance(node, Block): - localslst.extend(node.getvariables()) - traverse(visit, graph) - localnames = [self.expr(a, localscope) for a in uniqueitems(localslst)] +## # collect all the local variables +## graph = self.translator.getflowgraph(func) +## localslst = [] +## def visit(node): +## if isinstance(node, Block): +## localslst.extend(node.getvariables()) +## traverse(visit, graph) +## localnames = [self.expr(a, localscope) for a in uniqueitems(localslst)] # collect all the arguments vararg = varkw = None @@ -1110,7 +1121,7 @@ if docstr is not None: print >> f, docstr - fast_locals = [arg for arg in localnames if arg not in fast_set] +## fast_locals = [arg for arg in localnames if arg not in fast_set] ## # if goto is specialized, the false detection of ## # uninitialized variables goes away. ## if fast_locals and not self.specialize_goto: @@ -1134,25 +1145,7 @@ pass # del self.translator.flowgraphs[func] # got duplicate flowgraphs when doing this! - def rpyfunction_body(self, func, localscope): - try: - graph = self.translator.getflowgraph(func) - except Exception, e: - print 20*"*", e - print func - raise - # not needed, we use tuple assignment! - # remove_direct_loops(graph) - checkgraph(graph) - - allblocks = [] - - f = self.f - t = self.translator - #t.simplify(func) - graph = t.getflowgraph(func) - - + def rpyfunction_body(self, graph, localscope): start = graph.startblock allblocks = ordered_blocks(graph) nblocks = len(allblocks) Modified: pypy/branch/pycompiler/translator/goal/query.py ============================================================================== --- pypy/branch/pycompiler/translator/goal/query.py (original) +++ pypy/branch/pycompiler/translator/goal/query.py Fri Jul 1 18:28:54 2005 @@ -1,5 +1,6 @@ # functions to query information out of the translator and annotator from the debug prompt of translate_pypy import types +import re import pypy.annotation.model as annmodel import pypy.objspace.flow.model as flowmodel @@ -251,6 +252,16 @@ if len(callb[x]) >= 2 and x not in b_nb: print ' '.join([prettycallable((classdef and classdef.cls, func)) for (classdef,func) in callb[x].keys()]) +def pretty_els(objs): + accum = [] + for classdef, obj in objs: + cls = classdef and classdef.cls + accum.append(prettycallable((cls, obj))) + els = ' '.join(accum) + if len(accum) == 1: + return els + else: + return "{%s}" % els def pbccall(translator): fams = translator.annotator.getpbccallfamilies().root_info.itervalues() @@ -282,17 +293,6 @@ else: return "in total %d %s" % (nels, prettycallable(kinds)) - def pretty_els(objs): - accum = [] - for classdef, obj in objs: - cls = classdef and classdef.cls - accum.append(prettycallable((cls, obj))) - els = ' '.join(accum) - if len(accum) == 1: - return els - else: - return "{%s}" % els - items = one_pattern_fams.items() items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) # sort by pattern and then by els @@ -311,6 +311,129 @@ print " - many callables, many patterns -" print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) +def pbcbmsanity(translator): + callb = translator.annotator.getpbccallables() + bk = translator.annotator.bookkeeper + bmeths = [x for x in callb if isinstance(x, types.MethodType) and x.im_self is not None] + print "%d bound-methods" % len(bmeths) + fams = translator.annotator.getpbccallfamilies() + plural_bm_families = {} + one_el = 0 + for bm in bmeths: + notpbc = bm.im_self not in bk.pbccache + freestanding = bm.im_func in callb + if notpbc or freestanding: + print "! %s," % bm, + if notpbc: + print "of non-PBC %s,", + if freestanding: + print "found freestanding too" + bm_fam = fams[(None, bm)] + if len(bm_fam.objects) == 1: + one_el += 1 + else: + plural_bm_families[bm_fam] = True + print "%d families of one bound-method" % one_el + print "%d families with more than just one bound-method" % len(plural_bm_families) + for bm_fam in plural_bm_families: + print pretty_els(bm_fam.objects) + return plural_bm_families + +class Counters(dict): + + def __getitem__(self, outcome): + if (isinstance(outcome, annmodel.SomeObject) or + isinstance(outcome, tuple) and outcome and + isinstance(outcome[0], annmodel.SomeObject)): + for k in self.iterkeys(): + if k == outcome: + outcome = k + break + else: + raise KeyError + return dict.__getitem__(self, outcome) + + def get(self, outcome, defl): + try: + return self[outcome] + except KeyError: + return defl + + def __setitem__(self, outcome, c): + if (isinstance(outcome, annmodel.SomeObject) or + isinstance(outcome, tuple) and outcome and + isinstance(outcome[0], annmodel.SomeObject)): + for k in self.iterkeys(): + if k == outcome: + outcome = k + break + return dict.__setitem__(self, outcome, c) + + +def keyrepr(k): + if isinstance(k, tuple): + return "(%s)" % ', '.join([keyrepr(x) for x in k]) + else: + return str(k) + +def statsfor(t, category): + stats = t.annotator.bookkeeper.stats + for_category = stats.classify[category] + print "%s total = %d" % (category, len(for_category)) + counters = Counters() + for pos, outcome in for_category.iteritems(): + counters[outcome] = counters.get(outcome, 0) + 1 + + w = max([len(keyrepr(o)) for o in counters.keys()])+1 + if w < 60: + for outcome, n in counters.iteritems(): + print "%*s | %d" % (w, keyrepr(outcome), n) + else: + for outcome, n in counters.iteritems(): + print "%s | %d" % (keyrepr(outcome), n) + +def statsforstrformat(t): + stats = t.annotator.bookkeeper.stats + stats = stats.classify['strformat'] + result = {} + for fmt, args in stats.itervalues(): + fmts = re.findall("%l?.", fmt) + if not isinstance(args, tuple): + args = (args,) + for f, a in zip(fmts, args): + result[(f,a)] = result.get((f,a), 0) + 1 + for (f,a), c in result.iteritems(): + print "%s %s %d" % (f, keyrepr(a), c) + +def statbuiltins(t): + stats = t.annotator.bookkeeper.stats.classify + for k in stats: + if k.startswith('__builtin__'): + statsfor(t, k) + +def dicts(t): + ann = t.annotator + r = [] + + def sdicts(): + for so in ann.bindings.itervalues(): + if isinstance(so, annmodel.SomeDict): + yield so + for so in ann.bookkeeper.immutable_cache.itervalues(): + if isinstance(so, annmodel.SomeDict): + yield so + + for so in sdicts(): + sk, sv = so.dictdef.dictkey.s_value, so.dictdef.dictvalue.s_value + for x in r: + if x == (sk, sv): + break + else: + r.append((sk, sv)) + + for x in r: + print x + # debug helper def tryout(f, *args): try: Deleted: /pypy/branch/pycompiler/translator/goal/targetpypy0.py ============================================================================== --- /pypy/branch/pycompiler/translator/goal/targetpypy0.py Fri Jul 1 18:28:54 2005 +++ (empty file) @@ -1,33 +0,0 @@ -from pypy.objspace import dummy -from pypy.interpreter.pycode import PyCode - -# __________ Entry point __________ - -def entry_point(code, w_loc): - code2 = PyCode(space) - code2 = code2._from_code(code) - code2.exec_code(space, space.wrap({}), w_loc) - -# _____ Define and setup target _____ - -def target(): - global space - space = dummy.DummyObjSpace() - - from pypy.interpreter import pycode - - pycode.setup_frame_classes() - - from pypy.interpreter import pyopcode - - # cheat - space._gatewaycache.content[pyopcode.app] = space.newdict([]) - - return entry_point,[object, dummy.W_Obj] - -# _____ Run translated _____ - -def run(c_entry_point): - w_result = c_entry_point(compile("a+b","","eval"),dummy.W_Obj()) - print w_result - Deleted: /pypy/branch/pycompiler/translator/goal/targetpypy1.py ============================================================================== --- /pypy/branch/pycompiler/translator/goal/targetpypy1.py Fri Jul 1 18:28:54 2005 +++ (empty file) @@ -1,75 +0,0 @@ -from pypy.objspace.std.objspace import StdObjSpace, W_Object -from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.std import stdtypedef - -# __________ Entry point __________ - -operations = "mul add sub div mod lshift rshift floordiv truediv ".split() - -def entry_point(): - w_a = W_IntObject(space, -7) - w_b = W_IntObject(space, 6) - results_w = [mmentrypoints[op](space, w_a, w_b) for op in operations] - return [space.unwrap(each) for each in resuls_w] - -# flatten the above code, to get a nicer look -def make_flat_code(): - g = globals() - # make globals constants from the operations - code = """def entry_point(): - import sys - w_a = W_IntObject(space, -7) - # -sys.maxint-1 crashes: genc problem with OP_SUB and int constant - # when implementing lshift_Long_Long and rshift__Long_Long - w_b = W_IntObject(space, 6) - results_w = [] - append = results_w.append -""" - for op in operations: - g["op_%s" % op] = mmentrypoints[op] - line = " append(op_%s(space, w_a, w_b))" % op - code += line + '\n' - code += " return [space.unwrap(each) for each in results_w]\n" - print code - exec code in g - -# _____ Define and setup target _____ -def target(): - global space, mmentrypoints - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - space = StdObjSpace() - # call cache filling code *not* needed here - - # ------------------------------------------------------------ - mmentrypoints = {} - for name in operations: - mm = getattr(space.MM, name) - exprargs, expr, miniglobals, fallback = ( - mm.install_not_sliced(space.model.typeorder, baked_perform_call=False)) - func = stdtypedef.make_perform_trampoline('__mm_'+name, - exprargs, expr, miniglobals, - mm) - mmentrypoints[name] = func - # ------------------------------------------------------------ - - # further call the entry_point once to trigger building remaining - # caches (as far as analyzing the entry_point is concerned) - make_flat_code() - entry_point() - - return entry_point, [] - -# _____ Run translated _____ - -def run(c_entry_point): - res = c_entry_point() - print res - import operator - assert res == [getattr(operator, name)(-7, 6) for name in operations] - -if __name__ == "__main__": - # just run it without translation - target() - run(entry_point) - \ No newline at end of file Modified: pypy/branch/pycompiler/translator/goal/targetpypymain.py ============================================================================== --- pypy/branch/pycompiler/translator/goal/targetpypymain.py (original) +++ pypy/branch/pycompiler/translator/goal/targetpypymain.py Fri Jul 1 18:28:54 2005 @@ -1,6 +1,9 @@ import os, sys from pypy.objspace.std.objspace import StdObjSpace -from pypy.annotation.model import * +# XXX from pypy.annotation.model import * +# since we are execfile()'ed this would pull some +# weird objects into the globals, which we would try to pickle. +from pypy.annotation.model import SomeList, SomeString from pypy.annotation.listdef import ListDef from pypy.interpreter import gateway Modified: pypy/branch/pycompiler/translator/goal/targetrpystone.py ============================================================================== --- pypy/branch/pycompiler/translator/goal/targetrpystone.py (original) +++ pypy/branch/pycompiler/translator/goal/targetrpystone.py Fri Jul 1 18:28:54 2005 @@ -1,36 +1,12 @@ -import buildcache2 -from pypy.objspace.std.objspace import StdObjSpace -from pypy.translator.test import rpystone +from pypy.translator.goal import targetrpystonex -# __________ Entry point __________ - -LOOPS = 150000 +LOOPS = 2000000 -# rpystone.setslow(False) -def entry_point(): - rpystone.entrypoint(LOOPS) - +# __________ Entry point __________ # _____ Define and setup target _____ -def target(): - global space, mmentrypoints - space = StdObjSpace() - - # ------------------------------------------------------------ - - return entry_point, [] - # _____ Run translated _____ -def run(c_entry_point): - res_w = c_entry_point() - print res_w - print "CPython:" - rpystone.entrypoint(50000) - -if __name__ == "__main__": - # just run it without translation - LOOPS = 50000 - target() - run(entry_point) - \ No newline at end of file +(entry_point, + target, + run) = targetrpystonex.make_target_definition(LOOPS) Deleted: /pypy/branch/pycompiler/translator/goal/targetrpystone2.py ============================================================================== --- /pypy/branch/pycompiler/translator/goal/targetrpystone2.py Fri Jul 1 18:28:54 2005 +++ (empty file) @@ -1,36 +0,0 @@ -import buildcache2 -from pypy.objspace.std.objspace import StdObjSpace -from pypy.translator.test import rpystone - -# __________ Entry point __________ - -LOOPS = 1000000 - -rpystone.setslow(False) - -def entry_point(): - rpystone.entrypoint(LOOPS) - -# _____ Define and setup target _____ -def target(): - global space, mmentrypoints - space = StdObjSpace() - - # ------------------------------------------------------------ - - return entry_point, [] - -# _____ Run translated _____ - -def run(c_entry_point): - res_w = c_entry_point() - print res_w - print "CPython:" - rpystone.entrypoint(50000) - -if __name__ == "__main__": - # just run it without translation - LOOPS = 50000 - target() - run(entry_point) - \ No newline at end of file Modified: pypy/branch/pycompiler/translator/goal/translate_pypy.py ============================================================================== --- pypy/branch/pycompiler/translator/goal/translate_pypy.py (original) +++ pypy/branch/pycompiler/translator/goal/translate_pypy.py Fri Jul 1 18:28:54 2005 @@ -15,45 +15,54 @@ -no-a Don't infer annotations, just translate everything -no-s Don't simplify the graph after annotation -no-t Don't type-specialize the graph operations with the C typer + -no-o Don't do backend-oriented optimizations -no-c Don't generate the C code + -fork (UNIX) Create a restartable checkpoint after annotation -c Generate the C code, but don't compile it -o Generate and compile the C code, but don't run it - -no-mark-some-objects - Do not mark functions that have SomeObject in their signature. -tcc Equivalent to the envvar PYPY_CC='tcc -shared -o "%s.so" "%s.c"' -- http://fabrice.bellard.free.fr/tcc/ -no-d Disable recording of debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed + -no-snapshot + Don't redirect imports to the translation snapshot + -save filename + saves the translator to a file. The file type can either + be .py or .zip (recommended). + -load filename + restores the translator from a file. The file type must + be either .py or .zip . """ import autopath, sys, os -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -basedir = autopath.this_dir +if '-no-snapshot' not in sys.argv: + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + basedir = autopath.this_dir -pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') + pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') -if not os.path.isdir(pypy_translation_snapshot_dir): - print """ -Translation is performed on a specific revision of PyPy which lives on -a branch. This needs to be checked out into translator/goal with: + if not os.path.isdir(pypy_translation_snapshot_dir): + print """ + Translation is performed on a specific revision of PyPy which lives on + a branch. This needs to be checked out into translator/goal with: -svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot -"""[1:] - sys.exit(2) + svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot + """[1:] + sys.exit(2) -# override imports from pypy head with imports from pypy-translation-snapshot -import pypy -pypy.__path__.insert(0, pypy_translation_snapshot_dir) + # override imports from pypy head with imports from pypy-translation-snapshot + import pypy + pypy.__path__.insert(0, pypy_translation_snapshot_dir) -# complement imports from pypy.objspace (from pypy-translation-snapshot) -# with pypy head objspace/ -import pypy.objspace -pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) + # complement imports from pypy.objspace (from pypy-translation-snapshot) + # with pypy head objspace/ + import pypy.objspace + pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) -print "imports redirected to pypy-translation-snapshot." + print "imports redirected to pypy-translation-snapshot." -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx import threading, pdb @@ -65,7 +74,7 @@ from pypy.annotation.model import SomeObject from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_print - +from pypy.translator.pickle.main import load, save # XXX this tries to make compiling faster from pypy.translator.tool import buildpyxmodule @@ -77,25 +86,38 @@ # __________ Main __________ def analyse(target): - global t, entry_point - - entry_point, inputtypes = target() + global t, entry_point, inputtypes - t = Translator(entry_point, verbose=True, simplifying=True) + if target: + entry_point, inputtypes = target() + t = Translator(entry_point, verbose=True, simplifying=True) + a = None + else: + # otherwise we have been loaded + a = t.annotator + t.frozen = False if listen_port: run_async_server() if not options['-no-a']: + print 'Annotating...' a = t.annotate(inputtypes, policy=PyPyAnnotatorPolicy()) sanity_check_exceptblocks(t) - worstblocks_topten(a) - if not options['-no-s']: - a.simplify() - if not options['-no-t']: - a.specialize() + worstblocks_topten(a, 3) + find_someobjects(t) + if a and not options['-no-s']: + print 'Simplifying...' + a.simplify() + if a and options['-fork']: + from pypy.translator.goal import unixcheckpoint + unixcheckpoint.restartable_point() + if a and not options['-no-t']: + print 'Specializing...' + t.specialize() + if not options['-no-o']: + print 'Back-end optimizations...' + t.backend_optimizations() + if a: t.frozen = True # cannot freeze if we don't have annotations - if not options['-no-mark-some-objects']: - options['-no-mark-some-objects'] = True # Do not do this again - find_someobjects(t) def sanity_check_exceptblocks(translator): annotator = translator.annotator @@ -225,6 +247,8 @@ targetspec = 'targetpypymain' huge = 100 + load_file = None + save_file = None options = {'-text': False, '-no-c': False, @@ -234,11 +258,17 @@ '-no-a': False, '-no-s': False, '-no-t': False, + '-no-o': False, '-tcc': False, '-no-d': False, + '-no-snapshot' : False, + '-load': False, + '-save': False, + '-fork': False, } listen_port = None - for arg in sys.argv[1:]: + argiter = iter(sys.argv[1:]) + for arg in argiter: if arg in ('-h', '--help'): print __doc__.strip() sys.exit() @@ -256,6 +286,11 @@ else: assert arg in options, "unknown option %r" % (arg,) options[arg] = True + if arg == '-load': + load_file = argiter.next() + loaded_dic = load(load_file) + if arg == '-save': + save_file = argiter.next() if options['-tcc']: os.environ['PYPY_CC'] = 'tcc -shared -o "%s.so" "%s.c"' if options['-no-d']: @@ -455,12 +490,41 @@ cleanup() try: - targetspec_dic = {} - sys.path.insert(0, os.path.dirname(targetspec)) - execfile(targetspec+'.py',targetspec_dic) - print "Analysing target as defined by %s" % targetspec - analyse(targetspec_dic['target']) + if load_file: + t = loaded_dic['trans'] + entry_point = t.entrypoint + inputtypes = loaded_dic['inputtypes'] + targetspec_dic = loaded_dic['targetspec_dic'] + targetspec = loaded_dic['targetspec'] + old_options = loaded_dic['options'] + for name in '-no-a -no-s -no-t -no-o'.split(): + # if one of these options has not been set, before, + # then the action has been done and must be prevented, now. + if not old_options[name]: + if options[name]: + print 'option %s is implied by the load' % name + options[name] = True + print "continuing Analysis as defined by %s, loaded from %s" %( + targetspec, load_file) + print 'options in effect:', options + analyse(None) + else: + targetspec_dic = {} + sys.path.insert(0, os.path.dirname(targetspec)) + execfile(targetspec+'.py', targetspec_dic) + print "Analysing target as defined by %s" % targetspec + print 'options in effect:', options + analyse(targetspec_dic['target']) print '-'*60 + if save_file: + print 'saving state to %s' % save_file + save(t, save_file, + trans=t, + inputtypes=inputtypes, + targetspec=targetspec, + targetspec_dic=targetspec_dic, + options=options, + ) if options['-no-c']: print 'Not generating C code.' elif options['-c']: Modified: pypy/branch/pycompiler/translator/llvm/build_llvm_module.py ============================================================================== --- pypy/branch/pycompiler/translator/llvm/build_llvm_module.py (original) +++ pypy/branch/pycompiler/translator/llvm/build_llvm_module.py Fri Jul 1 18:28:54 2005 @@ -14,7 +14,7 @@ from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture -debug = False +debug = True class CompileError(exceptions.Exception): pass Modified: pypy/branch/pycompiler/translator/llvm/llvmbc.py ============================================================================== --- pypy/branch/pycompiler/translator/llvm/llvmbc.py (original) +++ pypy/branch/pycompiler/translator/llvm/llvmbc.py Fri Jul 1 18:28:54 2005 @@ -97,8 +97,7 @@ #Shift instructions def shift_instruction(self, instr, l_target, l_a, l_b): self.phi_done = True - assert l_target.llvmtype() == l_a.llvmtype() - #assert l_b.llvmtype() == 'ubyte' #or cast to ubyte or assuma nothing goes wrong + # XXX hack: just assume that l_b is of the appropriate type s = "%s = %s %s, ubyte %s" % (l_target.llvmname(), instr, l_a.typed_name(), l_b.llvmname()) self.instructions.append(s) Modified: pypy/branch/pycompiler/translator/llvm/test/llvmsnippet.py ============================================================================== --- pypy/branch/pycompiler/translator/llvm/test/llvmsnippet.py (original) +++ pypy/branch/pycompiler/translator/llvm/test/llvmsnippet.py Fri Jul 1 18:28:54 2005 @@ -62,6 +62,13 @@ def return_none(): pass +def shiftleft(i, j): + return i << j + +def shiftright(i, j): + return i >> j + + #float snippets def float_f1(x): Modified: pypy/branch/pycompiler/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/branch/pycompiler/translator/llvm/test/test_genllvm.py (original) +++ pypy/branch/pycompiler/translator/llvm/test/test_genllvm.py Fri Jul 1 18:28:54 2005 @@ -1,5 +1,7 @@ from __future__ import division import autopath +import sys + import py from pypy.translator.translator import Translator @@ -97,6 +99,14 @@ f = compile_function(llvmsnippet.return_none, []) assert f() is None + def test_shift(self): + shl = compile_function(llvmsnippet.shiftleft, [int, int]) + shr = compile_function(llvmsnippet.shiftright, [int, int]) + for i in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + for j in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + assert shl(i, j) == i << j + assert shr(i, j) == i >> j + class TestFloat(object): def setup_method(self, method): if not llvm_found: Modified: pypy/branch/pycompiler/translator/llvm/typerepr.py ============================================================================== --- pypy/branch/pycompiler/translator/llvm/typerepr.py (original) +++ pypy/branch/pycompiler/translator/llvm/typerepr.py Fri Jul 1 18:28:54 2005 @@ -85,8 +85,6 @@ "int_mod": "rem", "int_xor": "xor", "int_and": "and", - "int_lshift": "shl", - "int_rshift": "shr", "int_or": "or", "int_eq": "seteq", "int_ne": "setne", @@ -105,15 +103,51 @@ assert len(args) == 2 l_args = [self.gen.get_repr(arg) for arg in args] l_func.dependencies.update(l_args) - l_op = SignedTypeRepr.directly_supported_binary_ops[opname] - if l_op in ('shl', 'shr'): #feel free to refactor this - lblock.shift_instruction( - l_op, l_target, - l_args[0], l_args[1]) - else: - lblock.binary_instruction( - l_op, l_target, - l_args[0], l_args[1]) + lblock.binary_instruction( + SignedTypeRepr.directly_supported_binary_ops[opname], l_target, + l_args[0], l_args[1]) + + def t_op_int_lshift(self, l_target, args, lblock, l_func): + # XXX hack: llvm only supports shifts by ubyte args + # so we have to jump through some loops + # someone on the LLVM list said this would change in the future + assert len(args) == 2 + l_tmp1 = self.gen.get_local_tmp(None, l_func) #using only the name + l_tmp2 = self.gen.get_local_tmp(None, l_func) + l_tmp3 = self.gen.get_local_tmp(None, l_func) + l_args = [self.gen.get_repr(arg) for arg in args] + l_func.dependencies.update(l_args) + lblock.instruction("%s = setge %s, %s" % (l_tmp1.llvmname(), + l_args[1].typed_name(), + 8 * BYTES_IN_INT)) + lblock.instruction("%s = cast int %s to ubyte" % + (l_tmp2.llvmname(), l_args[1].llvmname())) + lblock.shift_instruction("shl", l_tmp3, l_args[0], l_tmp2) + lblock.instruction("%s = select bool %s, int 0, int %s" % + (l_target.llvmname(), l_tmp1.llvmname(), + l_tmp3.llvmname())) + lblock.phi_done = True + + def t_op_int_rshift(self, l_target, args, lblock, l_func): + # XXX hack: llvm only supports shifts by ubyte args + # so we have to jump through some loops + # someone on the LLVM list said this would change in the future + assert len(args) == 2 + l_tmp1 = self.gen.get_local_tmp(None, l_func) #using only the name + l_tmp2 = self.gen.get_local_tmp(None, l_func) + l_tmp3 = self.gen.get_local_tmp(None, l_func) + l_args = [self.gen.get_repr(arg) for arg in args] + l_func.dependencies.update(l_args) + lblock.instruction("%s = setge %s, %s" % (l_tmp1.llvmname(), + l_args[1].typed_name(), + 8 * BYTES_IN_INT)) + lblock.instruction("%s = cast int %s to ubyte" % (l_tmp2.llvmname(), + l_args[1].llvmname())) + lblock.shift_instruction("shr", l_tmp3, l_args[0], l_tmp2) + lblock.instruction("%s = select bool %s, int 0, int %s" % + (l_target.llvmname(), l_tmp1.llvmname(), + l_tmp3.llvmname())) + lblock.phi_done = True def t_op_int_pos(self, l_target, args, lblock, l_func): pass @@ -133,8 +167,9 @@ def t_op_int_abs(self, l_target, args, lblock, l_func): l_arg = self.gen.get_repr(args[0]) l_func.dependencies.add(l_arg) - lblock.instruction("%s = and int 2147483647, %s" % (l_target.llvmname(), - l_arg.llvmname())) + lblock.instruction("%s = and int %s, %s" % (l_target.llvmname(), + sys.maxint - 1, + l_arg.llvmname())) def typename(self): return "int" Modified: pypy/branch/pycompiler/translator/pickle/genpickle.py ============================================================================== --- pypy/branch/pycompiler/translator/pickle/genpickle.py (original) +++ pypy/branch/pycompiler/translator/pickle/genpickle.py Fri Jul 1 18:28:54 2005 @@ -17,7 +17,7 @@ from pypy.translator.gensupp import builtin_base from pypy.rpython.rarithmetic import r_int, r_uint from pypy.objspace.flow.model import Variable, Constant, SpaceOperation -from pypy.objspace.flow.model import FunctionGraph, Block, Link +from pypy.objspace.flow.model import FunctionGraph, Block, Link, Atom from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool from pypy.annotation.model import SomeList, SomeString, SomeTuple @@ -33,195 +33,258 @@ from types import * import types +class AlreadyCreated(Exception): pass + # ____________________________________________________________ +#XXX Hack: This float is supposed to overflow to inf +OVERFLOWED_FLOAT = float("1e10000000000000000000000000000000") +#XXX Hack: and this one to underflow to -inf +OVERFLOWED_FLOATM = float("-1e10000000000000000000000000000000") + class GenPickle: def __init__(self, translator, writer = None): self.translator = translator - self.initcode = [ + self.writer = writer + self.initcode = [] + self.produce = self._produce() + self.produce( 'from __future__ import %s\n' % ', '.join(all_feature_names) + 'import new, types, sys', - ] - - self.latercode = [] # list of generators generating extra lines - self.debugstack = () # linked list of nested nameof() - - self.picklenames = {Constant(None): 'None', - Constant(False): 'False', - Constant(True): 'True', - # hack: overflowed float - Constant(float("1e10000000000000000000000000000000")): - 'float("1e10000000000000000000000000000000")', - } + ) + self.picklenames = {} # memoize objects for name in all_feature_names + "new types sys".split(): - self.picklenames[Constant(globals()[name])] = name + self.memoize(globals()[name], name) + self.memoize((), '()') self.namespace = NameManager() + self.uniquename = self.namespace.uniquename self.namespace.make_reserved_names('None False True') self.namespace.make_reserved_names('new types sys') self.namespace.make_reserved_names(' '.join(all_feature_names)) + self.namespace.make_reserved_names('result') # result dict + self.result = {} + self.simple_const_types = { + int: repr, + long: repr, + float: self.save_float, + str: repr, + unicode: repr, + type(None): repr, + bool: repr, + } + self.typecache = {} # hold types vs. nameof methods # we distinguish between the "user program" and other stuff. # "user program" will never use save_global. self.domains = ( 'pypy.objspace.std.', + 'pypy.objspace.descroperation', 'pypy._cache.', 'pypy.interpreter.', 'pypy.module.', + 'pypy.translator.test.', '__main__', ) self.shortnames = { - SpaceOperation: 'SOP', Variable: 'V', Constant: 'C', Block: 'B', SpamBlock: 'SB', EggBlock: 'EB', Link: 'L', - FunctionGraph: 'F', - SomeInteger: 'SI', - SomeObject: 'SO', - SomeChar: 'SC', - SomeBool: 'SB', - SomeList: 'SL', - SomeString: 'SS', - SomeTuple: 'ST', - SomeInstance: 'SIN', + FunctionGraph: 'FG', + SomeInteger: 'sI', + SomeObject: 'sO', + SomeChar: 'sC', + SomeBool: 'sB', + SomeList: 'sL', + SomeString: 'sS', + SomeTuple: 'sT', + SomeInstance: 'sIn', + } + self.inline_instances = { + SpaceOperation: True, } - self.writer = writer - def nameof(self, obj, debug=None, namehint=None): - key = Constant(obj) + def save_float(self, fl): + if fl == OVERFLOWED_FLOAT: + return 'float("1e10000000000000000000000000000000")' + elif fl == OVERFLOWED_FLOATM: + return 'float("-1e10000000000000000000000000000000")' + return repr(fl) + + def pickle(self, *args, **kwds): + for obj in args: + self.nameof(obj) + for obj in kwds.values(): + self.nameof(obj) + self.result.update(kwds) + + def finish(self): + self.pickle(self.result) + self.produce('result = %s' % self.nameof(self.result)) + if self.writer: + self.writer.close() + + def memoize(self, obj, name): + self.picklenames[id(obj)] = name + return name + + def memoize_unique(self, obj, basename): + if id(obj) in self.picklenames: + raise AlreadyCreated + return self.memoize(obj, self.uniquename(basename)) + + def _produce(self): + writer = self.writer + down = 1234 + cnt = [0, 0] # text, calls + self.last_progress = '' + if writer: + write = writer.write + else: + write = self.initcode.append + def produce(text): + write(text+'\n') + cnt[0] += len(text) + 1 + cnt[1] += 1 + if cnt[1] == down: + cnt[1] = 0 + self.progress("%d" % cnt[0]) + return produce + + def progress(self, txt): + back = '\x08' * len(self.last_progress) + self.last_progress = txt+' ' # soft space + print back+txt, + + def nameof(self, obj): try: - return self.picklenames[key] + try: + return self.picklenames[id(obj)] + except KeyError: + typ = type(obj) + return self.simple_const_types[typ](obj) except KeyError: - if debug: - stackentry = debug, obj - else: - stackentry = obj - self.debugstack = (self.debugstack, stackentry) - obj_builtin_base = builtin_base(obj) - if obj_builtin_base in (object, int, long) and type(obj) is not obj_builtin_base: - # assume it's a user defined thingy - name = self.nameof_instance(obj) - else: - for cls in type(obj).__mro__: - meth = getattr(self, - 'nameof_' + ''.join( [ - c for c in cls.__name__ - if c.isalpha() or c == '_'] ), - None) - if meth: - break - else: - raise Exception, "nameof(%r)" % (obj,) - - code = meth.im_func.func_code - if namehint and 'namehint' in code.co_varnames[:code.co_argcount]: - name = meth(obj, namehint=namehint) - else: - name = meth(obj) - self.debugstack, x = self.debugstack - assert x is stackentry - if name[0].isalpha(): - # avoid to store things which are used just once - self.picklenames[key] = name + try: + try: + meth = self.typecache[typ] + except KeyError: + obj_builtin_base = builtin_base(obj) + if (obj_builtin_base in (object,) + tuple( + self.simple_const_types.keys()) and + typ is not obj_builtin_base): + # assume it's a user defined thingy + meth = self.nameof_instance + else: + for cls in typ.__mro__: + meth = getattr(self, 'nameof_' + ''.join( + [ c for c in cls.__name__ + if c.isalpha() or c == '_'] ), None) + if meth: + break + else: + raise Exception, "nameof(%r)" % (obj,) + self.typecache[typ] = meth + name = meth(obj) + except AlreadyCreated: + name = self.picklenames[id(obj)] return name def nameofargs(self, tup, plain_tuple = False): """ a string with the nameofs, concatenated """ # see if we can build a compact representation - for each in tup: - if type(each) is tuple and len(each) > 2: - break - else: - ret = ', '.join([self.nameof(arg) for arg in tup]) - if plain_tuple and len(tup) == 1: - ret += ',' - if len(ret) <= 90: - return ret - ret = '\n ' + (',\n ').join( + ret = ', '.join([self.nameof(arg) for arg in tup]) + if plain_tuple and len(tup) == 1: + ret += ',' + if len(ret) <= 90: + return ret + ret = '\n ' + ',\n '.join( [self.nameof(arg) for arg in tup]) + ',\n ' return ret - def uniquename(self, basename): - return self.namespace.uniquename(basename) - - def initcode_python(self, name, pyexpr): - # generate init code that will evaluate the given Python expression - #self.initcode.append("print 'setting up', %r" % name) - self.initcode.append("%s = %s" % (name, pyexpr)) - def nameof_object(self, value): if type(value) is not object: - raise Exception, "nameof(%r)" % (value,) - name = self.uniquename('g_object') - self.initcode_python(name, "object()") + raise Exception, "nameof(%r): type %s not object" % ( + value, type(value).__name__) + name = self.memoize_unique(value, 'g_object') + self.produce('%s = object()' % name) return name def nameof_module(self, value): # all allowed here, we reproduce ourselves if self.is_app_domain(value.__name__): - name = self.uniquename('gmod_%s' % value.__name__) - self.initcode.append('%s = new.module(%r)\n' - 'sys.modules[%r] = %s'% ( + name = self.memoize_unique(value, 'gmod_%s' % value.__name__) + self.produce('%s = new.module(%r)\n' + 'sys.modules[%r] = %s'% ( name, value.__name__, value.__name__, name) ) def initmodule(): - for k, v in value.__dict__.items(): + names = value.__dict__.keys() + names.sort() + for k in names: try: + v = value.__dict__[k] nv = self.nameof(v) yield '%s.%s = %s' % (name, k, nv) except PicklingError: pass - self.later(initmodule()) + for line in initmodule(): + self.produce(line) else: - name = self.uniquename(value.__name__) - self.initcode_python(name, "__import__(%r)" % (value.__name__,)) + name = self.memoize_unique(value, value.__name__) + self.produce('%s = __import__(%r)' % (name, value.__name__,)) return name - def nameof_int(self, value): - return repr(value) - - # we don't need to name the following const types. - # the compiler folds the consts the same way as we do. - # note that true pickling is more exact, here. - nameof_long = nameof_float = nameof_bool = nameof_NoneType = nameof_int - nameof_str = nameof_unicode = nameof_int - - def skipped_function(self, func): + def skipped_function(self, func, reason=None, _dummydict={}): # Generates a placeholder for missing functions # that raises an exception when called. # The original code object is retained in an # attribute '_skipped_code' - name = self.uniquename('gskippedfunc_' + func.__name__) - codename = self.nameof(func.func_code) - self.initcode.append('def %s(*a,**k):\n' - ' raise NotImplementedError' % name) - self.initcode.append('%s._skipped_code = %s' % (name, codename) ) - return name + skipname = 'gskippedfunc_' + func.__name__ + funcname = func.__name__ + # need to handle this specially + if id(func) in self.picklenames: + raise AlreadyCreated + # generate code object before the skipped func (reads better) + func_code = getattr(func, 'func_code', None) # maybe builtin + self.nameof(func_code) + if reason: + text = 'skipped: %r, see _skipped_code attr: %s' % ( + reason, funcname) + else: + text = 'skipped, see _skipped_code attr: %s' % funcname + def dummy(*args, **kwds): + raise NotImplementedError, text + _dummydict['__builtins__'] = __builtins__ + skippedfunc = new.function(dummy.func_code, _dummydict, skipname, (), + dummy.func_closure) + skippedfunc._skipped_code = func_code + name = self.nameof(skippedfunc) + return self.memoize(func, name) def nameof_staticmethod(self, sm): # XXX XXX XXXX func = sm.__get__(42.5) - name = self.uniquename('gsm_' + func.__name__) functionname = self.nameof(func) - self.initcode_python(name, 'staticmethod(%s)' % functionname) + name = self.memoize_unique(sm, 'gsm_' + func.__name__) + self.produce('%s = staticmethod(%s)' % (name, functionname)) return name def nameof_instancemethod(self, meth): + func = self.nameof(meth.im_func) + typ = self.nameof(meth.im_class) if meth.im_self is None: # no error checking here - return self.nameof(meth.im_func) + name = self.memoize_unique(meth, 'gmeth_' + func) + self.produce('%s = %s.%s' % (name, typ, meth.__name__)) else: ob = self.nameof(meth.im_self) - func = self.nameof(meth.im_func) - typ = self.nameof(meth.im_class) - name = self.uniquename('gmeth_'+meth.im_func.__name__) - self.initcode_python(name, 'new.instancemethod(%s, %s, %s)' % ( - func, ob, typ)) - return name + name = self.memoize_unique(meth, 'gumeth_'+ func) + self.produce('%s = new.instancemethod(%s, %s, %s)' % ( + name, func, ob, typ)) + return name - # new version: save if we don't know def should_translate_attr(self, pbc, attr): ann = self.translator.annotator if ann: @@ -241,22 +304,31 @@ # builtin function # where does it come from? Python2.2 doesn't have func.__module__ for modname, module in sys.modules.items(): - # here we don't ignore extension modules + # here we don't ignore extension modules, but it must be + # a builtin module + if not module: continue + if hasattr(module, '__file__'): + fname = module.__file__.lower() + pyendings = '.py', '.pyc', '.pyo' + if [fname.endswith(ending) for ending in pyendings]: + continue if func is getattr(module, func.__name__, None): break else: - raise Exception, '%r not found in any built-in module' % (func,) - name = self.uniquename('gbltin_' + func.__name__) + #raise Exception, '%r not found in any built-in module' % (func,) + return self.skipped_function( + func, 'not found in any built-in module') + name = self.memoize_unique(func, 'gbltin_' + func.__name__) if modname == '__builtin__': - self.initcode_python(name, func.__name__) + self.produce('%s = %s' % (name, func.__name__)) else: modname = self.nameof(module) - self.initcode_python(name, '%s.%s' % (modname, func.__name__)) + self.produce('%s = %s.%s' % (name, modname, func.__name__)) else: # builtin (bound) method - name = self.uniquename('gbltinmethod_' + func.__name__) selfname = self.nameof(func.__self__) - self.initcode_python(name, '%s.%s' % (selfname, func.__name__)) + name = self.memoize_unique(func, 'gbltinmethod_' + func.__name__) + self.produce('%s = %s.%s' % (name, selfname, func.__name__)) return name def nameof_classobj(self, cls): @@ -265,27 +337,21 @@ try: return self.save_global(cls) - except PicklingError: + except PicklingError, e: pass metaclass = "type" if issubclass(cls, Exception): # if cls.__module__ == 'exceptions': # don't rely on this, py.magic redefines AssertionError - if getattr(__builtin__,cls.__name__,None) is cls: - name = self.uniquename('gexc_' + cls.__name__) - self.initcode_python(name, cls.__name__) + if getattr(__builtin__, cls.__name__, None) is cls: + name = self.memoize_unique(cls, 'gexc_' + cls.__name__) + self.produce('%s = %s' % (name, cls.__name__)) return name - #else: - # # exceptions must be old-style classes (grr!) - # metaclass = "&PyClass_Type" - # For the moment, use old-style classes exactly when the - # pypy source uses old-style classes, to avoid strange problems. if not isinstance(cls, type): assert type(cls) is ClassType metaclass = "types.ClassType" - name = self.uniquename('gcls_' + cls.__name__) basenames = [self.nameof(base) for base in cls.__bases__] def initclassobj(): content = cls.__dict__.items() @@ -302,7 +368,6 @@ if isapp: if (isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen): - print value continue if isinstance(value, classmethod): doc = value.__get__(cls).__doc__ @@ -310,7 +375,6 @@ continue if (isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen): - print value continue if key in ignore: continue @@ -322,15 +386,15 @@ baseargs = ", ".join(basenames) if baseargs: baseargs = '(%s)' % baseargs + name = self.memoize_unique(cls, 'gcls_' + cls.__name__) ini = 'class %s%s:\n __metaclass__ = %s' % (name, baseargs, metaclass) if '__slots__' in cls.__dict__: ini += '\n __slots__ = %r' % cls.__slots__ - self.initcode.append(ini) - self.initcode.append('%s.name = %r' % (name, cls.__name__)) - # squeeze it out, now# self.later(initclassobj()) - self.picklenames[Constant(cls)] = name + self.produce(ini) + self.produce('%s.__name__ = %r' % (name, cls.__name__)) + self.produce('%s.__module__ = %r' % (name, cls.__module__)) for line in initclassobj(): - self.initcode.append(line) + self.produce(line) return name nameof_class = nameof_classobj # for Python 2.2 @@ -357,6 +421,8 @@ type(type.__dict__['__basicsize__']): "type(type.__dict__['__basicsize__'])", # type 'instancemethod': type(Exception().__init__): 'type(Exception().__init__)', + # type 'listiterator': + type(iter([])): 'type(iter([]))', } descriptor_filter = {} for _key in typename_mapping.keys(): @@ -367,46 +433,54 @@ def nameof_type(self, cls): if cls.__module__ != '__builtin__': return self.nameof_classobj(cls) # user-defined type - name = self.uniquename('gtype_%s' % cls.__name__) + name = self.memoize_unique(cls, 'gtype_%s' % cls.__name__) if getattr(__builtin__, cls.__name__, None) is cls: expr = cls.__name__ # type available from __builtin__ elif cls in types.__dict__.values(): for key, value in types.__dict__.items(): if value is cls: break - self.initcode.append('from types import %s as %s' % ( + self.produce('from types import %s as %s' % ( key, name)) return name else: expr = self.typename_mapping[cls] - self.initcode_python(name, expr) + self.produce('%s = %s' % (name, expr)) return name def nameof_tuple(self, tup): chunk = 20 - name = self.uniquename('T%d' % len(tup)) + # first create all arguments + for i in range(0, len(tup), chunk): + self.nameofargs(tup[i:i+chunk], True) + # see if someone else created us meanwhile + name = self.memoize_unique(tup, 'T%d' % len(tup)) argstr = self.nameofargs(tup[:chunk], True) - self.initcode_python(name, '(%s)' % argstr) + self.produce('%s = (%s)' % (name, argstr)) for i in range(chunk, len(tup), chunk): argstr = self.nameofargs(tup[i:i+chunk], True) - self.initcode.append('%s += (%s)' % (name, argstr) ) + self.produce('%s += (%s)' % (name, argstr) ) return name def nameof_list(self, lis): chunk = 20 - name = self.uniquename('L%d' % len(lis)) def initlist(): - chunk = 20 for i in range(0, len(lis), chunk): argstr = self.nameofargs(lis[i:i+chunk]) yield '%s += [%s]' % (name, argstr) - self.initcode_python(name, '[]') - self.later(initlist()) + name = self.memoize_unique(lis, 'L%d' % len(lis)) + self.produce('%s = []' % name) + for line in initlist(): + self.produce(line) return name - def is_app_domain(self, modname): + def is_app_domain(self, modname, exclude=()): for domain in self.domains: - if modname.startswith(domain): + if domain.endswith('.') and modname.startswith(domain): + # handle subpaths + return True + if modname == domain and modname not in exclude: + # handle exact module names return True return False @@ -414,6 +488,8 @@ if '__name__' in dic: module = dic['__name__'] try: + if type(module) is str and self.is_app_domain(module): + raise ImportError __import__(module) mod = sys.modules[module] except (ImportError, KeyError, TypeError): @@ -421,51 +497,56 @@ else: if dic is mod.__dict__ and not self.is_app_domain(module): dictname = module.split('.')[-1] + '__dict__' - dictname = self.uniquename(dictname) - self.initcode.append('from %s import __dict__ as %s' % ( - module, dictname) ) - self.picklenames[Constant(dic)] = dictname + dictname = self.memoize_unique(dic, dictname) + self.produce('from %s import __dict__ as %s' % ( + module, dictname) ) return dictname - name = self.uniquename('D%d' % len(dic)) def initdict(): - for k in dic: + keys = dic.keys() + keys.sort() + told = False + for k in keys: try: - if type(k) is str: - yield '%s[%r] = %s' % (name, k, self.nameof(dic[k])) - else: - yield '%s[%s] = %s' % (name, self.nameof(k), - self.nameof(dic[k])) + nk, nv = self.nameof(k), self.nameof(dic[k]) + yield '%s[%s] = %s' % (name, nk, nv) except PicklingError: pass - self.initcode_python(name, '{}') - self.later(initdict()) + else: + # some sanity check + if type(k) is int: + if k in self.picklenames: + print ('WARNING: this dict most likely contains ' + 'the id of some object!!') + print 'name of object: %s' % self.picklenames[k] + elif k == id(dic[k]): + print ('WARNING: this dict most likely contains ' + 'the id of one of it\'s objects!!') + if not told: + print dic + told = True + name = self.memoize_unique(dic, 'D%d' % len(dic)) + self.produce('%s = {}' % name) + for line in initdict(): + self.produce(line) return name # strange prebuilt instances below, don't look too closely # XXX oh well. def nameof_member_descriptor(self, md): - name = self.uniquename('gdescriptor_%s_%s' % ( - md.__objclass__.__name__, md.__name__)) cls = self.nameof(md.__objclass__) - self.initcode_python(name, '%s.__dict__[%r]' % (cls, md.__name__)) + name = self.memoize_unique(md, 'gdescriptor_%s_%s' % ( + md.__objclass__.__name__, md.__name__)) + self.produce('%s = %s.__dict__[%r]' % (name, cls, md.__name__)) return name nameof_getset_descriptor = nameof_member_descriptor nameof_method_descriptor = nameof_member_descriptor nameof_wrapper_descriptor = nameof_member_descriptor def nameof_instance(self, instance): - klass = instance.__class__ - if klass in self.shortnames: - name = self.uniquename(self.shortnames[klass]) - else: - name = self.uniquename('ginst_' + klass.__name__) - cls = self.nameof(klass) - if hasattr(klass, '__base__'): - base_class = builtin_base(instance) - base = self.nameof(base_class) - else: - base_class = None - base = cls + if isinstance(instance, Atom): + # cannot reconstruct this, it *must* be + # the one from model + return self.save_global(instance) def initinstance(): if hasattr(instance, '__setstate__'): # the instance knows what to do @@ -481,14 +562,33 @@ "%s has no dict and no __setstate__" % name) content = restorestate.items() content.sort() + attrs = [] for key, value in content: if self.should_translate_attr(instance, key): if hasattr(value, '__doc__'): doc = value.__doc__ if type(doc) is str and doc.lstrip().startswith('NOT_RPYTHON'): continue - line = '%s.%s = %s' % (name, key, self.nameof(value)) - yield line + attrs.append( (key, self.nameof(value)) ) + for k, v in attrs: + yield '%s.%s = %s' % (name, k, v) + + klass = instance.__class__ + cls = self.nameof(klass) + if hasattr(klass, '__base__'): + base_class = builtin_base(instance) + base = self.nameof(base_class) + else: + base_class = None + base = cls + if klass in self.inline_instances: + immediate = True + else: + if klass in self.shortnames: + name = self.memoize_unique(instance, self.shortnames[klass]) + else: + name = self.memoize_unique(instance, 'ginst_' + klass.__name__) + immediate = False if hasattr(instance, '__reduce_ex__'): try: reduced = instance.__reduce_ex__() @@ -501,7 +601,7 @@ assert not hasattr(instance, '__dict__'), ('wrong assumptions' ' about __slots__ in %s instance without __setstate__,' ' please update %s' % (cls.__name__, __name__) ) - restorestate = slotted.__getstate__(instance) + restorestate = _get(instance) restorer = _rec restoreargs = klass, else: @@ -526,50 +626,50 @@ else: restorestate = instance.__dict__ restoreargstr = self.nameofargs(restoreargs) + if immediate: + assert restorestate is None + return '%s(%s)' % (restorename, restoreargstr) if isinstance(klass, type): - self.initcode.append('%s = %s(%s)' % (name, restorename, - restoreargstr)) + self.produce('%s = %s(%s)' % (name, restorename, restoreargstr)) else: - self.initcode.append('%s = new.instance(%s)' % (name, cls)) + self.produce('%s = new.instance(%s)' % (name, cls)) if restorestate is not None: - self.later(initinstance()) + for line in initinstance(): + self.produce(line) return name def save_global(self, obj): # this is almost similar to pickle.py name = obj.__name__ - key = Constant(obj) - if key not in self.picklenames: - module = getattr(obj, "__module__", None) - if module is None: - module = whichmodule(obj, name) - if self.is_app_domain(module): - # not allowed to import this - raise PicklingError('%s belongs to the user program' % - name) - try: - __import__(module) - mod = sys.modules[module] - klass = getattr(mod, name) - except (ImportError, KeyError, AttributeError): + module = getattr(obj, "__module__", None) + if module is None: + module = whichmodule(obj, name) + if self.is_app_domain(module): + # not allowed to import this + raise PicklingError('%s belongs to the user program' % + name) + try: + __import__(module) + mod = sys.modules[module] + klass = getattr(mod, name) + except (ImportError, KeyError, AttributeError): + raise PicklingError( + "Can't pickle %r: it's not found as %s.%s" % + (obj, module, name)) + else: + if klass is not obj: raise PicklingError( - "Can't pickle %r: it's not found as %s.%s" % + "Can't pickle %r: it's not the same object as %s.%s" % (obj, module, name)) - else: - if klass is not obj: - raise PicklingError( - "Can't pickle %r: it's not the same object as %s.%s" % - (obj, module, name)) - # from here we do our own stuff - restorename = self.uniquename(obj.__name__) - if restorename != obj.__name__: - self.initcode.append('from %s import %s as %s' % ( - module, obj.__name__, restorename) ) - else: - self.initcode.append('from %s import %s' % ( - module, obj.__name__) ) - self.picklenames[key] = restorename - return self.picklenames[key] + # from here we do our own stuff + restorename = self.memoize_unique(obj, obj.__name__) + if restorename != obj.__name__: + self.produce('from %s import %s as %s' % ( + module, obj.__name__, restorename) ) + else: + self.produce('from %s import %s' % ( + module, obj.__name__) ) + return restorename def nameof_function(self, func): # look for skipped functions @@ -577,42 +677,51 @@ if func not in self.translator.flowgraphs: # see if this is in translator's domain module = whichmodule(func, func.__name__) - if self.is_app_domain(module): - return self.skipped_function(func) + if self.is_app_domain(module, exclude=['__main__']): + # see if this buddy has been skipped in another save, before + if not hasattr(func, '_skipped_code'): + return self.skipped_function(func, + 'not found in translator\'s flowgraphs') else: if (func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON')): - return self.skipped_function(func) + return self.skipped_function(func, 'tagged as NOT_RPYTHON') try: return self.save_global(func) except PicklingError: pass args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, func.func_closure) - pyfuncobj = self.uniquename('gfunc_' + func.__name__) - self.initcode.append('%s = new.function(%s)' % (pyfuncobj, - self.nameofargs(args)) ) + argstr = self.nameofargs(args) + if hasattr(func, '_skipped_code'): + name = self.memoize_unique(func, func.__name__) + else: + name = self.memoize_unique(func, 'gfunc_' + func.__name__) + self.produce('%s = new.function(%s)' % (name, argstr) ) if func.__dict__: - for k, v in func.__dict__.items(): - try: - self.initcode.append('%s.%s = %s' % ( - pyfuncobj, k, self.nameof(v)) ) - except PicklingError: - pass - return pyfuncobj + def initfunction(): + items = func.__dict__.items() + items.sort() + for k, v in items: + try: + yield '%s.%s = %s' % (name, k, self.nameof(v)) + except PicklingError: + pass + for line in initfunction(): + self.produce(line) + return name def nameof_cell(self, cel): + # no need to name cells. Their contents is what is shared. obj = break_cell(cel) - pycell = self.uniquename('gcell_' + self.nameof(obj)) - self.initcode.append('%s = %s(%s)' % (pycell, self.nameof(make_cell), - self.nameof(obj)) ) - return pycell + return '%s(%s)' % (self.nameof(make_cell), self.nameof(obj)) def nameof_property(self, prop): - pyprop = self.uniquename('gprop_') - self.initcode.append('%s = property(%s)' % (pyprop, self.nameofargs( - (prop.fget, prop.fset, prop.fdel, prop.__doc__))) ) - return pyprop + argstr = self.nameofargs((prop.fget, prop.fset, prop.fdel, + prop.__doc__)) + name = self.memoize_unique(prop, 'gprop_') + self.produce('%s = property(%s)' % (name, argstr) ) + return name def nameof_code(self, code): args = (code.co_argcount, code.co_nlocals, code.co_stacksize, @@ -621,9 +730,9 @@ code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars) argstr = self.nameofargs(args) - codeobj = self.uniquename('gcode_' + code.co_name) - self.initcode.append('%s = new.code(%s)' % (codeobj, argstr)) - return codeobj + name = self.memoize_unique(code, 'gcode_' + code.co_name) + self.produce('%s = new.code(%s)' % (name, argstr)) + return name def nameof_file(self, fil): if fil is sys.stdin: return "sys.stdin" @@ -633,46 +742,10 @@ def nameof_methodwrapper(self, wp): # this object should be enhanced in CPython! - reprwp = repr(wp) - name = wp.__name__ - def dummy_methodwrapper(): - return reprwp + (': method %s of unknown object ' - 'cannot be reconstructed, sorry!' % name ) - return self.nameof(dummy_methodwrapper) - - def later(self, gen): - self.latercode.append((gen, self.debugstack)) + msg = '%r: method %s of unknown object cannot be reconstructed' % ( + wp, wp.__name__) + return self.skipped_function(wp, msg) - def collect_initcode(self): - writer = self.writer - while self.latercode: - gen, self.debugstack = self.latercode.pop() - #self.initcode.extend(gen) -- eats TypeError! bad CPython! - for line in gen: - self.initcode.append(line) - self.debugstack = () - if writer: - for line in self.initcode: - writer.write(line) - del self.initcode[:] - if writer: - writer.close() - - def getfrozenbytecode(self): - self.initcode.append('') - source = '\n'.join(self.initcode) - del self.initcode[:] - co = compile(source, '', 'exec') - originalsource = source - small = zlib.compress(marshal.dumps(co)) - source = """if 1: - import zlib, marshal - exec marshal.loads(zlib.decompress(%r))""" % small - # Python 2.2 SyntaxError without newline: Bug #501622 - source += '\n' - co = compile(source, '', 'exec') - del source - return marshal.dumps(co), originalsource def make_cell(obj): def func(): @@ -693,5 +766,10 @@ def _rec(klass, base=object, state=None): return _reconstructor(klass, base, state) +def _get(obj): + return slotted.__getstate__(obj) + def _set(obj, *args): slotted.__setstate__(obj, args) + +__all__ = ['GenPickle'] Modified: pypy/branch/pycompiler/translator/pickle/loader.py ============================================================================== --- pypy/branch/pycompiler/translator/pickle/loader.py (original) +++ pypy/branch/pycompiler/translator/pickle/loader.py Fri Jul 1 18:28:54 2005 @@ -2,6 +2,7 @@ class Loader: def __init__(self, fname): + self.opened = False self.f = self.open_file(fname) def open_file(self, fname): @@ -10,23 +11,29 @@ def next_block(self): raise SyntaxError, "implement next_block" - def load(self): + def load(self, progress=None): dic = {} for blk in self.next_block(): exec blk in dic + if progress: + progress() try: - return dic['ginst_Translator'] + return dic['result'] finally: self.close() def close(self): - self.f.close() + if self.opened: + self.f.close() class TextLoader(Loader): def open_file(self, fname): - return file(fname) + if type(fname) is str: + self.opened = True + return file(fname) + return fname # should be a file-like object def next_block(self): data = self.f.read().split('## SECTION ##\n') @@ -37,7 +44,10 @@ """ load compiled code from a ZIP file """ def open_file(self, fname): - return zipfile.ZipFile(fname, "r") + if type(fname) is str: + self.opened = True + return zipfile.ZipFile(fname, "r") + return fname def next_block(self): root = self.f.read('root') @@ -48,3 +58,5 @@ dump = self.f.read(name) assert md5.new(dump).hexdigest() == name, "broken checksum" yield marshal.loads(dump) + +__all__ = ['Loader', 'TextLoader', 'ZipLoader'] Modified: pypy/branch/pycompiler/translator/pickle/main.py ============================================================================== --- pypy/branch/pycompiler/translator/pickle/main.py (original) +++ pypy/branch/pycompiler/translator/pickle/main.py Fri Jul 1 18:28:54 2005 @@ -1,5 +1,42 @@ +import sys +from pypy.translator.pickle.genpickle import GenPickle +from pypy.translator.pickle.writer import Writer, TextWriter, ZipWriter +from pypy.translator.pickle.loader import Loader, TextLoader, ZipLoader + def load(fname): - pass + loader = _select(fname)[0] + assert loader, 'only .py and .zip files supported' + print "Loading:", + def progress(): + sys.stdout.write('.') + ret = loader(fname).load(progress) + print + return ret + +def save(translator, fname, **objects): + writer = _select(fname)[1] + assert writer, 'only .py and .zip files supported' + assert objects, 'please provide objects to be saved as keywords' + pickler = GenPickle(translator, writer(fname)) + hold = sys.getrecursionlimit() + if hold < 5000: + sys.setrecursionlimit(5000) + try: + pickler.pickle(**objects) + finally: + sys.setrecursionlimit(hold) + pickler.finish() + return pickler # for debugging purposes + +# and that's all, folks! +# _________________________________________________________________ + +def _select(fname): + name = fname.lower() + if name.endswith('.py'): + return TextLoader, TextWriter + elif name.endswith('.zip'): + return ZipLoader, ZipWriter + else: + return None, None -def save(translator, fname): - pass Modified: pypy/branch/pycompiler/translator/pickle/writer.py ============================================================================== --- pypy/branch/pycompiler/translator/pickle/writer.py (original) +++ pypy/branch/pycompiler/translator/pickle/writer.py Fri Jul 1 18:28:54 2005 @@ -6,6 +6,7 @@ self.chunksize = 100000 self.count = 0 self.blocknum = 0 + self.opened = False self.f = self.open_file(fname) def open_file(self, fname): @@ -15,17 +16,18 @@ self.pieces.append(text) self.count += len(text) + 1 if self.count >= self.chunksize: - src = '\n'.join(self.pieces) + src = ''.join(self.pieces) del self.pieces[:] self.count -= self.chunksize self.putblock(src) self.blocknum += 1 def close(self): - src = '\n'.join(self.pieces) + src = ''.join(self.pieces) self.putblock(src) self.finalize() - self.f.close() + if self.opened: + self.f.close() def finalize(self): pass @@ -34,10 +36,13 @@ class TextWriter(Writer): def open_file(self, fname): - return file(fname, 'w') + if type(fname) is str: + self.opened = True + return file(fname, 'w') + return fname # should be a file-like object def putblock(self, src): - print >> self.f, src + self.f.write(src) print >> self.f, '## SECTION ##' class ZipWriter(Writer): @@ -48,7 +53,10 @@ self.blocknames = [] def open_file(self, fname): - return zipfile.ZipFile(fname, "w", zipfile.ZIP_DEFLATED) + if type(fname) is str: + self.opened = True + return zipfile.ZipFile(fname, "w", zipfile.ZIP_DEFLATED) + return fname def putblock(self, src): cod = compile(src, 'block_%d' % self.blocknum, 'exec') @@ -62,3 +70,5 @@ digest = md5.new(dump).hexdigest() self.f.writestr(digest, dump) self.f.writestr('root', digest) + +__all__ = ['Writer', 'TextWriter', 'ZipWriter'] Modified: pypy/branch/pycompiler/translator/simplify.py ============================================================================== --- pypy/branch/pycompiler/translator/simplify.py (original) +++ pypy/branch/pycompiler/translator/simplify.py Fri Jul 1 18:28:54 2005 @@ -52,7 +52,7 @@ Example: try: - ovfcheck(array1[idx-1] += array2[idx+1]) + array1[idx-1] = ovfcheck(array1[idx-1] + array2[idx+1]) except OverflowError: ... @@ -341,6 +341,10 @@ iter get '''.split(): CanRemove[_op] = True del _op +CanRemoveBuiltins = { + isinstance: True, + hasattr: True, + } def transform_dead_op_vars_in_blocks(blocks): """Remove dead operations and variables that are passed over a link @@ -415,8 +419,11 @@ # ... if op.args and isinstance(op.args[0], Constant): func = op.args[0].value - if func is isinstance: - del block.operations[i] + try: + if func in CanRemoveBuiltins: + del block.operations[i] + except TypeError: # func is not hashable + pass # look for output variables never used # warning: this must be completely done *before* we attempt to Modified: pypy/branch/pycompiler/translator/test/rpystone.py ============================================================================== --- pypy/branch/pycompiler/translator/test/rpystone.py (original) +++ pypy/branch/pycompiler/translator/test/rpystone.py Fri Jul 1 18:28:54 2005 @@ -1,21 +1,5 @@ #! /usr/bin/env python -def setslow(X): - global XF1, XF2, XF3, XP1, XP2, XP3, XP4, XP5, XP6, XP7, XP8 - XF1 = True - XF2 = X - XF3 = True - XP1 = X - XP2 = X - XP3 = True - XP4 = X - XP5 = True - XP6 = True - XP7 = True - XP8 = X - -setslow(True) - """ "PYSTONE" Benchmark Program @@ -65,7 +49,7 @@ class Record: def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, - IntComp = 0, StringComp = 0): + IntComp = 0, StringComp = ""): self.PtrComp = PtrComp self.Discr = Discr self.EnumComp = EnumComp @@ -110,8 +94,13 @@ #global PtrGlbNext starttime = clock() - for i in range(loops): - pass + #for i in range(loops): + # this is bad with very large values of loops + # XXX xrange support? + i = 0 + while i < loops: + i += 1 + # the above is most likely to vanish in C :-( nulltime = clock() - starttime g.PtrGlbNext = Record() @@ -127,29 +116,34 @@ EnumLoc = None # addition for flow space starttime = clock() - for i in range(loops): - if XP5:Proc5() - if XP4:Proc4() + #for i in range(loops): + # this is bad with very large values of loops + # XXX xrange support? + i = 0 + while i < loops: + Proc5() + Proc4() IntLoc1 = 2 IntLoc2 = 3 String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" EnumLoc = Ident2 - if XF2:g.BoolGlob = not Func2(String1Loc, String2Loc) + g.BoolGlob = not Func2(String1Loc, String2Loc) while IntLoc1 < IntLoc2: IntLoc3 = 5 * IntLoc1 - IntLoc2 IntLoc3 = Proc7(IntLoc1, IntLoc2) IntLoc1 = IntLoc1 + 1 - if XP8:Proc8(g.Array1Glob, g.Array2Glob, IntLoc1, IntLoc3) - if XP1:g.PtrGlb = Proc1(g.PtrGlb) + Proc8(g.Array1Glob, g.Array2Glob, IntLoc1, IntLoc3) + g.PtrGlb = Proc1(g.PtrGlb) CharIndex = 'A' while CharIndex <= g.Char2Glob: - if XF1 and EnumLoc == Func1(CharIndex, 'C'): - if XP6:EnumLoc = Proc6(Ident1) + if EnumLoc == Func1(CharIndex, 'C'): + EnumLoc = Proc6(Ident1) CharIndex = chr(ord(CharIndex)+1) IntLoc3 = IntLoc2 * IntLoc1 IntLoc2 = IntLoc3 / IntLoc1 IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 - if XP2:IntLoc1 = Proc2(IntLoc1) + IntLoc1 = Proc2(IntLoc1) + i += 1 benchtime = clock() - starttime - nulltime return benchtime, (loops / benchtime) @@ -159,12 +153,12 @@ PtrParIn.IntComp = 5 NextRecord.IntComp = PtrParIn.IntComp NextRecord.PtrComp = PtrParIn.PtrComp - if XP3:NextRecord.PtrComp = Proc3(NextRecord.PtrComp) + NextRecord.PtrComp = Proc3(NextRecord.PtrComp) if NextRecord.Discr == Ident1: NextRecord.IntComp = 6 - if XP6:NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) + NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) NextRecord.PtrComp = g.PtrGlb.PtrComp - if XP7:NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) + NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) else: PtrParIn = NextRecord.copy() NextRecord.PtrComp = None @@ -189,7 +183,7 @@ PtrParOut = g.PtrGlb.PtrComp else: g.IntGlob = 100 - if XP7:g.PtrGlb.IntComp = Proc7(10, g.IntGlob) + g.PtrGlb.IntComp = Proc7(10, g.IntGlob) return PtrParOut def Proc4(): @@ -208,7 +202,7 @@ def Proc6(EnumParIn): EnumParOut = EnumParIn - if XF3 and not Func3(EnumParIn): + if not Func3(EnumParIn): EnumParOut = Ident4 if EnumParIn == Ident1: EnumParOut = Ident1 @@ -254,7 +248,7 @@ def Func2(StrParI1, StrParI2): IntLoc = 1 while IntLoc <= 1: - if XF1 and Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: + if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: CharLoc = 'A' IntLoc = IntLoc + 1 if CharLoc >= 'W' and CharLoc <= 'Z': Modified: pypy/branch/pycompiler/translator/test/snippet.py ============================================================================== --- pypy/branch/pycompiler/translator/test/snippet.py (original) +++ pypy/branch/pycompiler/translator/test/snippet.py Fri Jul 1 18:28:54 2005 @@ -363,7 +363,7 @@ raise Exception return 0 -def try_raise_choose(n): +def try_raise_choose(n=int): try: raise_choose(n) except E1: Modified: pypy/branch/pycompiler/translator/test/test_annrpython.py ============================================================================== --- pypy/branch/pycompiler/translator/test/test_annrpython.py (original) +++ pypy/branch/pycompiler/translator/test/test_annrpython.py Fri Jul 1 18:28:54 2005 @@ -582,13 +582,13 @@ def test_flow_rev_numbers(self): a = self.RPythonAnnotator() - s = a.build_types(snippet.flow_rev_numbers, []) + s = a.build_types(snippet.flow_rev_numbers, [int]) assert s.knowntype == int assert not s.is_constant() # ! def test_methodcall_is_precise(self): a = self.RPythonAnnotator() - s = a.build_types(snippet.methodcall_is_precise, []) + s = a.build_types(snippet.methodcall_is_precise, [bool]) classes = a.bookkeeper.userclasses assert 'x' not in classes[snippet.CBase].attrs assert (classes[snippet.CSub1].attrs['x'].s_value == @@ -637,7 +637,7 @@ def assert_(x): assert x,"XXX" a = self.RPythonAnnotator() - s = a.build_types(assert_, []) + s = a.build_types(assert_, [int]) assert s.const is None def test_string_and_none(self): @@ -810,7 +810,7 @@ assert acc1 is acc2 is acc3 assert len(acc1.objects) == 3 - assert acc1.attrs == {'v1': True, 'v2': True} + assert dict.fromkeys(acc1.attrs) == {'v1': None, 'v2': None} assert access_sets[c1] is acc1 py.test.raises(KeyError, "access_sets[object()]") @@ -1264,6 +1264,122 @@ s = a.build_types(f, [int]*8) assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8) + def test_attr_moving_into_parent(self): + class A: pass + class B(A): pass + a1 = A() + b1 = B() + b1.stuff = a1 + a1.stuff = None + def f(): + return b1.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInstance) + assert not s.can_be_None + assert s.classdef.cls is A + + def test_class_attribute(self): + class A: + stuff = 42 + class B(A): + pass + def f(): + b = B() + return b.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s == a.bookkeeper.immutablevalue(42) + + def test_attr_recursive_getvalue(self): + class A: pass + a2 = A() + a2.stuff = None + a1 = A() + a1.stuff = a2 + def f(): + return a1.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInstance) + assert s.can_be_None + assert s.classdef.cls is A + + def test_long_list_recursive_getvalue(self): + class A: pass + lst = [] + for i in range(500): + a1 = A() + a1.stuff = lst + lst.append(a1) + def f(): + A().stuff = None + return (A().stuff, lst)[1] + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeList) + s_item = s.listdef.listitem.s_value + assert isinstance(s_item, annmodel.SomeInstance) + + def test_immutable_dict(self): + d = {4: "hello", + 5: "world"} + def f(n): + return d[n] + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert isinstance(s, annmodel.SomeString) + + def test_immutable_recursive_list(self): + l = [] + l.append(l) + def f(): + return l + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeList) + s_item = s.listdef.listitem.s_value + assert isinstance(s_item, annmodel.SomeList) + assert s_item.listdef.same_as(s.listdef) + + def test_defaults_with_list_or_dict(self): + def fn1(a=[]): + return a + def fn2(a={}): + return a + def f(): + fn1() + fn2() + return fn1([6, 7]), fn2({2: 3, 4: 5}) + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeTuple) + s1, s2 = s.items + assert not s1.is_constant() + assert not s2.is_constant() + assert isinstance(s1.listdef.listitem. s_value, annmodel.SomeInteger) + assert isinstance(s2.dictdef.dictkey. s_value, annmodel.SomeInteger) + assert isinstance(s2.dictdef.dictvalue.s_value, annmodel.SomeInteger) + + def test_pbc_union(self): + class A: + def meth(self): + return 12 + class B(A): + pass + class C(B): + pass + def f(i): + if i: + f(0) + x = B() + else: + x = C() + return x.meth() + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s == a.bookkeeper.immutablevalue(12) + def g(n): return [0,1,2,n] Modified: pypy/branch/pycompiler/translator/test/test_cltrans.py ============================================================================== --- pypy/branch/pycompiler/translator/test/test_cltrans.py (original) +++ pypy/branch/pycompiler/translator/test/test_cltrans.py Fri Jul 1 18:28:54 2005 @@ -43,7 +43,7 @@ py.test.skip("Common Lisp neither configured nor detected.") def test_if(self): - cl_if = make_cl_func(t.if_then_else) + cl_if = make_cl_func(t.if_then_else, [object, object, object]) assert cl_if(True, 50, 100) == 50 assert cl_if(False, 50, 100) == 100 assert cl_if(0, 50, 100) == 100 @@ -61,16 +61,16 @@ assert cl_perfect(28) == True def test_bool(self): - cl_bool = make_cl_func(t.my_bool) + cl_bool = make_cl_func(t.my_bool, [object]) assert cl_bool(0) == False assert cl_bool(42) == True assert cl_bool(True) == True def test_contains(self): - my_contains = make_cl_func(t.my_contains) + my_contains = make_cl_func(t.my_contains, [list, int]) assert my_contains([1, 2, 3], 1) assert not my_contains([1, 2, 3], 0) - is_one_or_two = make_cl_func(t.is_one_or_two) + is_one_or_two = make_cl_func(t.is_one_or_two, [int]) assert is_one_or_two(2) assert not is_one_or_two(3) @@ -88,9 +88,9 @@ assert f1(1) == 2 f2 = make_cl_func(t.while_func, [int]) assert f2(10) == 55 - f3 = make_cl_func(t.simple_id) + f3 = make_cl_func(t.simple_id, [int]) assert f3(9) == 9 - f4 = make_cl_func(t.branch_id) + f4 = make_cl_func(t.branch_id, [int, int, int]) assert f4(1, 2, 3) == 2 assert f4(0, 2, 3) == 3 f5 = make_cl_func(t.int_id, [int]) @@ -124,7 +124,7 @@ assert result.val == ( '#(#() #(0) #(1) #(0 1) #(2) #(0 2) #(1 2) #(0 1 2))') def test_yast(self): - cl_sum = make_cl_func(t.yast) # yet another sum test + cl_sum = make_cl_func(t.yast, [list]) # yet another sum test assert cl_sum(range(12)) == 66 Deleted: /pypy/branch/pycompiler/translator/tool/flowtrace.py ============================================================================== --- /pypy/branch/pycompiler/translator/tool/flowtrace.py Fri Jul 1 18:28:54 2005 +++ (empty file) @@ -1,394 +0,0 @@ -""" - -This is an experimental hack - use it at your peril! I (rxe) needed some sanity -check when (attempting) to write gencpp.py and this ended up being a useful -exercise. I doubt it much use to anyone else or the rest of the project, but it -might have some interesting possiblities later on once we have full translation. -:-) - -The idea is simple - take the basic blocks output via the flow object space and -evaluate them against the standard object space. It is effectively the same as -creating a C extension to the CPython interpreter to use the CPython API instead -of interpreting bytecodes - except in this case the we don't need to compile -anything and all space operations are emitted on the fly. One might call this a -flow interpreter - I wouldn't go that far! - -""" -import autopath -from pypy.objspace.flow import FlowObjSpace -from pypy.objspace.flow.model import traverse, Constant, Variable, Block, Link -from pypy.translator.simplify import simplify_graph -from pypy.interpreter.baseobjspace import OperationError -from pypy.interpreter.argument import Arguments - - -class FlowTracer(object): - - def __init__(self, flow_space, space, debug = False, trace = True): - self.space = space - self.flow_space = flow_space - self.trace = trace - self.debug = debug - - def pprint(self, v): - s = self.space.unwrap(self.space.repr(v.e_value)) - if len(s) > 30: - s = s[:27] + "..." - - if isinstance(v, Constant): - s = "Const(%s)" % s - - elif isinstance(v, Variable): - s = "%s(%s)" % (v, s) - - else: - assert False, "really?" - return s - - - def get_blocknames(self, graph): - blocknames = {} - def visit(n): - if isinstance(n, Block): - blocknames[n] = 'block%d' % len(blocknames) - - traverse(visit, graph) - return blocknames - - - def wrap_constants(self, graph): - all = [] - - def visit(n): - # Note - be careful with uniqueitems and constants, as there can - # multiple constant of the same value (XXX why?) - if isinstance(n, Block): - values = [] - values += n.inputargs - for op in n.operations: - values += op.args - - for ii in values: - all.append(ii) - - all.append(n.exitswitch) - - if isinstance(n, Link): - values = n.args - for ii in values: - all.append(ii) - - traverse(visit, graph) - for ii in all: - - if isinstance(ii, Constant) : - ii.e_value = self.space.wrap(ii.value) - - else: - assert (isinstance(ii, Variable) or ii is None) - - def wrap_linkexits(self, graph): - all = [] - - def visit(n): - if isinstance(n, Link): - all.append(n) - - traverse(visit, graph) - - for l in all: - l.exitcase = self.space.wrap(l.exitcase) - - - def execute_function(self, graph, *args_w): - - curblock = graph.startblock - assert len(curblock.inputargs) == len(args_w) - - # We add value as evaluated values during interpretation - # to variables, constants and exit switches. - # Variables are done on assignment (ie lazily) - for input, arg in zip(curblock.inputargs, args_w): - input.e_value = arg - - # Here we add value attribute with wrap - self.wrap_constants(graph) - self.wrap_linkexits(graph) - - blocknames = self.get_blocknames(graph) - last_exception = None - while True: - - if self.trace: - print 'Entering %s:' % blocknames[curblock] - print ' Input args :- %s' % (", ".join(map(self.pprint, curblock.inputargs))) - print ' Operations :-' - - for op in curblock.operations: - - # Why does op.args have a list in it? - opargs = [a.e_value for a in op.args] - if self.trace: - print ' %s = space.%s(%s)' % (op.result, - op.opname, - ", ".join(map(self.pprint, op.args))) - - if op.opname == "exception": - assert (len(opargs) == 1) - # XXX What we suppose to do with argument??? - if last_exception is not None: - res = last_exception - last_exception = None - else: - res = self.space.w_None - - elif op.opname == "call_args": - assert (len(opargs) >= 2) - shape = self.space.unwrap(opargs[1]) - args = Arguments.fromshape(shape, *opargs[2:]) - res = self.call_args(opargs[0], args) - - else: - # More special cases - spaceop = getattr(self.space, op.opname) - - if op.opname in ("newlist", "newdict", "newtuple"): - # These expect a list, not a *args - res = spaceop(opargs) - - else: - try: - res = spaceop(*opargs) - - # More special case - if op.opname == "is_true": - # Rewrap it! - res = self.space.wrap(res) - - except OperationError, exc: - last_exception = exc.w_type - res = self.space.w_None - - op.result.e_value = res - - if self.trace: - # Cases will likely not be a space object - if curblock.exits and curblock.exitswitch == op.result: - print ' %s := exit(%s)' % (op.result, op.result.e_value) - else: - print ' %s := %s' % (op.result, self.pprint(op.result)) - - # Switch to next block - if curblock.exits: - - # exits (safe code) - exit_link = None - if len(curblock.exits) == 1: - exit_link = curblock.exits[0] - - else: - exit_res = curblock.exitswitch.e_value - for link in curblock.exits: - if self.space.is_true(self.space.eq(exit_res, link.exitcase)): - exit_link = link - break - - assert exit_link is not None - - if self.trace: - print ' Exit to %s :- ' % blocknames[exit_link.target] - - sourceargs = exit_link.args - targetargs = exit_link.target.inputargs - assert len(sourceargs) == len(targetargs) - - for s, t in zip(sourceargs, targetargs): - if self.trace: - print " %s = %s" % (t, s) - - t.e_value = s.e_value - - curblock = exit_link.target - - if self.trace: - print - - elif len(curblock.inputargs) == 2: # exc_cls, exc_value - exc_cls, exc_value = curblock.inputargs - if self.trace: - print "Raising -", - print self.pprint(exc_cls), self.pprint(exc_value) - raise exc_cls.e_value, exc_value.e_value - - else: - result = curblock.inputargs[0] - if self.trace: - print "Returning -", self.pprint(result) - - return result.e_value - - - def call_args(self, w_func, args): - - func = self.space.unwrap(w_func) - if hasattr(func, "func_code"): - graph = self.flow_space.build_flow(func) - simplify_graph(graph) - if self.debug: - debug(func) - scope_w = args.parse(func.name, func.code.signature(), func.defs_w) - return self.execute_function(graph, *scope_w) - - else: - # XXX We could try creating the flow graph by runnning another - # flow objspace under self.space. Hmmm - if only I had - # bigger computer. - - # Instead we cheat (this is great fun when it is a fake type :-)) - if self.trace: - print "WOA! Cheating!", w_func - - return self.space.call_args(w_func, args) - - - def call(self, f, *args): - w = self.space.wrap - args_w = [w(ii) for ii in args] - w_func = w(f) - - res = self.call_args(w_func, Arguments(self.space, args_w)) - return self.space.unwrap(res) - - -def debug(func): - """Shows the control flow graph with annotations if computed. - Requires 'dot' and pygame.""" - from pypy.translator.tool.pygame.graphdisplay import GraphDisplay - from pypy.translator.tool.graphpage import FlowGraphPage - from pypy.translator.translator import Translator - t = Translator(func) - t.simplify() - #t.annotate([int]) - FlowGraphPage(t).display() - -def timeit(num, func, *args): - from time import time as now - start = now() - for i in xrange(num): - print func(*args) - return now() - start - -if __name__ == '__main__': - from pypy.objspace.std import Space - space = Space() - - def create_std_func(app_func): - - import new - from pypy.interpreter.gateway import app2interp - - # Horrible hack (ame needs to start with "app_") - app_func = new.function(app_func.func_code, - app_func.func_globals, - "app_" + app_func.__name__) - - # Create our function - func_gw = app2interp(app_func) - func = func_gw.get_function(space) - w_func = space.wrap(func) - - def f(*args): - args_w = [space.wrap(ii) for ii in args] - args_ = Arguments(space, args_w) - w_result = space.call_args(w_func, args_) - return space.unwrap(w_result) - return f - - def create_flow_func(f): - flow_space = FlowObjSpace() - interpreter = FlowTracer(flow_space, space) - def func(*args): - return interpreter.call(f, *args) - return func - - def do(f, *args): - print "doing %s(%s)" % (f.__name__, ", ".join(map(str, args))) - f_flow = create_flow_func(f) - res = f_flow(*args) - f_norm = create_std_func(f) - res_norm = f_norm(*args) - assert res == res_norm - return res - - def do_flow_only(f, *args): - print "doing %s(%s)" % (f.__name__, ", ".join(map(str, args))) - f_flow = create_flow_func(f) - res = f_flow(*args) - return res - - #///////////////////////////////////////////////////////////////////////////// - - def tests(): - from pypy.translator.test import snippet - - tests = [ - (snippet.if_then_else, 1, 2, 3), - (snippet.if_then_else, 0, 2, 3), - (snippet.my_gcd, 256, 192), - (snippet.is_perfect_number, 81), - (snippet.my_bool, 1), - (snippet.my_bool, 0), - (snippet.two_plus_two,), - #(snippet.sieve_of_eratosthenes,), - (snippet.simple_func, 10), - (snippet.nested_whiles, 1, 10), - (snippet.simple_func, 10), - (snippet.builtinusage,), - (snippet.poor_man_range, 10), - (snippet.poor_man_rev_range, 10), - (snippet.simple_id, 2) , - (snippet.branch_id, 1, "k", 1.0) , - (snippet.branch_id, False, "k", 1.0) , - (snippet.builtinusage,), - (snippet.yast, [1,2,3,4,5]), - (snippet.time_waster, 5), - (snippet.half_of_n, 20), - (snippet.int_id, 20), - (snippet.greet, "world"), - (snippet.choose_last,), - #(snippet.choose_last,), XXX Why does repeating this break? - (snippet.poly_branch, 1), - (snippet.s_and, 1, 1), - (snippet.s_and, 0, 1), - (snippet.s_and, 1, 0), - (snippet.s_and, 0, 0), - (snippet.break_continue, 15), - (snippet.reverse_3, ("k", 1, 1.0)), - (snippet.finallys, ("k", 1, 1.0)), - (snippet.finallys, ("k",)), - (snippet.finallys, []), - (snippet._append_five, []), - (snippet._append_five, [1,2,3]), - ] - for ii in tests: - print do(*ii) - - tests = [ - (snippet.factorial, 4), - (snippet.factorial2, 4), - (snippet.call_five,), - (snippet.build_instance,), - (snippet.set_attr,), - (snippet.merge_setattr, 0), - (snippet.merge_setattr, 1), - # XXX These don't work from test.snippet (haven't tried anymore) - #(snippet.inheritance1,), - #(snippet.inheritance2,), - - ] - - for ii in tests: - print do_flow_only(*ii) - - tests() - Modified: pypy/branch/pycompiler/translator/tool/graphpage.py ============================================================================== --- pypy/branch/pycompiler/translator/tool/graphpage.py (original) +++ pypy/branch/pycompiler/translator/tool/graphpage.py Fri Jul 1 18:28:54 2005 @@ -133,8 +133,9 @@ return for var in vars: if hasattr(var, 'concretetype'): - info = self.links.get(var.name, var.name) - info = '(%s) %s' % (var.concretetype, info) + #info = self.links.get(var.name, var.name) + #info = '(%s) %s' % (var.concretetype, info) + info = str(var.concretetype) self.links[var.name] = info for graph in graphs: traverse(visit, graph) Modified: pypy/branch/pycompiler/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/branch/pycompiler/translator/tool/pygame/drawgraph.py (original) +++ pypy/branch/pycompiler/translator/tool/pygame/drawgraph.py Fri Jul 1 18:28:54 2005 @@ -230,7 +230,7 @@ def getfont(self, size): if size in self.FONTCACHE: return self.FONTCACHE[size] - elif size < 4: + elif size < 5: self.FONTCACHE[size] = None return None else: Modified: pypy/branch/pycompiler/translator/tool/pygame/graphclient.py ============================================================================== --- pypy/branch/pycompiler/translator/tool/pygame/graphclient.py (original) +++ pypy/branch/pycompiler/translator/tool/pygame/graphclient.py Fri Jul 1 18:28:54 2005 @@ -13,13 +13,48 @@ DOT_FILE = udir.join('graph.dot') PLAIN_FILE = udir.join('graph.plain') +import py +def dot2plain(dotfile, plainfile): + if 0: + cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) + elif 0: + gw = py.execnet.SshGateway('codespeak.net') + channel = gw.remote_exec(""" + import py + content = channel.receive() + fn = py.path.local.make_numbered_dir('makegraph').join('graph.dot') + fn.write(content) + tfn = fn.new(ext='.plain') + py.process.cmdexec("dot -Tplain %s >%s" %(fn, tfn)) + channel.send(tfn.read()) + """) + channel.send(py.path.local(dotfile).read()) + plainfile = py.path.local(plainfile) + plainfile.write(channel.receive()) + else: + import urllib + content = py.path.local(dotfile).read() + request = urllib.urlencode({'dot': content}) + try: + urllib.urlretrieve('http://codespeak.net/pypy/convertdot.cgi', + str(plainfile), + data=request) + except IOError: + success = False + else: + plainfile = py.path.local(plainfile) + success = (plainfile.check(file=1) and + plainfile.read().startswith('graph ')) + if not success: + print "NOTE: failed to use codespeak's convertdot.cgi, trying local 'dot'" + cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) class ClientGraphLayout(GraphLayout): def __init__(self, connexion, key, dot, links, **ignored): # generate a temporary .dot file and call dot on it DOT_FILE.write(dot) - cmdexec('dot -Tplain %s>%s' % (str(DOT_FILE),str(PLAIN_FILE))) + dot2plain(DOT_FILE, PLAIN_FILE) GraphLayout.__init__(self, PLAIN_FILE) self.connexion = connexion self.key = key Modified: pypy/branch/pycompiler/translator/transform.py ============================================================================== --- pypy/branch/pycompiler/translator/transform.py (original) +++ pypy/branch/pycompiler/translator/transform.py Fri Jul 1 18:28:54 2005 @@ -10,9 +10,17 @@ import types from pypy.objspace.flow.model import SpaceOperation from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import last_exception +from pypy.objspace.flow.model import last_exception, checkgraph from pypy.translator.annrpython import CannotSimplify from pypy.annotation import model as annmodel +from pypy.annotation.specialize import MemoTable + + +def checkgraphs(self, blocks): + for block in blocks: + fn = self.annotated[block] + graph = self.translator.flowgraphs[fn] + checkgraph(graph) def fully_annotated_blocks(self): """Ignore blocked blocks.""" @@ -32,20 +40,19 @@ def transform_allocate(self, block_subset): """Transforms [a] * b to alloc_and_set(b, a) where b is int.""" for block in block_subset: - operations = block.operations[:] - n_op = len(operations) - for i in range(0, n_op-1): - op1 = operations[i] - op2 = operations[i+1] - if (op1.opname == 'newlist' and - len(op1.args) == 1 and - op2.opname == 'mul' and - op1.result is op2.args[0] and - self.gettype(op2.args[1]) is int): + length1_lists = {} # maps 'c' to 'a', in the above notation + for i in range(len(block.operations)): + op = block.operations[i] + if (op.opname == 'newlist' and + len(op.args) == 1): + length1_lists[op.result] = op.args[0] + elif (op.opname == 'mul' and + op.args[0] in length1_lists and + self.gettype(op.args[1]) is int): new_op = SpaceOperation('alloc_and_set', - (op2.args[1], op1.args[0]), - op2.result) - block.operations[i+1:i+2] = [new_op] + (op.args[1], length1_lists[op.args[0]]), + op.result) + block.operations[i] = new_op # a[b:c] # --> @@ -153,10 +160,20 @@ if not specialcase: op.args[0] = Constant(specialized_callb.prebuiltinstances.keys()[0]) else: - if op.opname == 'simple_call': - op.opname = intern('simple_specialcase') + if op.opname != 'simple_call': + assert 0, "not supported: call_args to a specialized function" + callable = callb.prebuiltinstances.keys()[0] + tag = getattr(callable, '_annspecialcase_', None) + if tag == 'specialize:memo': + arglist_s = [self.binding(v) for v in op.args[1:]] + memo_table = MemoTable(self.bookkeeper, + callable, + self.binding(op.result), + arglist_s) + op.opname = intern('call_memo') + op.args[0] = Constant(memo_table) else: - op.opname = intern('specialcase_args') + op.opname = intern('call_specialcase') default_extra_passes = [ transform_specialization, @@ -167,10 +184,14 @@ """Apply set of transformations available.""" # WARNING: this produces incorrect results if the graph has been # modified by t.simplify() after it had been annotated. - if ann.translator: - ann.translator.checkgraphs() if block_subset is None: - block_subset = list(fully_annotated_blocks(ann)) + block_subset = fully_annotated_blocks(ann) + d = {} + for block in block_subset: + d[block] = True + block_subset = d + if ann.translator: + checkgraphs(ann, block_subset) transform_dead_code(ann, block_subset) for pass_ in extra_passes: pass_(ann, block_subset) @@ -178,4 +199,5 @@ # chance to remove dependency on certain variables transform_dead_op_vars(ann, block_subset) if ann.translator: - ann.translator.checkgraphs() + checkgraphs(ann, block_subset) + Modified: pypy/branch/pycompiler/translator/translator.py ============================================================================== --- pypy/branch/pycompiler/translator/translator.py (original) +++ pypy/branch/pycompiler/translator/translator.py Fri Jul 1 18:28:54 2005 @@ -4,7 +4,7 @@ translation-related code. It can be used for interactive testing of the translator; see pypy/bin/translator.py. """ -import autopath, os, sys +import autopath, os, sys, types from pypy.objspace.flow.model import * from pypy.translator.simplify import simplify_graph @@ -39,9 +39,20 @@ if self.entrypoint: self.getflowgraph() + def __getstate__(self): + # try to produce things a bit more ordered + return self.entrypoint, self.functions, self.__dict__ + + def __setstate__(self, args): + assert len(args) == 3 + self.__dict__.update(args[2]) + assert args[0] is self.entrypoint and args[1] is self.functions + def getflowgraph(self, func=None, called_by=None, call_tag=None): """Get the flow graph for a function (default: the entry point).""" func = func or self.entrypoint + if not isinstance(func, types.FunctionType): + raise Exception, "getflowgraph() expects a function, got %s" % func try: graph = self.flowgraphs[func] except KeyError: @@ -136,10 +147,15 @@ self.rtyper = RPythonTyper(self.annotator) self.rtyper.specialize() + def backend_optimizations(self): + from pypy.translator.backendoptimization import backend_optimizations + for graph in self.flowgraphs.values(): + backend_optimizations(graph) + def source(self, func=None): """Returns original Python source. - Returns for functions written while the + Returns for functions written during the interactive session. """ func = func or self.entrypoint Deleted: /pypy/branch/pycompiler/translator/typer.py ============================================================================== --- /pypy/branch/pycompiler/translator/typer.py Fri Jul 1 18:28:54 2005 +++ (empty file) @@ -1,209 +0,0 @@ -from __future__ import generators -import autopath -from pypy.objspace.flow.model import SpaceOperation, Variable, Constant -from pypy.objspace.flow.model import Block, Link, uniqueitems -from pypy.translator.unsimplify import insert_empty_block - - -class TyperError(Exception): - def __str__(self): - result = Exception.__str__(self) - if hasattr(self, 'where'): - result += '\n.. %r\n.. %r' % self.where - return result - - -class Specializer: - - def __init__(self, annotator, defaultconcretetype, typematches, - specializationtable): - self.annotator = annotator - self.defaultconcretetype = defaultconcretetype - self.typematches = typematches - # turn the table into a dict for faster look-ups - d = {} - for e in specializationtable: - opname1 = e[0] - opname2 = e[1] - spectypes = e[2:-1] - restype = e[-1] - info = opname2, spectypes, restype - d.setdefault(opname1, []).append(info) - d.setdefault(opname2, []).append(info) - self.specializationdict = d - - def specialize(self): - """Main entry point: specialize all annotated blocks of the program.""" - # new blocks can be created as a result of specialize_block(), so - # we need to be careful about the loop here. - already_seen = {} - pending = self.annotator.annotated.keys() - while pending: - for block in pending: - if block.operations != (): - self.specialize_block(block) - already_seen[block] = True - pending = [block for block in self.annotator.annotated - if block not in already_seen] - - def settype(self, a, concretetype): - """Set the concretetype of a Variable.""" - assert isinstance(a, Variable) - if hasattr(a, 'concretetype') and a.concretetype != concretetype: - raise TyperError, "inconsitent type for %r: %r != %r" % ( - a, a.concretetype, concretetype) - a.concretetype = concretetype - - def setbesttype(self, a): - """Set the best concretetype for a Variable according to - the annotations.""" - try: - return a.concretetype - except AttributeError: - s_value = self.annotator.binding(a, True) - if s_value is not None: - besttype = self.annotation2concretetype(s_value) - else: - besttype = self.defaultconcretetype - self.settype(a, besttype) - return besttype - - def annotation2concretetype(self, s_value): - for concretetype in self.typematches: - if concretetype.s_annotation.contains(s_value): - return concretetype - return self.defaultconcretetype - - def convertvar(self, v, concretetype): - """Get the operation(s) needed to convert 'v' to the given type.""" - ops = [] - if isinstance(v, Constant): - # we should never modify a Constant in-place - v = Constant(v.value) - v.concretetype = concretetype - - elif hasattr(v, 'concretetype') and v.concretetype != concretetype: - # XXX do we need better conversion paths? - - # 1) convert to the generic type - if v.concretetype != self.defaultconcretetype: - v2 = Variable() - v2.concretetype = self.defaultconcretetype - newops = list(v.concretetype.convert_to_obj(self, v, v2)) - v = v2 - ops += newops - - # 2) convert back from the generic type - if concretetype != self.defaultconcretetype: - v2 = Variable() - v2.concretetype = concretetype - newops = list(concretetype.convert_from_obj(self, v, v2)) - v = v2 - ops += newops - - return v, ops - - def specialize_block(self, block): - # give the best possible types to the input args - for a in block.inputargs: - self.setbesttype(a) - - # specialize all the operations, as far as possible - newops = [] - for op in block.operations: - - args = list(op.args) - bindings = [self.annotator.binding(a, True) for a in args] - - # replace constant annotations with real Constants - for i in range(len(op.args)): - if isinstance(args[i], Variable) and bindings[i] is not None: - if bindings[i].is_constant(): - args[i] = Constant(bindings[i].const) - op = SpaceOperation(op.opname, args, op.result) - - # make a specialized version of the current operation - # (which may become several operations) - try: - flatten_ops(self.specialized_op(op, bindings), newops) - except TyperError, e: - e.where = (block, op) - raise - - block.operations[:] = newops - self.insert_link_conversions(block) - - - def typed_op(self, op, argtypes, restype, newopname=None): - """Make a typed copy of the given SpaceOperation.""" - result = [] - args = list(op.args) - assert len(argtypes) == len(args) - - # type-convert the input arguments - for i in range(len(args)): - args[i], convops = self.convertvar(args[i], argtypes[i]) - result += convops - - # store the result variable's type - self.settype(op.result, restype) - - # store the possibly modified SpaceOperation - op = SpaceOperation(newopname or op.opname, args, op.result) - result.append(op) - return result - - - def insert_link_conversions(self, block): - # insert the needed conversions on the links - can_insert_here = block.exitswitch is None and len(block.exits) == 1 - for link in block.exits: - try: - for i in range(len(link.args)): - a1 = link.args[i] - if a1 in (link.last_exception, link.last_exc_value):# treated specially in gen_link - continue - a2 = link.target.inputargs[i] - a2type = self.setbesttype(a2) - a1, convops = self.convertvar(a1, a2type) - if convops and not can_insert_here: - # cannot insert conversion operations around a single - # link, unless it is the only exit of this block. - # create a new block along the link... - newblock = insert_empty_block(self.annotator.translator, - link) - # ...and do the conversions there. - self.insert_link_conversions(newblock) - break # done with this link - flatten_ops(convops, block.operations) - link.args[i] = a1 - except TyperError, e: - e.where = (block, link) - raise - - - def specialized_op(self, op, bindings): - specializations = self.specializationdict.get(op.opname, ()) - for opname2, spectypes, restype in specializations: - assert len(spectypes) == len(op.args) == len(bindings) - for i in range(len(spectypes)): - if bindings[i] is None: - break - if not spectypes[i].s_annotation.contains(bindings[i]): - break - else: - # specialization found - yield self.typed_op(op, spectypes, restype, newopname=opname2) - return - # specialization not found - argtypes = [self.defaultconcretetype] * len(op.args) - yield self.typed_op(op, argtypes, self.defaultconcretetype) - - -def flatten_ops(op, newops): - # Flatten lists and generators and record all SpaceOperations found - if isinstance(op, SpaceOperation): - newops.append(op) - else: - for op1 in op: - flatten_ops(op1, newops) From adim at codespeak.net Fri Jul 1 18:30:58 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 18:30:58 +0200 (CEST) Subject: [pypy-svn] r14042 - in pypy/branch/pycompiler: annotation bin documentation documentation/tool documentation/website interpreter lib module module/_codecs module/recparser module/sys objspace objspace/flow objspace/std objspace/std/test rpython rpython/test tool Message-ID: <20050701163058.C6C1927B51@code1.codespeak.net> Author: adim Date: Fri Jul 1 18:30:34 2005 New Revision: 14042 Added: pypy/branch/pycompiler/rpython/llinterp.py - copied unchanged from r14039, pypy/dist/pypy/rpython/llinterp.py pypy/branch/pycompiler/rpython/rconstantdict.py - copied unchanged from r14039, pypy/dist/pypy/rpython/rconstantdict.py pypy/branch/pycompiler/rpython/rdict.py - copied unchanged from r14039, pypy/dist/pypy/rpython/rdict.py pypy/branch/pycompiler/rpython/test/test_llinterp.py - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_llinterp.py pypy/branch/pycompiler/rpython/test/test_rbuiltin.py - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/branch/pycompiler/rpython/test/test_rconstantdict.py - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rconstantdict.py pypy/branch/pycompiler/rpython/test/test_rdict.py - copied unchanged from r14039, pypy/dist/pypy/rpython/test/test_rdict.py pypy/branch/pycompiler/tool/asterisk.py - copied unchanged from r14039, pypy/dist/pypy/tool/asterisk.py Removed: pypy/branch/pycompiler/lib/inprogress__codecs.py pypy/branch/pycompiler/lib/unicodecodec.py pypy/branch/pycompiler/objspace/dummy.py Modified: pypy/branch/pycompiler/annotation/binaryop.py pypy/branch/pycompiler/annotation/bookkeeper.py pypy/branch/pycompiler/annotation/builtin.py pypy/branch/pycompiler/annotation/classdef.py pypy/branch/pycompiler/annotation/model.py pypy/branch/pycompiler/annotation/pairtype.py pypy/branch/pycompiler/annotation/policy.py pypy/branch/pycompiler/annotation/specialize.py pypy/branch/pycompiler/annotation/unaryop.py pypy/branch/pycompiler/bin/translator.py pypy/branch/pycompiler/documentation/architecture.txt pypy/branch/pycompiler/documentation/coding-guide.txt pypy/branch/pycompiler/documentation/contributor.txt (contents, props changed) pypy/branch/pycompiler/documentation/faq.txt (contents, props changed) pypy/branch/pycompiler/documentation/misc.txt pypy/branch/pycompiler/documentation/objspace.txt pypy/branch/pycompiler/documentation/svn-help.txt pypy/branch/pycompiler/documentation/tool/makecontributor.py (props changed) pypy/branch/pycompiler/documentation/translation.txt pypy/branch/pycompiler/documentation/website/EP2005-announcement.txt (props changed) pypy/branch/pycompiler/documentation/website/news.txt pypy/branch/pycompiler/interpreter/eval.py pypy/branch/pycompiler/interpreter/function.py pypy/branch/pycompiler/interpreter/nestedscope.py pypy/branch/pycompiler/interpreter/pycode.py pypy/branch/pycompiler/interpreter/pyopcode.py pypy/branch/pycompiler/interpreter/typedef.py pypy/branch/pycompiler/lib/_exceptions.py pypy/branch/pycompiler/module/README.txt (props changed) pypy/branch/pycompiler/module/_codecs/ (props changed) pypy/branch/pycompiler/module/recparser/automata.py pypy/branch/pycompiler/module/recparser/ebnfparse.py pypy/branch/pycompiler/module/recparser/grammar.py pypy/branch/pycompiler/module/recparser/pythonlexer.py pypy/branch/pycompiler/module/recparser/pythonutil.py pypy/branch/pycompiler/module/recparser/tuplebuilder.py (contents, props changed) pypy/branch/pycompiler/module/sys/state.py pypy/branch/pycompiler/objspace/flow/flowcontext.py pypy/branch/pycompiler/objspace/flow/model.py pypy/branch/pycompiler/objspace/flow/objspace.py pypy/branch/pycompiler/objspace/flow/operation.py pypy/branch/pycompiler/objspace/std/floatobject.py pypy/branch/pycompiler/objspace/std/floattype.py pypy/branch/pycompiler/objspace/std/inttype.py pypy/branch/pycompiler/objspace/std/listobject.py pypy/branch/pycompiler/objspace/std/model.py pypy/branch/pycompiler/objspace/std/mro.py pypy/branch/pycompiler/objspace/std/objspace.py pypy/branch/pycompiler/objspace/std/stringobject.py pypy/branch/pycompiler/objspace/std/strutil.py pypy/branch/pycompiler/objspace/std/test/test_floatobject.py pypy/branch/pycompiler/objspace/std/test/test_strutil.py pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py pypy/branch/pycompiler/objspace/std/tupleobject.py pypy/branch/pycompiler/objspace/std/unicodeobject.py pypy/branch/pycompiler/objspace/std/unicodetype.py pypy/branch/pycompiler/rpython/annlowlevel.py pypy/branch/pycompiler/rpython/exceptiondata.py pypy/branch/pycompiler/rpython/lltype.py pypy/branch/pycompiler/rpython/normalizecalls.py pypy/branch/pycompiler/rpython/rarithmetic.py pypy/branch/pycompiler/rpython/rbool.py (contents, props changed) pypy/branch/pycompiler/rpython/rbuiltin.py pypy/branch/pycompiler/rpython/rclass.py pypy/branch/pycompiler/rpython/rfloat.py (contents, props changed) pypy/branch/pycompiler/rpython/rint.py pypy/branch/pycompiler/rpython/rlist.py pypy/branch/pycompiler/rpython/rmodel.py pypy/branch/pycompiler/rpython/robject.py pypy/branch/pycompiler/rpython/rpbc.py pypy/branch/pycompiler/rpython/rptr.py pypy/branch/pycompiler/rpython/rrange.py pypy/branch/pycompiler/rpython/rslice.py pypy/branch/pycompiler/rpython/rstr.py pypy/branch/pycompiler/rpython/rtuple.py pypy/branch/pycompiler/rpython/rtyper.py pypy/branch/pycompiler/rpython/test/snippet.py (props changed) pypy/branch/pycompiler/rpython/test/test_llann.py pypy/branch/pycompiler/rpython/test/test_lltype.py pypy/branch/pycompiler/rpython/test/test_normalizecalls.py pypy/branch/pycompiler/rpython/test/test_rbool.py (contents, props changed) pypy/branch/pycompiler/rpython/test/test_rclass.py pypy/branch/pycompiler/rpython/test/test_rfloat.py (contents, props changed) pypy/branch/pycompiler/rpython/test/test_rint.py (contents, props changed) pypy/branch/pycompiler/rpython/test/test_rlist.py pypy/branch/pycompiler/rpython/test/test_rpbc.py pypy/branch/pycompiler/rpython/test/test_rptr.py pypy/branch/pycompiler/rpython/test/test_rrange.py pypy/branch/pycompiler/rpython/test/test_rstr.py pypy/branch/pycompiler/rpython/test/test_rtuple.py pypy/branch/pycompiler/rpython/test/test_rtyper.py pypy/branch/pycompiler/tool/_enum_exceptions.py pypy/branch/pycompiler/tool/ansi_print.py pypy/branch/pycompiler/tool/cache.py pypy/branch/pycompiler/tool/import_graph.py (props changed) pypy/branch/pycompiler/tool/traceconfig.py (props changed) pypy/branch/pycompiler/tool/unionfind.py Log: (merged from the top directory) svn merge -r13379:14040 http://codespeak.net/svn/pypy/dist/pypy Modified: pypy/branch/pycompiler/annotation/binaryop.py ============================================================================== --- pypy/branch/pycompiler/annotation/binaryop.py (original) +++ pypy/branch/pycompiler/annotation/binaryop.py Fri Jul 1 18:30:34 2005 @@ -32,14 +32,11 @@ 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or', 'inplace_xor', 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', 'cmp', - 'union', 'coerce', + 'coerce', ] +[opname+'_ovf' for opname in - """add sub mul truediv - floordiv div mod divmod pow lshift - inplace_add inplace_sub inplace_mul inplace_truediv - inplace_floordiv inplace_div inplace_mod inplace_pow - inplace_lshift""".split() + """add sub mul floordiv div mod pow lshift + """.split() ]) for opname in BINARY_OPERATIONS: @@ -98,39 +95,46 @@ if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const < obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def le((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const <= obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def eq((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const == obj2.const) else: + getbookkeeper().count("non_int_eq", obj1, obj2) return SomeBool() def ne((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const != obj2.const) else: + getbookkeeper().count("non_int_eq", obj1, obj2) return SomeBool() def gt((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const > obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def ge((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const >= obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def cmp((obj1, obj2)): + getbookkeeper().count("cmp", obj1, obj2) if obj1.is_constant() and obj2.is_constant(): return immutablevalue(cmp(obj1.const, obj2.const)) else: @@ -179,9 +183,11 @@ return r def divmod((obj1, obj2)): + getbookkeeper().count("divmod", obj1, obj2) return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()]) def coerce((obj1, obj2)): + getbookkeeper().count("coerce", obj1, obj2) return pair(obj1, obj2).union() # reasonable enough # cloning a function with identical code, for the can_only_throw attribute @@ -302,6 +308,7 @@ class __extend__(pairtype(SomeString, SomeObject)): def mod((str, args)): + getbookkeeper().count('strformat', str, args) return SomeString() @@ -328,6 +335,11 @@ lst1.listdef.union(lst2.listdef) return lst1 + def eq((lst1, lst2)): + lst1.listdef.union(lst2.listdef) + return SomeBool() + ne = eq + class __extend__(pairtype(SomeList, SomeObject)): @@ -364,13 +376,16 @@ class __extend__(pairtype(SomeDict, SomeObject)): def getitem((dic1, obj2)): + getbookkeeper().count("dict_getitem", dic1) return dic1.dictdef.read_value() def setitem((dic1, obj2), s_value): + getbookkeeper().count("dict_setitem", dic1) dic1.dictdef.generalize_key(obj2) dic1.dictdef.generalize_value(s_value) def delitem((dic1, obj1)): + getbookkeeper().count("dict_delitem", dic1) pass @@ -391,6 +406,7 @@ except IndexError: return SomeImpossibleValue() else: + getbookkeeper().count("tuple_random_getitem", tup1) return unionof(*tup1.items) @@ -400,13 +416,16 @@ return getbookkeeper().newlist(lst1.listdef.read_item()) def getitem((lst1, int2)): + getbookkeeper().count("list_getitem", int2) return lst1.listdef.read_item() def setitem((lst1, int2), s_value): + getbookkeeper().count("list_setitem", int2) lst1.listdef.mutate() lst1.listdef.generalize(s_value) def delitem((lst1, int2)): + getbookkeeper().count("list_delitem", int2) lst1.listdef.resize() class __extend__(pairtype(SomeList, SomeSlice)): @@ -430,14 +449,17 @@ class __extend__(pairtype(SomeString, SomeInteger)): def getitem((str1, int2)): + getbookkeeper().count("str_getitem", int2) return SomeChar() def mul((str1, int2)): # xxx do we want to support this + getbookkeeper().count("str_mul", str1, int2) return SomeString() class __extend__(pairtype(SomeInteger, SomeString)): def mul((int1, str2)): # xxx do we want to support this + getbookkeeper().count("str_mul", str2, int1) return SomeString() class __extend__(pairtype(SomeInteger, SomeList)): @@ -464,11 +486,11 @@ class __extend__(pairtype(SomeBuiltin, SomeBuiltin)): def union((bltn1, bltn2)): - if bltn1.analyser != bltn2.analyser: + if bltn1.analyser != bltn2.analyser or bltn1.methodname != bltn2.methodname: raise UnionError("merging incompatible builtins == BAD!") else: s_self = unionof(bltn1.s_self, bltn2.s_self) - return SomeBuiltin(bltn1.analyser, s_self) + return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) class __extend__(pairtype(SomePBC, SomePBC)): def union((pbc1, pbc2)): @@ -485,11 +507,7 @@ classdef2 = classdef if classdef != d[x]: classdef = classdef.commonbase(d[x]) - for cand in classdef.getmro(): - if x in cand.cls.__dict__.values(): - classdef = cand - break - else: + if classdef is None: raise UnionError( "confused pbc union trying unwarranted" "moving up of method %s from pair %s %s" % Modified: pypy/branch/pycompiler/annotation/bookkeeper.py ============================================================================== --- pypy/branch/pycompiler/annotation/bookkeeper.py (original) +++ pypy/branch/pycompiler/annotation/bookkeeper.py Fri Jul 1 18:30:34 2005 @@ -24,6 +24,7 @@ self.objects = { obj: True } self.read_locations = {} self.attrs = {} + self.values = {} # used in the typer def update(self, other): self.objects.update(other.objects) @@ -39,6 +40,123 @@ self.objects.update(other.objects) self.patterns.update(other.patterns) +class Stats: + + def __init__(self, bookkeeper): + self.bookkeeper = bookkeeper + self.classify = {} + + def count(self, category, *args): + for_category = self.classify.setdefault(category, {}) + classifier = getattr(self, 'consider_%s' % category, self.consider_generic) + outcome = classifier(*args) + for_category[self.bookkeeper.position_key] = outcome + + def indexrepr(self, idx): + if idx.is_constant(): + if idx.const is None: + return '' + if isinstance(idx, SomeInteger): + if idx.const >=0: + return 'pos-constant' + else: + return 'Neg-constant' + return idx.const + else: + if isinstance(idx, SomeInteger): + if idx.nonneg: + return "non-neg" + else: + return "MAYBE-NEG" + else: + return self.typerepr(idx) + + def steprepr(self, stp): + if stp.is_constant(): + if stp.const in (1, None): + return 'step=1' + else: + return 'step=%s?' % stp.const + else: + return 'non-const-step %s' % self.typerepr(stp) + + def consider_generic(self, *args): + return tuple([self.typerepr(x) for x in args]) + + def consider_newslice(self, s_start, s_stop, s_step): + return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)]) + + def consider_list_list_eq(self, obj1, obj2): + return obj1, obj2 + + def consider_contains(self, seq): + return seq + + def consider_non_int_eq(self, obj1, obj2): + if obj1.knowntype == obj2.knowntype == list: + self.count("list_list_eq", obj1, obj2) + return obj1.knowntype.__name__, obj2.knowntype.__name__ + + def consider_non_int_comp(self, obj1, obj2): + return obj1.knowntype.__name__, obj2.knowntype.__name__ + + def typerepr(self, obj): + if isinstance(obj, SomeInstance): + return obj.classdef.cls.__name__ + else: + return obj.knowntype.__name__ + + def consider_tuple_iter(self, tup): + ctxt = "[%s]" % sys._getframe(4).f_code.co_name + if tup.is_constant(): + return ctxt, tup.const + else: + return ctxt, tuple([self.typerepr(x) for x in tup.items]) + + def consider_tuple_random_getitem(self, tup): + return tuple([self.typerepr(x) for x in tup.items]) + + def consider_list_index(self): + return '!' + + def consider_list_getitem(self, idx): + return self.indexrepr(idx) + + def consider_list_setitem(self, idx): + return self.indexrepr(idx) + + def consider_list_delitem(self, idx): + return self.indexrepr(idx) + + def consider_str_join(self, s): + if s.is_constant(): + return repr(s.const) + else: + return "NON-CONSTANT" + + def consider_str_getitem(self, idx): + return self.indexrepr(idx) + + def consider_strformat(self, str, args): + if str.is_constant(): + s = repr(str.const) + else: + s = "?!!!!!!" + if isinstance(args, SomeTuple): + return (s, tuple([self.typerepr(x) for x in args.items])) + else: + return (s, self.typerepr(args)) + + def consider_dict_getitem(self, dic): + return dic + + def consider_dict_setitem(self, dic): + return dic + + def consider_dict_delitem(self, dic): + return dic + + class Bookkeeper: """The log of choices that have been made while analysing the operations. It ensures that the same 'choice objects' will be returned if we ask @@ -47,6 +165,12 @@ Currently used for factories and user-defined classes.""" + def __setstate__(self, dic): + self.__dict__.update(dic) # normal action + # import ordering hack + global BUILTIN_ANALYZERS + from pypy.annotation.builtin import BUILTIN_ANALYZERS + def __init__(self, annotator): self.annotator = annotator self.userclasses = {} # map classes to ClassDefs @@ -57,7 +181,8 @@ self.seen_mutable = {} self.listdefs = {} # map position_keys to ListDefs self.dictdefs = {} # map position_keys to DictDefs - + self.immutable_cache = {} + # mapping position -> key, prev_result for specializations self.spec_callsite_keys_results = {} @@ -69,11 +194,17 @@ self.pbc_call_sites = {} - + self.memo_tables = [] + + self.stats = Stats(self) + # import ordering hack global BUILTIN_ANALYZERS from pypy.annotation.builtin import BUILTIN_ANALYZERS + def count(self, category, *args): + self.stats.count(category, *args) + def enter(self, position_key): """Start of an operation. The operation is uniquely identified by the given key.""" @@ -147,8 +278,6 @@ dictdef.generalize_value(s_value) return SomeDict(dictdef) - immutable_cache = {} - def immutablevalue(self, x): """The most precise SomeValue instance that contains the immutable value x.""" @@ -177,23 +306,28 @@ elif tp is float: result = SomeFloat() elif tp is list: + key = Constant(x) try: - return self.immutable_cache[id(x)] + return self.immutable_cache[key] except KeyError: - items_s = [self.immutablevalue(e) for e in x] - result = SomeList(ListDef(self, unionof(*items_s))) - self.immutable_cache[id(x)] = result + result = SomeList(ListDef(self, SomeImpossibleValue())) + self.immutable_cache[key] = result + for e in x: + result.listdef.generalize(self.immutablevalue(e)) elif tp is dict: # exactly a dict + key = Constant(x) try: - return self.immutable_cache[id(x)] + return self.immutable_cache[key] except KeyError: - keys_s = [self.immutablevalue(e) for e in x.keys()] - values_s = [self.immutablevalue(e) for e in x.values()] - result = SomeDict(DictDef(self, unionof(*keys_s), - unionof(*values_s))) - self.immutable_cache[id(x)] = result + result = SomeDict(DictDef(self, + SomeImpossibleValue(), + SomeImpossibleValue())) + self.immutable_cache[key] = result + for ek, ev in x.iteritems(): + result.dictdef.generalize_key(self.immutablevalue(ek)) + result.dictdef.generalize_value(self.immutablevalue(ev)) elif ishashable(x) and x in BUILTIN_ANALYZERS: - result = SomeBuiltin(BUILTIN_ANALYZERS[x]) + result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (x.__module__, x.__name__)) elif isinstance(x, lltype._ptr): result = SomePtr(lltype.typeOf(x)) elif callable(x) or isinstance(x, staticmethod): # XXX @@ -287,38 +421,36 @@ access_sets = self.pbc_maximal_access_sets objects = pbc.prebuiltinstances.keys() - access = None - first = None - change = False - + for obj in objects: if obj is not None: first = obj break + else: + return SomeImpossibleValue() + + change, rep, access = access_sets.find(first) + for obj in objects: + if obj is not None: + change1, rep, access = access_sets.union(rep, obj) + change = change or change1 - if first is not None: - change, rep, access = access_sets.find(objects[0]) - for obj in objects: - if obj is not None: - change1, rep, access = access_sets.union(rep, obj) - change = change or change1 - - access.attrs[attr] = True - position = self.position_key - access.read_locations[position] = True + position = self.position_key + access.read_locations[position] = True actuals = [] + for c in access.objects: + if hasattr(c, attr): + actuals.append(self.immutablevalue(getattr(c, attr))) + s_result = unionof(*actuals) - if access: - for c in access.objects: - if hasattr(c, attr): - actuals.append(self.immutablevalue(getattr(c, attr))) + access.attrs[attr] = s_result if change: for position in access.read_locations: self.annotator.reflowfromposition(position) - return unionof(*actuals) + return s_result def consider_pbc_call(self, pbc, shape, spaceop=None, implicit_init=None): # computation done at fix-point if not isinstance(pbc, SomePBC): Modified: pypy/branch/pycompiler/annotation/builtin.py ============================================================================== --- pypy/branch/pycompiler/annotation/builtin.py (original) +++ pypy/branch/pycompiler/annotation/builtin.py Fri Jul 1 18:30:34 2005 @@ -85,8 +85,8 @@ def builtin_unichr(s_int): return constpropagate(unichr, [s_int], SomeUnicodeCodePoint()) -def builtin_unicode(s_obj): - raise TypeError, "unicode() calls should not happen at interp-level" +##def builtin_unicode(s_obj): +## raise TypeError, "unicode() calls should not happen at interp-level" def our_issubclass(cls1, cls2): """ we're going to try to be less silly in the face of old-style classes""" @@ -148,8 +148,8 @@ r.const = hasattr(s_obj.const, s_attr.const) return r -def builtin_callable(s_obj): - return SomeBool() +##def builtin_callable(s_obj): +## return SomeBool() def builtin_tuple(s_iterable): if isinstance(s_iterable, SomeTuple): @@ -179,10 +179,10 @@ getbookkeeper().warning("ignoring apply%r" % (stuff,)) return SomeObject() -def builtin_compile(*stuff): - s = SomeObject() - s.knowntype = types.CodeType - return s +##def builtin_compile(*stuff): +## s = SomeObject() +## s.knowntype = types.CodeType +## return s def builtin_slice(*args): bk = getbookkeeper() @@ -220,15 +220,15 @@ def rarith_intmask(s_obj): return SomeInteger() -def rarith_ovfcheck(s_obj): - if isinstance(s_obj, SomeInteger) and s_obj.unsigned: - getbookkeeper().warning("ovfcheck on unsigned") - return s_obj - -def rarith_ovfcheck_lshift(s_obj1, s_obj2): - if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned: - getbookkeeper().warning("ovfcheck_lshift with unsigned") - return SomeInteger() +##def rarith_ovfcheck(s_obj): +## if isinstance(s_obj, SomeInteger) and s_obj.unsigned: +## getbookkeeper().warning("ovfcheck on unsigned") +## return s_obj + +##def rarith_ovfcheck_lshift(s_obj1, s_obj2): +## if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned: +## getbookkeeper().warning("ovfcheck_lshift with unsigned") +## return SomeInteger() def unicodedata_decimal(s_uchr): raise TypeError, "unicodedate.decimal() calls should not happen at interp-level" @@ -254,8 +254,8 @@ BUILTIN_ANALYZERS[original] = value BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_uint] = restricted_uint -BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck -BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift +##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck +##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init @@ -272,9 +272,9 @@ BUILTIN_ANALYZERS[unicodedata.decimal] = unicodedata_decimal # xxx # os.path stuff -BUILTIN_ANALYZERS[os.path.dirname] = pathpart -BUILTIN_ANALYZERS[os.path.normpath] = pathpart -BUILTIN_ANALYZERS[os.path.join] = pathpart +#BUILTIN_ANALYZERS[os.path.dirname] = pathpart +#BUILTIN_ANALYZERS[os.path.normpath] = pathpart +#BUILTIN_ANALYZERS[os.path.join] = pathpart BUILTIN_ANALYZERS[os.path.exists] = test BUILTIN_ANALYZERS[os.path.isdir] = test @@ -306,9 +306,7 @@ def nullptr(T): assert T.is_constant() p = lltype.nullptr(T.const) - r = SomePtr(lltype.typeOf(p)) - r.const = p - return r + return immutablevalue(p) def cast_pointer(PtrT, s_p): assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p @@ -316,9 +314,18 @@ cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl()) return SomePtr(ll_ptrtype=lltype.typeOf(cast_p)) +def getRuntimeTypeInfo(T): + assert T.is_constant() + return immutablevalue(lltype.getRuntimeTypeInfo(T.const)) + +def runtime_type_info(s_p): + assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % s_p + return SomePtr(lltype.typeOf(lltype.runtime_type_info(s_p.ll_ptrtype._example()))) BUILTIN_ANALYZERS[lltype.malloc] = malloc BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer +BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo +BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info Modified: pypy/branch/pycompiler/annotation/classdef.py ============================================================================== --- pypy/branch/pycompiler/annotation/classdef.py (original) +++ pypy/branch/pycompiler/annotation/classdef.py Fri Jul 1 18:30:34 2005 @@ -7,42 +7,115 @@ from pypy.annotation.model import SomeImpossibleValue, SomePBC, tracking_unionof +# The main purpose of a ClassDef is to collect information about class/instance +# attributes as they are really used. An Attribute object is stored in the +# most general ClassDef where an attribute of that name is read/written: +# classdef.attrs = {'attrname': Attribute()} +# +# The following invariants hold: +# +# (A) if an attribute is read/written on an instance of class A, then the +# classdef of A or a parent class of A has an Attribute object corresponding +# to that name. +# +# (I) if B is a subclass of A, then they don't have both an Attribute for the +# same name. (All information from B's Attribute must be merged into A's.) +# +# Additionally, each ClassDef records an 'attr_sources': it maps attribute +# names to a set of objects that want to provide a constant value for this +# attribute at the level of this class. The attrsources provide information +# higher in the class hierarchy than concrete Attribute()s. It is for the case +# where (so far or definitely) the user program only reads/writes the attribute +# at the level of a subclass, but a value for this attribute could possibly +# exist in the parent class or in an instance of a parent class. +# +# The point of not automatically forcing the Attribute instance up to the +# parent class which has a class attribute of the same name is apparent with +# multiple subclasses: +# +# A +# attr=s1 +# / \ +# / \ +# B C +# attr=s2 attr=s3 +# +# In this case, as long as 'attr' is only read/written from B or C, the +# Attribute on B says that it can be 's1 or s2', and the Attribute on C says +# it can be 's1 or s3'. Merging them into a single Attribute on A would give +# the more imprecise 's1 or s2 or s3'. +# +# The following invariant holds: +# +# (II) if a class A has an Attribute, the 'attrsources' for the same name is +# empty. It is also empty on all subclasses of A. (The information goes +# into the Attribute directly in this case.) +# +# The attrsources have the format {object: classdef}. For class attributes, +# 'object' is the class in question and 'classdef' its corresponding classdef, +# used for binding methods. For attribute sources that are prebuilt instances, +# 'classdef' is None. +# +# The following invariant holds: +# +# (III) for a class A, each attrsource that comes from the class (as opposed to +# from a prebuilt instance) must be merged into all Attributes of the +# same name in all subclasses of A, if any. (Parent class attributes can +# be visible in reads from instances of subclasses.) + + class Attribute: # readonly-ness # SomeThing-ness - # more potential sources (pbcs or classes) of information - # NB. the laziness of 'sources' was required for two reasons: - # * some strange attributes exist on classes but are never touched, - # immutablevalue() wouldn't be happy with them - # * there is an infinite recursion between immutablevalue() and - # add_source_for_attribute() for cyclic constant structures. + # NB. an attribute is readonly if it is a constant class attribute. + # Both writing to the instance attribute and discovering prebuilt + # instances that have the attribute set will turn off readonly-ness. def __init__(self, name, bookkeeper): self.name = name self.bookkeeper = bookkeeper - self.sources = {} # source -> None or ClassDef # XXX a SomeImpossibleValue() constant? later!! self.s_value = SomeImpossibleValue() self.readonly = True self.read_locations = {} + def add_constant_source(self, source, classdef): + s_value = self.bookkeeper.immutablevalue( + source.__dict__[self.name]) + if classdef: + s_value = s_value.bindcallables(classdef) + else: + # a prebuilt instance source forces readonly=False, see above + self.readonly = False + self.s_value = tracking_unionof(self, self.s_value, s_value) + def getvalue(self): - while self.sources: - source, classdef = self.sources.popitem() - s_value = self.bookkeeper.immutablevalue( - source.__dict__[self.name]) - if classdef: - s_value = s_value.bindcallables(classdef) - self.s_value = tracking_unionof(self, self.s_value, s_value) + # Same as 'self.s_value' for historical reasons. return self.s_value def merge(self, other): assert self.name == other.name - self.sources.update(other.sources) self.s_value = tracking_unionof(self, self.s_value, other.s_value) self.readonly = self.readonly and other.readonly self.read_locations.update(other.read_locations) + def mutated(self, homedef): # reflow from attr read positions + s_newvalue = self.getvalue() + # check for method demotion + if isinstance(s_newvalue, SomePBC): + attr = self.name + meth = False + for func, classdef in s_newvalue.prebuiltinstances.items(): + if isclassdef(classdef): + meth = True + break + if meth and getattr(homedef.cls, attr, None) is None: + self.bookkeeper.warning("demoting method %s to base class %s" % (self.name, homedef)) + + for position in self.read_locations: + self.bookkeeper.annotator.reflowfromposition(position) + + class ClassDef: "Wraps a user class." @@ -53,6 +126,7 @@ #self.instantiation_locations = {} self.cls = cls self.subdefs = {} + self.attr_sources = {} # {name: {constant_object: classdef_or_None}} base = object mixeddict = {} sources = {} @@ -93,41 +167,47 @@ value.class_ = cls # remember that this is really a method self.add_source_for_attribute(name, sources.get(name, cls), self) - def attr_mutated(self, homedef, attrdef): # reflow from attr read positions - s_newvalue = attrdef.getvalue() - # check for method demotion - if isinstance(s_newvalue, SomePBC): - attr = attrdef.name - meth = False - for func, classdef in s_newvalue.prebuiltinstances.items(): - if isclassdef(classdef): - meth = True - break - if meth and getattr(homedef.cls, attr, None) is None: - self.bookkeeper.warning("demoting method %s to base class %s" % (attrdef.name, homedef)) - - for position in attrdef.read_locations: - self.bookkeeper.annotator.reflowfromposition(position) - def add_source_for_attribute(self, attr, source, clsdef=None): - homedef = self.locate_attribute(attr) - attrdef = homedef.attrs[attr] - attrdef.sources[source] = clsdef - if attrdef.read_locations: - # we should reflow from all the reader's position, - # but as an optimization we try to see if the attribute - # has really been generalized - s_prev_value = attrdef.s_value - s_next_value = attrdef.getvalue() - if s_prev_value != s_next_value: - self.attr_mutated(homedef, attrdef) - - def locate_attribute(self, attr): + """Adds information about a constant source for an attribute. + """ for cdef in self.getmro(): if attr in cdef.attrs: - return cdef - self.generalize_attr(attr) - return self + # the Attribute() exists already for this class (or a parent) + attrdef = cdef.attrs[attr] + s_prev_value = attrdef.s_value + attrdef.add_constant_source(source, clsdef) + # we should reflow from all the reader's position, + # but as an optimization we try to see if the attribute + # has really been generalized + if attrdef.s_value != s_prev_value: + attrdef.mutated(cdef) # reflow from all read positions + return + else: + # remember the source in self.attr_sources + sources = self.attr_sources.setdefault(attr, {}) + sources[source] = clsdef + # register the source in any Attribute found in subclasses, + # to restore invariant (III) + # NB. add_constant_source() may discover new subdefs but the + # right thing will happen to them because self.attr_sources + # was already updated + if clsdef is not None: + for subdef in self.getallsubdefs(): + if attr in subdef.attrs: + attrdef = subdef.attrs[attr] + s_prev_value = attrdef.s_value + attrdef.add_constant_source(source, clsdef) + if attrdef.s_value != s_prev_value: + attrdef.mutated(subdef) # reflow from all read positions + + def locate_attribute(self, attr): + while True: + for cdef in self.getmro(): + if attr in cdef.attrs: + return cdef + self.generalize_attr(attr) + # the return value will likely be 'self' now, but not always -- see + # test_annrpython.test_attr_moving_from_subclass_to_class_to_parent def find_attribute(self, attr): return self.locate_attribute(attr).attrs[attr] @@ -140,7 +220,7 @@ while other is not None and not issubclass(self.cls, other.cls): other = other.basedef # special case for MI with Exception - if not other: + if other is None and other1 is not None: if issubclass(self.cls, Exception) and issubclass(other1.cls, Exception): return self.bookkeeper.getclassdef(Exception) return other @@ -169,41 +249,59 @@ pending.append(sub) seen[sub] = True -## def getallinstantiations(self): -## locations = {} -## for clsdef in self.getallsubdefs(): -## locations.update(clsdef.instantiation_locations) -## return locations - def _generalize_attr(self, attr, s_value): # first remove the attribute from subclasses -- including us! + # invariant (I) subclass_attrs = [] + constant_sources = {} for subdef in self.getallsubdefs(): if attr in subdef.attrs: subclass_attrs.append(subdef.attrs[attr]) del subdef.attrs[attr] + if attr in subdef.attr_sources: + # accumulate attr_sources for this attribute from all subclasses + d = subdef.attr_sources[attr] + constant_sources.update(d) + d.clear() # invariant (II) + + # accumulate attr_sources for this attribute from all parents, too + # invariant (III) + for superdef in self.getmro(): + if attr in superdef.attr_sources: + for source, classdef in superdef.attr_sources[attr].items(): + if classdef is not None: + constant_sources[source] = classdef - # do the generalization + # create the Attribute and do the generalization asked for newattr = Attribute(attr, self.bookkeeper) if s_value: newattr.s_value = s_value - + + # keep all subattributes' values for subattr in subclass_attrs: newattr.merge(subattr) + + # store this new Attribute, generalizing the previous ones from + # subclasses -- invariant (A) self.attrs[attr] = newattr + # add the values of the pending constant attributes + # completes invariants (II) and (III) + for source, classdef in constant_sources.items(): + newattr.add_constant_source(source, classdef) + # reflow from all read positions - self.attr_mutated(self, newattr) + newattr.mutated(self) def generalize_attr(self, attr, s_value=None): - # if the attribute exists in a superclass, generalize there. + # if the attribute exists in a superclass, generalize there, + # as imposed by invariant (I) for clsdef in self.getmro(): if attr in clsdef.attrs: clsdef._generalize_attr(attr, s_value) break else: self._generalize_attr(attr, s_value) - assert attr in self.attrs def about_attribute(self, name): """This is the interface for the code generators to ask about @@ -238,7 +336,11 @@ continue # not matching d[func] = value if uplookup is not None: - d[upfunc] = uplookup + # when the method is found in a parent class, it get bound to the + # 'self' subclass. This allows the 'func: classdef' entry of the + # PBC dictionary to track more precisely with which 'self' the + # method is called. + d[upfunc] = self elif meth: self.check_missing_attribute_update(name) if d: Modified: pypy/branch/pycompiler/annotation/model.py ============================================================================== --- pypy/branch/pycompiler/annotation/model.py (original) +++ pypy/branch/pycompiler/annotation/model.py Fri Jul 1 18:30:34 2005 @@ -50,7 +50,7 @@ So I trashed 8 hours of work, without a check-in. (Just writing this here to leave *some* trace of work). -Then I tried to make allinstances unique and wrote a lot +Then I tried to make all instances unique and wrote a lot of attribute tracking code here, locked write access outside of __init__, and patched many modules and several hundred lines of code. @@ -204,8 +204,15 @@ def __init__(self, listdef): self.listdef = listdef def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.listdef.same_as(other.listdef)) + if self.__class__ is not other.__class__: + return False + if not self.listdef.same_as(other.listdef): + return False + selfdic = self.__dict__.copy() + otherdic = other.__dict__.copy() + del selfdic['listdef'] + del otherdic['listdef'] + return selfdic == otherdic def can_be_none(self): return True @@ -240,12 +247,26 @@ def __init__(self, dictdef): self.dictdef = dictdef def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.dictdef.same_as(other.dictdef)) + if self.__class__ is not other.__class__: + return False + if not self.dictdef.same_as(other.dictdef): + return False + selfdic = self.__dict__.copy() + otherdic = other.__dict__.copy() + del selfdic['dictdef'] + del otherdic['dictdef'] + return selfdic == otherdic def can_be_none(self): return False + def fmt_const(self, const): + if len(const) < 20: + return repr(const) + else: + return '{...%s...}'%(len(const),) + + class SomeIterator(SomeObject): "Stands for an iterator returning objects from a given container." knowntype = type(iter([])) # arbitrarily chose seqiter as the type @@ -381,6 +402,7 @@ (SomeInteger(nonneg=True, unsigned=True), lltype.Unsigned), (SomeFloat(), lltype.Float), (SomeChar(), lltype.Char), + (SomeUnicodeCodePoint(), lltype.UniChar), ] def annotation_to_lltype(s_val, info=None): @@ -407,7 +429,10 @@ def ll_to_annotation(v): if v is None: - raise ValueError, "cannot retrieve Void low-level type value" + # i think we can only get here in the case of void-returning + # functions + from bookkeeper import getbookkeeper + return getbookkeeper().immutablevalue(None) return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ Modified: pypy/branch/pycompiler/annotation/pairtype.py ============================================================================== --- pypy/branch/pycompiler/annotation/pairtype.py (original) +++ pypy/branch/pycompiler/annotation/pairtype.py Fri Jul 1 18:30:34 2005 @@ -9,6 +9,9 @@ if name == '__extend__': cls = bases[0] # override data into the existing base for key, value in dict.items(): + if key == '__module__': + continue + # XXX do we need to provide something more for pickling? setattr(cls, key, value) return None else: Modified: pypy/branch/pycompiler/annotation/policy.py ============================================================================== --- pypy/branch/pycompiler/annotation/policy.py (original) +++ pypy/branch/pycompiler/annotation/policy.py Fri Jul 1 18:30:34 2005 @@ -1,6 +1,20 @@ # base annotation policy for overrides and specialization from pypy.annotation.specialize import memo, ctr_location, default_specialize as default -from pypy.translator.annrpython import BasicAnnotatorPolicy +from pypy.annotation.specialize import argtype, argvalue +# for some reason, model must be imported first, +# or we create a cycle. +from pypy.annotation import model as annmodel +from pypy.annotation.bookkeeper import getbookkeeper + + +class BasicAnnotatorPolicy: + + def specialize(pol, bookkeeper, spaceop, func, args, mono): + return None, None + + def compute_at_fixpoint(pol, annotator): + annotator.bookkeeper.compute_at_fixpoint() + class AnnotatorPolicy(BasicAnnotatorPolicy): """ @@ -48,3 +62,11 @@ default_specialize = staticmethod(default) specialize__memo = staticmethod(memo) specialize__ctr_location = staticmethod(ctr_location) + specialize__arg0 = staticmethod(argvalue(0)) + specialize__argtype0 = staticmethod(argtype(0)) + specialize__arg1 = staticmethod(argvalue(1)) + specialize__argtype1 = staticmethod(argtype(1)) + + def override__ignore(pol, *args): + bk = getbookkeeper() + return bk.immutablevalue(None) Modified: pypy/branch/pycompiler/annotation/specialize.py ============================================================================== --- pypy/branch/pycompiler/annotation/specialize.py (original) +++ pypy/branch/pycompiler/annotation/specialize.py Fri Jul 1 18:30:34 2005 @@ -126,6 +126,18 @@ # ____________________________________________________________________________ # specializations +class MemoTable: + def __init__(self, bookkeeper, func, s_result, arglist_s): + self.table = {} + self.arglist_s = arglist_s + self.s_result = s_result + for arglist in possible_arguments(arglist_s): + result = func(*arglist) + self.table[arglist] = result + bookkeeper.memo_tables.append(self) + def _freeze_(self): + return True + def memo(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" assert mono, "not-static call to memoized %s" % func @@ -140,28 +152,32 @@ possible_results.append(bookkeeper.immutablevalue(result)) return unionof(*possible_results), args -def possible_arguments(args): +def possible_values_of(s): from pypy.annotation.model import SomeBool, SomePBC - # enumerate all tuples (x1,..xn) of concrete values that are contained - # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either - # a constant or SomePBC. - if not args: - yield () - return - s = args[0] if s.is_constant(): - possible_values = [s.const] + return [s.const] elif isinstance(s, SomePBC): for value in s.prebuiltinstances.values(): assert value is True, ("concrete call with a method bound " "on a non-constant instance") - possible_values = s.prebuiltinstances.keys() + return s.prebuiltinstances.keys() elif isinstance(s, SomeBool): - possible_values = [False, True] + return [False, True] else: - raise AssertionError, "concrete call with a non-constant arg %r" % (s,) - for tuple_tail in possible_arguments(args[1:]): - for value in possible_values: + raise ValueError, "memo call with a non-constant arg %r" % (s,) + +def possible_arguments(args): + # enumerate all tuples (x1,..xn) of concrete values that are contained + # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either + # a constant or SomePBC. + return cartesian_product([possible_values_of(s) for s in args]) + +def cartesian_product(lstlst): + if not lstlst: + yield () + return + for tuple_tail in cartesian_product(lstlst[1:]): + for value in lstlst[0]: yield (value,) + tuple_tail #def argtypes(bookkeeper, spaceop, func, args, mono): Modified: pypy/branch/pycompiler/annotation/unaryop.py ============================================================================== --- pypy/branch/pycompiler/annotation/unaryop.py (original) +++ pypy/branch/pycompiler/annotation/unaryop.py Fri Jul 1 18:30:34 2005 @@ -83,9 +83,20 @@ return SomeInteger() def str(obj): + getbookkeeper().count('str', obj) return SomeString() - repr = hex = oct = str + def repr(obj): + getbookkeeper().count('repr', obj) + return SomeString() + + def hex(obj): + getbookkeeper().count('hex', obj) + return SomeString() + + def oct(obj): + getbookkeeper().count('oct', obj) + return SomeString() def id(obj): # xxx return SomeInteger() @@ -197,6 +208,7 @@ return immutablevalue(len(tup.items)) def iter(tup): + getbookkeeper().count("tuple_iter", tup) return SomeIterator(tup) def getanyitem(tup): @@ -211,8 +223,11 @@ def method_extend(lst, s_iterable): lst.listdef.resize() - s_iter = s_iterable.iter() - pair(lst, SomeInteger()).setitem(s_iter.next()) + if isinstance(s_iterable, SomeList): # unify the two lists + lst.listdef.union(s_iterable.listdef) + else: + s_iter = s_iterable.iter() + pair(lst, SomeInteger()).setitem(s_iter.next()) def method_reverse(lst): lst.listdef.mutate() @@ -220,20 +235,19 @@ def method_insert(lst, s_index, s_value): lst.listdef.resize() pair(lst, SomeInteger()).setitem(s_value) - + def method_pop(lst, s_index=None): lst.listdef.resize() return lst.listdef.read_item() def method_index(lst, el): + getbookkeeper().count("list_index") return SomeInteger(nonneg=True) def len(lst): s_item = lst.listdef.read_item() if isinstance(s_item, SomeImpossibleValue): - r = SomeInteger(nonneg=True) - r.const = 0 - return r + return immutablevalue(0) return SomeObject.len(lst) def iter(lst): @@ -247,12 +261,10 @@ def len(dct): s_key = dct.dictdef.read_key() s_value = dct.dictdef.read_value() - if isinstance(s_key, SomeImpossibleValue) and isinstance(s_value, SomeImpossibleValue): - r = SomeInteger(nonneg=True) - r.const = 0 - return r + if isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue): + return immutablevalue(0) return SomeObject.len(dct) - + def iter(dct): return SomeIterator(dct) @@ -260,14 +272,15 @@ return dct.dictdef.read_key() def method_get(dct, key, dfl): - return unionof(dct.dictdef.read_value(), dfl) + dct.dictdef.generalize_key(key) + dct.dictdef.generalize_value(dfl) + return dct.dictdef.read_value() def method_copy(dct): return dct def method_update(dct1, dct2): - dct1.dictdef.generalize_key(dct2.dictdef.read_key()) - dct1.dictdef.generalize_value(dct2.dictdef.read_value()) + dct1.dictdef.union(dct2.dictdef) def method_keys(dct): return getbookkeeper().newlist(dct.dictdef.read_key()) @@ -278,10 +291,10 @@ def method_items(dct): return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(), dct.dictdef.read_value()))) - -class __extend__(SomeString): +class __extend__(SomeString): + def method_startswith(str, frag): return SomeBool() @@ -289,6 +302,10 @@ return SomeBool() def method_join(str, s_list): + getbookkeeper().count("str_join", str) + s_item = s_list.listdef.read_item() + if s_item == SomeImpossibleValue(): + return immutablevalue("") return SomeString() def method_find(str, frag): @@ -316,14 +333,21 @@ return SomeInteger(nonneg=True) def method_split(str, patt): # XXX + getbookkeeper().count("str_split", str, patt) return getbookkeeper().newlist(SomeString()) + def method_replace(str, s1, s2): + return SomeString() + class __extend__(SomeChar): def len(chr): return immutablevalue(1) + def method_isspace(chr): + return SomeBool() + class __extend__(SomeUnicodeCodePoint): def ord(uchr): @@ -378,6 +402,7 @@ if bltn.s_self is not None: return bltn.analyser(bltn.s_self, *args) else: + getbookkeeper().count(bltn.methodname.replace('.', '_'), *args) return bltn.analyser(*args) def call(bltn, args, implicit_init=False): @@ -387,14 +412,14 @@ return bltn.analyser(bltn.s_self, *args) else: return bltn.analyser(*args) - + class __extend__(SomePBC): def getattr(pbc, s_attr): bookkeeper = getbookkeeper() return bookkeeper.pbc_getattr(pbc, s_attr) - + def setattr(pbc, s_attr, s_value): getbookkeeper().warning("setattr not wanted on %r" % (pbc,)) @@ -405,21 +430,21 @@ #bookkeeper = getbookkeeper() #results = [] #for func, classdef in pbc.prebuiltinstances.items(): - # if isclassdef(classdef): + # if isclassdef(classdef): # s_self = SomeInstance(classdef) # args1 = args.prepend(s_self) # else: # args1 = args # results.append(bookkeeper.pycall(func, args1)) - #return unionof(*results) + #return unionof(*results) - def bindcallables(pbc, classdef): - """ turn the callables in the given SomeCallable 'cal' + def bindcallables(pbc, classdef): + """ turn the callables in the given SomeCallable 'cal' into bound versions. """ d = {} for func, value in pbc.prebuiltinstances.items(): - if isinstance(func, FunctionType): + if isinstance(func, FunctionType): if isclassdef(value): getbookkeeper().warning("rebinding an already bound " "method %r with %r" % (func, value)) @@ -427,20 +452,24 @@ elif isinstance(func, staticmethod): d[func.__get__(43)] = value else: - d[func] = value + d[func] = value return SomePBC(d) def is_true(pbc): outcome = None for c in pbc.prebuiltinstances: + if c is not None and not bool(c): + getbookkeeper().warning("PBC %r has truth value False" % (c,)) + getbookkeeper().count("pbc_is_true", pbc) + for c in pbc.prebuiltinstances: if outcome is None: outcome = bool(c) else: if outcome != bool(c): return SomeBool() return immutablevalue(outcome) - - + + # annotation of low-level types from pypy.annotation.model import SomePtr, ll_to_annotation, annotation_to_lltype class __extend__(SomePtr): @@ -451,7 +480,8 @@ return ll_to_annotation(v) def len(p): - return ll_to_annotation(len(p.ll_ptrtype._example())) + len(p.ll_ptrtype._example()) # just doing checking + return SomeObject.len(p) def setattr(p, s_attr, s_value): # just doing checking assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype Modified: pypy/branch/pycompiler/bin/translator.py ============================================================================== --- pypy/branch/pycompiler/bin/translator.py (original) +++ pypy/branch/pycompiler/bin/translator.py Fri Jul 1 18:30:34 2005 @@ -211,8 +211,12 @@ def setup_readline(): import readline - import rlcompleter - readline.parse_and_bind("tab: complete") + try: + import rlcompleter2 + rlcompleter2.setup() + except ImportError: + import rlcompleter + readline.parse_and_bind("tab: complete") import os histfile = os.path.join(os.environ["HOME"], ".pypytrhist") try: Modified: pypy/branch/pycompiler/documentation/architecture.txt ============================================================================== --- pypy/branch/pycompiler/documentation/architecture.txt (original) +++ pypy/branch/pycompiler/documentation/architecture.txt Fri Jul 1 18:30:34 2005 @@ -105,7 +105,7 @@ Please note that we are using the term *interpreter* most often in reference to the *plain interpreter* which just knows enough to read, dispatch and implement *bytecodes* thus shuffling objects around on the -stack and between namespaces. The (plain) interpreter is completly +stack and between namespaces. The (plain) interpreter is completely ignorant of how to access, modify or construct objects and their structure and thus delegates such operations to a so called `Object Space`_. @@ -351,7 +351,7 @@ order for our translation and type inference mechanisms to work effectively, we need to restrict the dynamism of our interpreter-level Python code at some point. However, in the start-up phase, we are -completly free to use all kind of nice python constructs, including +completely free to use all kind of nice python constructs, including metaclasses and execution of dynamically constructed strings. However, when the initialization phase (mainly, the function ``objspace.initialize()``) finishes, all code objects involved need to @@ -367,7 +367,7 @@ of values, and an exitswitch to one, two or multiple links which connect each basic block to other basic blocks. -The flow graphs are fed as input into the Annotator. The Annotator, +The flow graphs are fed as input into the Annotator. The Annotator, given entry point types, infers the types of values that flow through the program variables. Here, the definition of `RPython`_ comes again into play: RPython code is restricted in such a way that the @@ -383,7 +383,7 @@ definition will probably continue to shift marginally as we improve it. The actual low-level code (and, in fact, also other high-level code) is -emitted by "visiting" the type-annotated flow graph. Currently, we have +emitted by "visiting" the type-annotated flow graph. Currently we have a C-producing backend, and an LLVM-producing backend. The former also accepts non-annotated or partially-annotated graphs, which allow us to test it on a larger class of programs than what the Annotator can (or Modified: pypy/branch/pycompiler/documentation/coding-guide.txt ============================================================================== --- pypy/branch/pycompiler/documentation/coding-guide.txt (original) +++ pypy/branch/pycompiler/documentation/coding-guide.txt Fri Jul 1 18:30:34 2005 @@ -1,24 +1,25 @@ ===================================== -PyPy - Coding Guide +PyPy - Coding Guide ===================================== .. contents:: .. sectnum:: -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. +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. -.. _`RPython`: +.. _`RPython`: Restricted Python ================== -We are writing a Python interpreter in Python, using Python's well known ability -to step behind the algorithmic problems as language. At first glance, one might -think this achieves nothing but a better understanding how the interpreter works. -This alone would make it worth doing, but we have much larger goals. +We are writing a Python interpreter in Python, using Python's well known +ability to step behind the algorithmic problems as language. At first glance, +one might think this achieves nothing but a better understanding how the +interpreter works. This alone would make it worth doing, but we have much +larger goals. CPython vs. PyPy @@ -29,36 +30,36 @@ also aim at writing a more flexible interpreter at C level but but we want to use Python to give an alternative description of the interpreter. -The clear advantage is that such a description is shorter and simpler to -read, and many implementation details vanish. The drawback of this approach is +The clear advantage is that such a description is shorter and simpler to +read, and many implementation details vanish. The drawback of this approach is that this interpreter will be unbearably slow as long as it is run on top of CPython. To get to a useful interpreter again, we need to translate our high-level description of Python to a lower level one. One rather straight-forward way is to do a whole program analysis of the PyPy -interpreter and create a C source, again. There are many other ways, -but let's stick with this somewhat canonical approach. +interpreter and create a C source, again. There are many other ways, +but let's stick with this somewhat canonical approach. -our runtime interpreter is "restricted python" +our runtime interpreter is "restricted python" ---------------------------------------------- In order to make a C code generator feasible we restrict ourselves to a subset of the Python language, and we adhere to some rules which make -translation to lower level languages more obvious. +translation to lower level languages more obvious. Unlike source-to-source translations (like e.g. Starkiller_) we start translation from live python code objects which constitute our Python interpreter. When doing its work of interpreting bytecode our Python -implementation must behave in a static way often referenced as -"RPythonic". +implementation must behave in a static way often referenced as +"RPythonic". .. _Starkiller: http://www.python.org/pycon/dc2004/papers/1/paper.pdf However, when the PyPy interpreter is started as a Python program, it can use all of the Python language until it reaches interpretation runtime. That is, during initialization our program is free to use the -full dynamism of Python, including dynamic code generation. +full dynamism of Python, including dynamic code generation. An example can be found in the current implementation which is quite elegant: For the definition of all the opcodes of the Python @@ -74,19 +75,19 @@ during translation, a whole program analysis ("type inference") is performed, which makes use of the restrictions defined in RPython. This enables the code generator to emit efficient machine level replacements -for pure integer objects, for instance. +for pure integer objects, for instance. -.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py +.. _`pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py RPython Definition, not ----------------------- -The list and exact details of the "RPython" restrictions are a somewhat +The list and exact details of the "RPython" restrictions are a somewhat evolving topic. In particular, we have no formal language definition -as we find it more practical to discuss and evolve the set of +as we find it more practical to discuss and evolve the set of restrictions while working on the whole program analysis. If you have any questions about the restrictions below then please feel -free to mail us at pypy-dev at codespeak net. +free to mail us at pypy-dev at codespeak net. .. _`wrapped object`: coding-guide.html#wrapping-rules @@ -94,7 +95,7 @@ ------------------------- **variables** - + variables should contain values of at most one type as described in `Object restrictions`_ at each control flow point, that means for example that joining control paths using the same variable to @@ -103,16 +104,16 @@ and class instances is allowed. **constants** - + all module globals are considered constants. **control structures** - + all allowed **range** - - does not create an array. It is only allowed in for loops. The step argument + + does not create an array. It is only allowed in for loops. The step argument must be a constant. **definitions** @@ -135,55 +136,55 @@ We are using **integer, float, string, boolean** - + avoid string methods and complex operations like slicing with a step **tuples** - - no variable-length tuples; use them to store or return pairs or n-tuples of + + no variable-length tuples; use them to store or return pairs or n-tuples of values. Each combination of types for elements and length constitute a separate and not mixable type. **lists** - - lists are used as an allocated array; list.append() does naive resizing, so as + + lists are used as an allocated array; list.append() does naive resizing, so as far as possible use list comprehensions (see below). list.extend() or the += operator are allowed and efficient. Unless there is really a use case for it, repetition is limited to initialization purposes: '[single_value] * length'. **dicts** - + dicts with string keys only (preferably the kind of strings that are usually interned in CPython, i.e. short strings that look like identifiers). The implementation could safely decide that all dict keys should be interned. **list comprehensions** - - may be used to create allocated, initialized array. the array size must be + + may be used to create allocated, initialized array. the array size must be computable in advance, which implies that we don't allow an if clause. **functions** -+ statically called functions may use defaults and a variable number of - arguments (which may be passed as a list instead of a tuple, so write code that - does not depend on it being a tuple). - -+ dynamic dispatch enforces use of very simple signatures, equal for all - functions to be called in that context. At the moment, this occurs in the opcode - dispatch, only. ++ statically called functions may use defaults and a variable number of + arguments (which may be passed as a list instead of a tuple, so write code + that does not depend on it being a tuple). + ++ dynamic dispatch enforces use of very simple signatures, equal for all + functions to be called in that context. At the moment, this occurs in the + opcode dispatch, only. **builtin functions** - A few builtin functions will be used, while this set is not defined + A few builtin functions will be used, while this set is not defined completely, yet. Some builtin functions are special forms: **len** -+ may be used with basic types that have a length. But len is a special form ++ may be used with basic types that have a length. But len is a special form that is recognized by the compiler. -+ If a certain structure is never touched by len, the compiler might save the ++ If a certain structure is never touched by len, the compiler might save the length field from the underlying structure. ``int, float, ord, chr``... are available as simple conversion functions. @@ -198,8 +199,8 @@ **objects** - wrapped objects are borrowed from the object space. Just like in CPython, code - that needs e.g. a dictionary can use a wrapped dict and the object space + wrapped objects are borrowed from the object space. Just like in CPython, + code that needs e.g. a dictionary can use a wrapped dict and the object space operations on it. This layout makes the number of types to take care about quite limited. @@ -208,13 +209,13 @@ Integer Types ------------------------- -While implementing the integer type, we stumbled over the problem, that +While implementing the integer type, we stumbled over the problem, that integers are quite in flux in CPython right now. Starting on Python 2.2, -integers mutate into longs on overflow. However, shifting to the left truncates -up to 2.3 but extends to longs as well in 2.4. By contrast, we need a way to -perform wrap-around machine-sized arithmetic by default, while still being -able to check for overflow when we need it explicitly. Moreover, we need a -consistent behavior before and after translation. +integers mutate into longs on overflow. However, shifting to the left +truncates up to 2.3 but extends to longs as well in 2.4. By contrast, we need +a way to perform wrap-around machine-sized arithmetic by default, while still +being able to check for overflow when we need it explicitly. Moreover, we need +a consistent behavior before and after translation. We use normal integers for signed arithmetic. It means that before translation we get longs in case of overflow, and after translation we get a @@ -226,7 +227,7 @@ This special function should only be used with a single arithmetic operation as its argument, e.g. ``z = ovfcheck(x+y)``. Its intended meaning is to perform the given operation in overflow-checking mode. - + At run-time, in Python, the ovfcheck() function itself checks the result and raises OverflowError if it is a ``long``. But the code generators use ovfcheck() as a hint: they replace the whole ``ovfcheck(x+y)`` expression @@ -245,7 +246,7 @@ This function is used for wrap-around arithmetic. It returns the lower bits of its argument, masking away anything that doesn't fit in a C "signed long int". - Its purpose is, in Python, to convert from a Python ``long`` that resulted from a + Its purpose is, in Python, to convert from a Python ``long`` that resulted from a previous operation back to a Python ``int``. The code generators ignore intmask() entirely, as they are doing wrap-around signed arithmetic all the time by default anyway. (We have no equivalent of the "int" versus "long int" @@ -311,35 +312,46 @@ Exceptions explicitly raised or re-raised will always be generated. -PyPy is debuggable on top of CPython ------------------------------------- +PyPy is debuggable on top of CPython +------------------------------------ PyPy has the advantage that it is runnable on standard CPython. That means, we can run all of PyPy with all exception handling enabled, so we might catch cases where we failed to adhere to our implicit assertions. -.. _`wrapping rules`: +.. _`wrapping rules`: Wrapping rules ============== -PyPy is made of Python source code at two levels: there is on the one hand *application-level code* that looks like normal Python code, and that implements some functionalities as one would expect from Python code (e.g. one can give a pure Python implementation of some built-in functions like ``zip()``). There is also *interpreter-level code* for the functionalities that must more directly manipulate interpreter data and objects (e.g. the main loop of the interpreter, and the various object spaces). - -Application-level code doesn't see object spaces explicitly: it runs using an object space to support the objects it manipulates, but this is implicit. There is no need for particular conventions for application-level code. The sequel is only about interpreter-level code. (Ideally, no application-level variable should be called ``space`` or ``w_xxx`` to avoid confusion.) +PyPy is made of Python source code at two levels: there is on the one hand +*application-level code* that looks like normal Python code, and that +implements some functionalities as one would expect from Python code (e.g. one +can give a pure Python implementation of some built-in functions like +``zip()``). There is also *interpreter-level code* for the functionalities +that must more directly manipulate interpreter data and objects (e.g. the main +loop of the interpreter, and the various object spaces). + +Application-level code doesn't see object spaces explicitly: it runs using an +object space to support the objects it manipulates, but this is implicit. +There is no need for particular conventions for application-level code. The +sequel is only about interpreter-level code. (Ideally, no application-level +variable should be called ``space`` or ``w_xxx`` to avoid confusion.) Naming conventions ------------------ * ``space``: the object space is only visible at - interpreter-level code, where it is by convention passed around by the name ``space``. + interpreter-level code, where it is by convention passed around by the name + ``space``. * ``w_xxx``: any object seen by application-level code is an object explicitly managed by the object space. From the interpreter-level point of view, this is called a *wrapped* object. The ``w_`` prefix is used for any type of - application-level object. + application-level object. * ``xxx_w``: an interpreter-level container for wrapped objects, for example a list or a dict containing wrapped @@ -375,7 +387,8 @@ Building ``w_xxx`` objects -------------------------- -From the core interpreter, wrapped objects are usually built as the result of an object space operation. The ways to directly create a wrapped object are: +From the core interpreter, wrapped objects are usually built as the result of +an object space operation. The ways to directly create a wrapped object are: * ``space.wrap(x)``: returns a wrapped object containing the value ``x``. Only works if ``x`` is either a simple value @@ -510,32 +523,32 @@ application-level classes. -.. _`modules`: +.. _`modules`: -Modules in PyPy -=============== +Modules in PyPy +=============== -Modules visible from application programs are imported from +Modules visible from application programs are imported from interpreter or application level files. PyPy reuses almost all python modules of CPython's standard library, currently from version 2.3.4. We sometimes need to `modify modules`_ and - more often - regression tests -because they rely on implementation details of CPython. +because they rely on implementation details of CPython. If we don't just modify an original CPython module but need to rewrite it from scratch we put it into `pypy/lib/`_ as a pure application level -module. +module. When we need access to interpreter-level objects we put the module into `pypy/module`_. Such modules use a `mixed module mechanism`_ which makes it convenient to use both interpreter- and applicationlevel parts for the implementation. Note that there is no extra facility for -pure-interpreter level modules because we haven't needed it so far. +pure-interpreter level modules because we haven't needed it so far. -Determining the location of a module implementation ---------------------------------------------------- +Determining the location of a module implementation +--------------------------------------------------- -You can interactively find out where a module comes from, -here are examples for the possible locations:: +You can interactively find out where a module comes from, +here are examples for the possible locations:: >>>> import sys >>>> sys.__file__ @@ -556,21 +569,21 @@ '/home/hpk/pypy-dist/lib-python/2.3.4/os.py' >>>> -Module directories / Import order +Module directories / Import order --------------------------------- -Here is the order in which PyPy looks up Python modules: +Here is the order in which PyPy looks up Python modules: + +*pypy/modules* -*pypy/modules* + mixed interpreter/app-level builtin modules, such as + the ``sys`` and ``__builtin__`` module. - mixed interpreter/app-level builtin modules, such as - the ``sys`` and ``__builtin__`` module. +*contents of PYTHONPATH* -*contents of PYTHONPATH* - - lookup application level modules in each of the ``:`` separated - list of directories, specified in the ``PYTHONPATH`` environment - variable. + lookup application level modules in each of the ``:`` separated + list of directories, specified in the ``PYTHONPATH`` environment + variable. *pypy/lib/* @@ -582,93 +595,94 @@ *lib-python/2.3.4/* - The unmodified CPython library. **Never ever checkin anything here**. + The unmodified CPython library. **Never ever checkin anything here**. -.. _`modify modules`: +.. _`modify modules`: -Modifying a CPython library module or regression test -------------------------------------------------------- +Modifying a CPython library module or regression test +------------------------------------------------------- -Although PyPy is very compatible with CPython we sometimes need -to change modules contained in our copy of the standard library, -often due to the fact that PyPy works with all new-style classes -by default and CPython has a number of places where it relies -on some classes being old-style. +Although PyPy is very compatible with CPython we sometimes need +to change modules contained in our copy of the standard library, +often due to the fact that PyPy works with all new-style classes +by default and CPython has a number of places where it relies +on some classes being old-style. If you want to change a module or test contained in ``lib-python/2.3.4`` -then make sure that you copy the file to our ``lib-python/modified-2.3.4`` -directory first. In subversion commandline terms this reads:: +then make sure that you copy the file to our ``lib-python/modified-2.3.4`` +directory first. In subversion commandline terms this reads:: - svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/ + svn cp lib-python/2.3.4/somemodule.py lib-python/modified-2.3.4/ -and subsequently you edit and commit ``lib-python/modified-2.3.4/somemodule.py``. -This copying operation is important because it keeps the original -CPython tree clean and makes it obvious what we had to change. +and subsequently you edit and commit +``lib-python/modified-2.3.4/somemodule.py``. This copying operation is +important because it keeps the original CPython tree clean and makes it +obvious what we had to change. -.. _`mixed module mechanism`: -.. _`mixed modules`: +.. _`mixed module mechanism`: +.. _`mixed modules`: -Implementing a mixed interpreter/application level Module ---------------------------------------------------------- +Implementing a mixed interpreter/application level Module +--------------------------------------------------------- -If a module needs to access PyPy's interpreter level -then it is implemented as a mixed module. +If a module needs to access PyPy's interpreter level +then it is implemented as a mixed module. Mixed modules are directories in `pypy/module`_ with an `__init__.py` file containing specifications where each name in a module comes from. Only specified names will be exported to a Mixed Module's applevel -namespace. +namespace. application level definitions ............................. -Application level specifications are found in the `appleveldefs` -dictionary found in ``__init__.py`` files of directories in ``pypy/module``. -For example, in `pypy/module/__builtin__/__init__.py`_ you find the following -entry specifying where ``__builtin__.locals`` comes from:: +Application level specifications are found in the `appleveldefs` +dictionary found in ``__init__.py`` files of directories in ``pypy/module``. +For example, in `pypy/module/__builtin__/__init__.py`_ you find the following +entry specifying where ``__builtin__.locals`` comes from:: ... 'locals' : 'app_inspect.locals', ... -The ``app_`` prefix indicates that the submodule ``app_inspect`` is -interpreted at application level and the wrapped function value for ``locals`` -will be extracted accordingly. +The ``app_`` prefix indicates that the submodule ``app_inspect`` is +interpreted at application level and the wrapped function value for ``locals`` +will be extracted accordingly. interpreter level definitions ............................. -Interpreter level specifications are found in the ``interpleveldefs`` -dictionary found in ``__init__.py`` files of directories in ``pypy/module``. -For example, in `pypy/module/__builtin__/__init__.py`_ the following -entry specifies where ``__builtin__.len`` comes from:: +Interpreter level specifications are found in the ``interpleveldefs`` +dictionary found in ``__init__.py`` files of directories in ``pypy/module``. +For example, in `pypy/module/__builtin__/__init__.py`_ the following +entry specifies where ``__builtin__.len`` comes from:: ... 'len' : 'operation.len', ... -The ``operation`` submodule lives at interpreter level and ``len`` +The ``operation`` submodule lives at interpreter level and ``len`` is expected to be exposable to application level. Here is -the definition for ``operation.len()``:: +the definition for ``operation.len()``:: def len(space, w_obj): "len(object) -> integer\n\nReturn the number of items of a sequence or mapping." return space.len(w_obj) Exposed interpreter level functions usually take a ``space`` argument -and some wrapped values (see `wrapping rules`_) . +and some wrapped values (see `wrapping rules`_) . -You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: -namely an expression in parentheses to specify an interpreter level -expression directly (instead of pulling it indirectly from a file):: +You can also use a convenient shortcut in ``interpleveldefs`` dictionaries: +namely an expression in parentheses to specify an interpreter level +expression directly (instead of pulling it indirectly from a file):: ... 'None' : '(space.w_None)', 'False' : '(space.w_False)', - ... + ... The interpreter level expression has a ``space`` binding when -it is executed. +it is executed. Testing modules in ``pypy/lib`` -------------------------------- @@ -677,50 +691,50 @@ ("py.test" or "python ../../test_all.py") to run tests against the pypy/lib hierarchy. Note, that tests in `pypy/lib/test2`_ are allowed and encouraged to let their tests run at interpreter level although -`pypy/lib/`_ modules eventually live at PyPy's application level. -This allows us to quickly test our python-coded reimplementations -against CPython. +`pypy/lib/`_ modules eventually live at PyPy's application level. +This allows us to quickly test our python-coded reimplementations +against CPython. .. _`pypy/lib/test2`: http://codespeak.net/svn/pypy/dist/pypy/lib/test2 Testing modules in ``pypy/module`` ---------------------------------- -Simply change to ``pypy/module`` or to a subdirectory and `run the -tests as usual`_. +Simply change to ``pypy/module`` or to a subdirectory and `run the +tests as usual`_. Testing modules in ``lib-python`` ----------------------------------- -In order to let CPython's regression tests run against PyPy -you can switch to the `lib-python/`_ directory and run -the testing tool in order to start compliance tests. -(XXX check windows compatibility for producing test reports). +In order to let CPython's regression tests run against PyPy +you can switch to the `lib-python/`_ directory and run +the testing tool in order to start compliance tests. +(XXX check windows compatibility for producing test reports). -Naming conventions and directory layout +Naming conventions and directory layout =========================================== -Directory and File Naming +Directory and File Naming ------------------------- - directories/modules/namespaces are always **lowercase** - never use plural names in directory and file names -- ``__init__.py`` is usually empty except for - ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. +- ``__init__.py`` is usually empty except for + ``pypy/objspace/*`` and ``pypy/module/*/__init__.py``. - don't use more than 4 directory nesting levels -- keep filenames concise and completion-friendly. +- keep filenames concise and completion-friendly. Naming of python objects ------------------------ - class names are **CamelCase** -- functions/methods are lowercase and ``_`` separated +- functions/methods are lowercase and ``_`` separated - objectspace classes are spelled ``XyzObjSpace``. e.g. @@ -736,25 +750,25 @@ ----------------------------------------------------- - write good log messages because several people - are reading the diffs. + are reading the diffs. - if you add (text/py) files to the repository then please run - pypy/tool/fixeol in that directory. This will make sure - that the property 'svn:eol-style' is set to native which + pypy/tool/fixeol in that directory. This will make sure + that the property 'svn:eol-style' is set to native which allows checkin/checkout in native line-ending format. - branching (aka "svn copy") of source code should usually happen at ``svn/pypy/dist`` level in order to have a full self-contained pypy checkout for each branch. For branching - a ``try1`` branch you would for example do:: + a ``try1`` branch you would for example do:: svn cp http://codespeak.net/svn/pypy/dist \ - http://codespeak.net/svn/pypy/branch/try1 + http://codespeak.net/svn/pypy/branch/try1 - This allows to checkout the ``try1`` branch and receive a - self-contained working-copy for the branch. Note that - branching/copying is a cheap operation with subversion, as it - takes constant time irrespective of the size of the tree. + This allows to checkout the ``try1`` branch and receive a + self-contained working-copy for the branch. Note that + branching/copying is a cheap operation with subversion, as it + takes constant time irrespective of the size of the tree. - To learn more about how to use subversion read `this document`_. @@ -762,41 +776,41 @@ -.. _`using development tracker`: +.. _`using development tracker`: Using the development bug/feature tracker ========================================= -We have a `development tracker`_, based on Richard Jones' -`roundup`_ application. You can file bugs, -feature requests or see what's going on -for the next milestone, both from an E-Mail and from a -web interface. +We have a `development tracker`_, based on Richard Jones' +`roundup`_ application. You can file bugs, +feature requests or see what's going on +for the next milestone, both from an E-Mail and from a +web interface. use your codespeak login or register ------------------------------------- +------------------------------------ If you already committed to the PyPy source code, chances are that you can simply use your codespeak login that -you use for subversion or for shell access. +you use for subversion or for shell access. If you are not a commiter then you can still `register with -the tracker`_ easily. +the tracker`_ easily. modifying Issues from svn commit messages ------------------------------------------ +----------------------------------------- -If you are committing something related to -an issue in the development tracker you -can correlate your login message to a tracker -item by following these rules: +If you are committing something related to +an issue in the development tracker you +can correlate your login message to a tracker +item by following these rules: -- put the content of ``issueN STATUS`` on a single - new line +- put the content of ``issueN STATUS`` on a single + new line -- `N` must be an existing issue number from the `development tracker`_. +- `N` must be an existing issue number from the `development tracker`_. -- STATUS is one of:: +- STATUS is one of:: unread chatting @@ -811,10 +825,10 @@ .. _`roundup`: http://roundup.sf.net -.. _`testing in PyPy`: +.. _`testing in PyPy`: Testing in PyPy -=============== +=============== Our tests are based on the new `py.test`_ tool which lets you write unittests without boilerplate. All tests of modules @@ -829,55 +843,55 @@ Both types of tests need an `objectspace`_ they can run with (the interpreter dispatches operations on objects to an objectspace). If you run a test you -can usually give the '-o' switch to select an object space. E.g. '-o thunk' -will select the thunk object space. The default is the `Standard Object Space`_ -which aims to implement unmodified Python semantics. +can usually give the '-o' switch to select an object space. E.g. '-o thunk' +will select the thunk object space. The default is the `Standard Object Space`_ +which aims to implement unmodified Python semantics. .. _`standard object space`: objspace.html#standard-object-space -.. _`objectspace`: architecture.html#objectspace -.. _`py.test`: http://codespeak.net/py/current/doc/test.html +.. _`objectspace`: architecture.html#objectspace +.. _`py.test`: http://codespeak.net/py/current/doc/test.html + +Interpreter level tests +----------------------- -Interpreter level tests ------------------------ +You can write test functions and methods like this:: -You can write test functions and methods like this:: + def test_something(space): + # use space ... - def test_something(space): - # use space ... - - class TestSomething: - def test_some(self): - # use 'self.space' here + class TestSomething: + def test_some(self): + # use 'self.space' here Note that the prefix `test` for test functions and `Test` for test classes is mandatory. In both cases you can import Python modules at module global level and use plain 'assert' statements thanks to the -usage of the `py.test`_ tool. +usage of the `py.test`_ tool. -Application Level tests ------------------------ +Application Level tests +----------------------- For testing the conformance and well-behavedness of PyPy it -is often sufficient to write "normal" application-level +is often sufficient to write "normal" application-level Python code that doesn't need to be aware of any particular coding style or restrictions. If we have a choice we often use application level tests which usually look like this:: def app_test_something(): - # application level test code + # application level test code - class AppTestSomething: - def test_this(self): - # application level test code + class AppTestSomething: + def test_this(self): + # application level test code These application level test functions will run on top -of PyPy, i.e. they have no access to interpreter details. +of PyPy, i.e. they have no access to interpreter details. You cannot use imported modules from global level because they are imported at interpreter-level while you test code runs at application level. If you need to use modules -you have to import them within the test function. +you have to import them within the test function. -.. _`run the tests as usual`: +.. _`run the tests as usual`: Command line tool test_all -------------------------- @@ -886,65 +900,65 @@ python test_all.py -which is a synonym for the general `py.test`_ utility -located in the ``pypy`` directory. For switches to -modify test execution pass the ``-h`` option. +which is a synonym for the general `py.test`_ utility +located in the ``pypy`` directory. For switches to +modify test execution pass the ``-h`` option. Test conventions ---------------- - adding features requires adding appropriate tests. (It often even makes sense to first write the tests so that you are sure that they - actually can fail.) + actually can fail.) -- All over the pypy source code there are test/ directories +- All over the pypy source code there are test/ directories which contain unittests. Such scripts can usually be executed - directly or are collectively run by pypy/test_all.py + directly or are collectively run by pypy/test_all.py - each test directory needs a copy of pypy/tool/autopath.py which upon import will make sure that sys.path contains the directory - where 'pypy' is in. + where 'pypy' is in. -.. _`change documentation and website`: +.. _`change documentation and website`: -Changing documentation and website -================================== +Changing documentation and website +================================== -documentation/website files in your local checkout +documentation/website files in your local checkout --------------------------------------------------- -Most of the PyPy's documentation and website is kept in -`pypy/documentation` and `pypy/documentation/website` respectively. -You can simply edit or add '.txt' files which contain ReST-markuped +Most of the PyPy's documentation and website is kept in +`pypy/documentation` and `pypy/documentation/website` respectively. +You can simply edit or add '.txt' files which contain ReST-markuped files. Here is a `ReST quickstart`_ but you can also just look -at the existing documentation and see how things work. +at the existing documentation and see how things work. .. _`ReST quickstart`: http://docutils.sourceforge.net/docs/rst/quickref.html Automatically test documentation/website changes ------------------------------------------------ -.. _`docutils home page`: -.. _`docutils`: http://docutils.sourceforge.net/ +.. _`docutils home page`: +.. _`docutils`: http://docutils.sourceforge.net/ -We automatically check referential integrity and ReST-conformance. In order to -run the tests you need docutils_ installed. Then go to the local checkout -of the documentation directory and run the tests:: +We automatically check referential integrity and ReST-conformance. In order to +run the tests you need docutils_ installed. Then go to the local checkout +of the documentation directory and run the tests:: - cd .../pypy/documentation - python ../test_all.py + cd .../pypy/documentation + python ../test_all.py -If you see no failures chances are high that your modifications at least +If you see no failures chances are high that your modifications at least don't produce ReST-errors or wrong local references. A side effect of running -the tests is that you have `.html` files in the documentation directory -which you can point your browser to! +the tests is that you have `.html` files in the documentation directory +which you can point your browser to! -Additionally, if you also want to check for remote references inside -the documentation issue:: +Additionally, if you also want to check for remote references inside +the documentation issue:: - python ../test_all.py --checkremote + python ../test_all.py --checkremote -which will check that remote URLs are reachable. +which will check that remote URLs are reachable. .. include:: _ref.txt Modified: pypy/branch/pycompiler/documentation/contributor.txt ============================================================================== --- pypy/branch/pycompiler/documentation/contributor.txt (original) +++ pypy/branch/pycompiler/documentation/contributor.txt Fri Jul 1 18:30:34 2005 @@ -1,10 +1,10 @@ -Contributors to PyPy -==================== +Contributors to PyPy +==================== -Here is a list of developers who have committed to the PyPy source -code base, ordered by number of commits (which is certainly not a very -appropriate measure but it's something):: +Here is a list of developers who have committed to the PyPy source +code base, ordered by number of commits (which is certainly not a very +appropriate measure but it's something):: Armin Rigo Samuele Pedroni Modified: pypy/branch/pycompiler/documentation/faq.txt ============================================================================== --- pypy/branch/pycompiler/documentation/faq.txt (original) +++ pypy/branch/pycompiler/documentation/faq.txt Fri Jul 1 18:30:34 2005 @@ -1,13 +1,12 @@ -Frequently Asked Questions -========================== +Frequently Asked Questions +========================== -How fast is PyPy? +How fast is PyPy? As of June 2005, PyPy still runs on top of CPython and thus - is slower by a factor of 2000 compared to CPython. We don't + is slower by a factor of 2000 compared to CPython. We don't know yet how fast it will be once we complete our translation - efforts, aimed at a first static self-contained low-level - translated version. - + efforts, aimed at a first static self-contained low-level + translated version. Modified: pypy/branch/pycompiler/documentation/misc.txt ============================================================================== --- pypy/branch/pycompiler/documentation/misc.txt (original) +++ pypy/branch/pycompiler/documentation/misc.txt Fri Jul 1 18:30:34 2005 @@ -138,7 +138,7 @@ _codecsmodule -_csv - already exists? +_csv - already exists? See http://python-dsv.sourceforge.net/ _heapqmodule - already exists Modified: pypy/branch/pycompiler/documentation/objspace.txt ============================================================================== --- pypy/branch/pycompiler/documentation/objspace.txt (original) +++ pypy/branch/pycompiler/documentation/objspace.txt Fri Jul 1 18:30:34 2005 @@ -354,7 +354,7 @@ :args: list of arguments. Each one is a Constant or a Variable seen previously in the basic block. :result: a *new* Variable into which the result is to be stored. - Note that operations usually cannot implicitely raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. + Note that operations usually cannot implicitly raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. Variable Modified: pypy/branch/pycompiler/documentation/svn-help.txt ============================================================================== --- pypy/branch/pycompiler/documentation/svn-help.txt (original) +++ pypy/branch/pycompiler/documentation/svn-help.txt Fri Jul 1 18:30:34 2005 @@ -1,9 +1,9 @@ -Installing subversion for PyPy -============================== +Installing subversion for PyPy +============================== -Jens-Uwe Mager has prepared some installation files which should -help you to install subversion on your computer. +Jens-Uwe Mager has prepared some installation files which should +help you to install subversion on your computer. + Download Unix source tarball or prepackaged versions_ for MacOS, Windows, FreeBSD and Linux @@ -12,7 +12,7 @@ * See Microsoft website_ if you have .DLL issues. * Windows Installer file for Tortoise SVN (like Tortoise CVS) GUI_ - (Pick the UNICODE version for Windows 2000 and XP and + (Pick the UNICODE version for Windows 2000 and XP and see Win_ 2000, NT if you have problems loading it.) + Local copy of MacOS_ X binary tar ball @@ -28,7 +28,7 @@ **Download and install the appropriate installation file of subversion above.** -For linux: +For linux: download the tarball. unzip and untar it. Then type *./configure*. Then, as root, *make* followed by *make install*. Voil? ... a subversion client. @@ -87,7 +87,7 @@ Transmitting file data . Committed revision 631. -Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made! +Check online on the `svn-commit archives`_ and you'll see your revision. Feel free to add a documentation file on any major changes you've made! .. _`svn-commit archives`: http://codespeak.net/pipermail/pypy-svn/ @@ -158,4 +158,4 @@ .. _guide: http://svnbook.red-bean.com/book.html#svn-ch-1 .. _backports: http://www.backports.org .. _online: http://codespeak.net/svn/pypy/dist/ -.. _coding-guide: coding-guide.html +.. _coding-guide: coding-guide.html Modified: pypy/branch/pycompiler/documentation/translation.txt ============================================================================== --- pypy/branch/pycompiler/documentation/translation.txt (original) +++ pypy/branch/pycompiler/documentation/translation.txt Fri Jul 1 18:30:34 2005 @@ -24,12 +24,12 @@ Here are the steps we follow to translate a given program: 1. The complete program is imported. If needed, extra initialization is - performed. Once this is done, the program must be present in memory is + performed. Once this is done, the program must be present in memory as a form that is "static enough" in the sense of RPython_. 2. The `Flow Object Space`_ processes the input program, turning each function independently into a `control flow graph`_ data structure - recording sequences of basic operations in + recording sequences of basic operations in static single assignment form `SSA`_. 3. Optionally, the Annotator_ performs global type inference on the @@ -67,56 +67,56 @@ (INCOMPLETE DRAFT) -We describe below how a control flow graph can be "annotated" to -discover the types of the objects. This annotation pass is a form of -type inference. It is done after control flow graphs are built by the -FlowObjSpace, but before these graphs are translated into low-level code +We describe below how a control flow graph can be "annotated" to +discover the types of the objects. This annotation pass is a form of +type inference. It is done after control flow graphs are built by the +FlowObjSpace, but before these graphs are translated into low-level code (e.g. C/Lisp/Pyrex). Model ------------------------ -The major goal of the annotator is to "annotate" each variable that -appears in a flow graph. An "annotation" describes all the possible -Python objects that this variable could contain at run-time, based on a +The major goal of the annotator is to "annotate" each variable that +appears in a flow graph. An "annotation" describes all the possible +Python objects that this variable could contain at run-time, based on a whole-program analysis of all the flow graphs --- one per function. -An "annotation" is an instance of ``SomeObject``. There are subclasses -that are meant to represent specific families of objects. Note that -these classes are all meant to be instantiated; the classes ``SomeXxx`` +An "annotation" is an instance of ``SomeObject``. There are subclasses +that are meant to represent specific families of objects. Note that +these classes are all meant to be instantiated; the classes ``SomeXxx`` themselves are not the annotations. Here is an overview (see ``pypy.annotation.model``): -* ``SomeObject`` is the base class. An instance ``SomeObject()`` - represents any Python object. It is used for the case where we don't - have enough information to be more precise. In practice, the presence - of ``SomeObject()`` means that we have to make the annotated source code +* ``SomeObject`` is the base class. An instance ``SomeObject()`` + represents any Python object. It is used for the case where we don't + have enough information to be more precise. In practice, the presence + of ``SomeObject()`` means that we have to make the annotated source code simpler or the annotator smarter. -* ``SomeInteger()`` represents any integer. +* ``SomeInteger()`` represents any integer. ``SomeInteger(nonneg=True)`` represent a non-negative integer (``>=0``). -* ``SomeString()`` represents any string; ``SomeChar()`` a string of +* ``SomeString()`` represents any string; ``SomeChar()`` a string of length 1. -* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``. The - elements in this tuple are themselves constrained by the given list of - annotations. For example, ``SomeTuple([SomeInteger(), SomeString()])`` +* ``SomeTuple([s1,s2,..,sn])`` represents a tuple of length ``n``. The + elements in this tuple are themselves constrained by the given list of + annotations. For example, ``SomeTuple([SomeInteger(), SomeString()])`` represents a tuple with two items: an integer and a string. -There are more complex subclasses of ``SomeObject`` that we describe in +There are more complex subclasses of ``SomeObject`` that we describe in more details below. -All the ``SomeXxx`` instances can optionally have a ``const`` attribute, -which means that we know exactly which Python object the Variable will +All the ``SomeXxx`` instances can optionally have a ``const`` attribute, +which means that we know exactly which Python object the Variable will contain. -All the ``SomeXxx`` instances are supposed to be immutable. The -annotator manages a dictionary mapping Variables (which appear in flow -graphs) to ``SomeXxx`` instances; if it needs to revise its belief about -what a Variable can contain, it does so by updating this dictionary, not +All the ``SomeXxx`` instances are supposed to be immutable. The +annotator manages a dictionary mapping Variables (which appear in flow +graphs) to ``SomeXxx`` instances; if it needs to revise its belief about +what a Variable can contain, it does so by updating this dictionary, not the ``SomeXxx`` instance. @@ -124,18 +124,18 @@ Annotator -------------------------- -The annotator itself (``pypy.translator.annrpython``) works by -propagating the annotations forward in the flow graphs, starting at some -entry point function, possibly with explicitely provided annotations -about the entry point's input arguments. It considers each operation in -the flow graph in turn. Each operation takes a few input arguments -(Variables and Constants) and produce a single result (a Variable). -Depending on the input argument's annotations, an annotation about the -operation result is produced. The exact rules to do this are provided -by the whole ``pypy.annotation`` subdirectory, which defines all the -cases in detail according to the R-Python semantics. For example, if -the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are -annotated with ``SomeInteger()``, then v3 also receives the annotation +The annotator itself (``pypy.translator.annrpython``) works by +propagating the annotations forward in the flow graphs, starting at some +entry point function, possibly with explicitely provided annotations +about the entry point's input arguments. It considers each operation in +the flow graph in turn. Each operation takes a few input arguments +(Variables and Constants) and produce a single result (a Variable). +Depending on the input argument's annotations, an annotation about the +operation result is produced. The exact rules to do this are provided +by the whole ``pypy.annotation`` subdirectory, which defines all the +cases in detail according to the R-Python semantics. For example, if +the operation is 'v3=add(v1,v2)' and the Variables v1 and v2 are +annotated with ``SomeInteger()``, then v3 also receives the annotation ``SomeInteger()``. So for example the function:: def f(n): @@ -145,22 +145,22 @@ start ----------. | - V + V +-------------------+ | v2 = add(v1, 1) | +-------------------+ | `---> return block -If the annotator is told that v1 is ``SomeInteger()``, then it will -deduce that v2 (and hence the function's return value) is +If the annotator is told that v1 is ``SomeInteger()``, then it will +deduce that v2 (and hence the function's return value) is ``SomeInteger()``. .. _above: -This step-by-step annotation phase proceeds through all the operations -in a block, and then along the links between the blocks of the flow -graph. If there are loops in the flow graph, then the links will close +This step-by-step annotation phase proceeds through all the operations +in a block, and then along the links between the blocks of the flow +graph. If there are loops in the flow graph, then the links will close back to already-seen blocks, as in:: def g(n): @@ -189,60 +189,60 @@ | m3 = sub(n3, 1) |---' +--------------------+ -Be sure to follow the variable renaming that occurs systematically -across each link in a flow graph. In the above example the Variables -have been given names similar to the name of the original variables in -the source code (the FlowObjSpace tries to do this too) but keep in mind +Be sure to follow the variable renaming that occurs systematically +across each link in a flow graph. In the above example the Variables +have been given names similar to the name of the original variables in +the source code (the FlowObjSpace tries to do this too) but keep in mind that all Variables are different: n1, n2, i2, v2, n3, i3, j3, m3. -Assume that we call the annotator with an input annotation of -``SomeInteger()`` for n1. Following the links from the start, the -annotator will first believe that the Variable i2, whose value comes -from the constant 0 of the first link, must always be zero. It will -thus use the annotation ``SomeInteger(const=0)`` for i2. Then it will -propagate the annotations through both blocks, and find that v2 is -``SomeBool()`` and all other variables are ``SomeInteger()``. In -particular, the annotation of j3 is different from the annotation of the -Variable i2 into which it is copied (via the back-link). More -precisely, j3 is ``SomeInteger()`` but i2 is the more specific -``SomeInteger(const=0)``. This means that the assumption that i2 must -always be zero is found to be wrong. At this point, the annotation of -i2 is *generalized* to include both the existing and the new annotation. -(This is the purpose of ``pypy.annotation.model.unionof()``). Then +Assume that we call the annotator with an input annotation of +``SomeInteger()`` for n1. Following the links from the start, the +annotator will first believe that the Variable i2, whose value comes +from the constant 0 of the first link, must always be zero. It will +thus use the annotation ``SomeInteger(const=0)`` for i2. Then it will +propagate the annotations through both blocks, and find that v2 is +``SomeBool()`` and all other variables are ``SomeInteger()``. In +particular, the annotation of j3 is different from the annotation of the +Variable i2 into which it is copied (via the back-link). More +precisely, j3 is ``SomeInteger()`` but i2 is the more specific +``SomeInteger(const=0)``. This means that the assumption that i2 must +always be zero is found to be wrong. At this point, the annotation of +i2 is *generalized* to include both the existing and the new annotation. +(This is the purpose of ``pypy.annotation.model.unionof()``). Then these more general annotations must again be propagated forward. -This process of successive generalizations continues until the -annotations stabilize. In the above example, it is sufficient to -re-analyse the first block once, but in general it can take several -iterations to reach a fixpoint. Annotations may also be propagated from -one flow graph to another and back repeatedly, across ``call`` -operations. The overall model should ensure that this process -eventually terminates under reasonable conditions. Note that as long as -the process is not finished, the annotations given to the Variables are -wrong, in the sense that they are too specific; at run-time, the -Variables will possibly contain Python objects outside the set defined +This process of successive generalizations continues until the +annotations stabilize. In the above example, it is sufficient to +re-analyse the first block once, but in general it can take several +iterations to reach a fixpoint. Annotations may also be propagated from +one flow graph to another and back repeatedly, across ``call`` +operations. The overall model should ensure that this process +eventually terminates under reasonable conditions. Note that as long as +the process is not finished, the annotations given to the Variables are +wrong, in the sense that they are too specific; at run-time, the +Variables will possibly contain Python objects outside the set defined by the annotation, and the annotator doesn't know it yet. Description of the available types ----------------------------------------------- -The reference and the details for the annotation model is found in the -module ``pypy.annotation.model``. We describe below the issues related +The reference and the details for the annotation model is found in the +module ``pypy.annotation.model``. We describe below the issues related to the various kinds of annotations. Simple Types ++++++++++++ -``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands +``SomeInteger``, ``SomeBool``, ``SomeString``, ``SomeChar`` all stands for the obvious corresponding set of immutable Python objects. Tuples ++++++ -``SomeTuple`` only considers tuples of known length. We don't try to +``SomeTuple`` only considers tuples of known length. We don't try to handle tuples of varying length (the program should use lists instead). @@ -337,46 +337,46 @@ User-defined Classes and Instances ++++++++++++++++++++++++++++++++++ -``SomeInstance`` stands for an instance of the given class or any -subclass of it. For each user-defined class seen by the annotator, we -maintain a ClassDef (``pypy.annotation.classdef``) describing the -attributes of the instances of the class; essentially, a ClassDef gives -the set of all class-level and instance-level attributes, and for each +``SomeInstance`` stands for an instance of the given class or any +subclass of it. For each user-defined class seen by the annotator, we +maintain a ClassDef (``pypy.annotation.classdef``) describing the +attributes of the instances of the class; essentially, a ClassDef gives +the set of all class-level and instance-level attributes, and for each one, a corresponding ``SomeXxx`` annotation. -Instance-level attributes are discovered progressively as the annotation +Instance-level attributes are discovered progressively as the annotation progresses. Assignments like:: inst.attr = value -update the ClassDef of the given instance to record that the given +update the ClassDef of the given instance to record that the given attribute exists and can be as general as the given value. -For every attribute, the ClassDef also records all the positions where -the attribute is *read*. If, at some later time, we discover an -assignment that forces the annotation about the attribute to be -generalized, then all the places that read the attribute so far are -marked as invalid and the annotator will have to restart its analysis +For every attribute, the ClassDef also records all the positions where +the attribute is *read*. If, at some later time, we discover an +assignment that forces the annotation about the attribute to be +generalized, then all the places that read the attribute so far are +marked as invalid and the annotator will have to restart its analysis from there. -The distinction between instance-level and class-level attributes is -thin; class-level attributes are essentially considered as initial -values for instance-level attributes. Methods are not special in this -respect, expect that they are bound to the instance (i.e. ``self = -SomeInstance(cls)``) when considered as the initial value for the +The distinction between instance-level and class-level attributes is +thin; class-level attributes are essentially considered as initial +values for instance-level attributes. Methods are not special in this +respect, except that they are bound to the instance (i.e. ``self = +SomeInstance(cls)``) when considered as the initial value for the instance. -The inheritance rules are as follows: the union of two ``SomeInstance`` -annotations is the ``SomeInstance`` of the most precise common base -class. If an attribute is considered (i.e. read or written) through a -``SomeInstance`` of a parent class, then we assume that all subclasses -also have the same attribute, and that the same annotation applies to -them all (so code like ``return self.x`` in a method of a parent class -forces the parent class and all its subclasses to have an attribute -``x``, whose annotation is general enough to contain all the values that -all the subclasses might want to store in ``x``). However, distinct -subclasses can have attributes of the same names with different, -unrelated annotations if they are not used in a general way through the +The inheritance rules are as follows: the union of two ``SomeInstance`` +annotations is the ``SomeInstance`` of the most precise common base +class. If an attribute is considered (i.e. read or written) through a +``SomeInstance`` of a parent class, then we assume that all subclasses +also have the same attribute, and that the same annotation applies to +them all (so code like ``return self.x`` in a method of a parent class +forces the parent class and all its subclasses to have an attribute +``x``, whose annotation is general enough to contain all the values that +all the subclasses might want to store in ``x``). However, distinct +subclasses can have attributes of the same names with different, +unrelated annotations if they are not used in a general way through the parent class. @@ -443,9 +443,25 @@ Overview -------- -The RPython Typer is the bridge between the Annotator_ and the low-level code generators. The annotator computes types (or "annotations") that are high-level, in the sense that they describe RPython types like lists or instances of user-defined classes. In general, though, to emit code we need to represent these high-level annotations into the low-level model of the target language; for C, this means structures and pointers and arrays. The Typer both determines the appropriate low-level type for each annotation, and tries to replace *all* operations in the control flow graphs with one or a few low-level operations. Just like low-level types, there is only a fairly restricted set of low-level operations, along the lines of reading or writing from or to a field of a structure. - -In theory, this step is optional; some code generators might be able to read directly the high-level types. However, we expect that case to be the exception. "Compiling" high-level types into low-level ones is rather more messy than one would expect. This was the motivation for making this step explicit and isolated in a single place. After Typing, the graphs can only contain very few operations, which makes the job of the code generators much simpler. +The RPython Typer is the bridge between the Annotator_ and the low-level code +generators. The annotator computes types (or "annotations") that are +high-level, in the sense that they describe RPython types like lists or +instances of user-defined classes. In general, though, to emit code we need +to represent these high-level annotations into the low-level model of the +target language; for C, this means structures and pointers and arrays. The +Typer both determines the appropriate low-level type for each annotation, and +tries to replace *all* operations in the control flow graphs with one or a few +low-level operations. Just like low-level types, there is only a fairly +restricted set of low-level operations, along the lines of reading or writing +from or to a field of a structure. + +In theory, this step is optional; some code generators might be able to read +directly the high-level types. However, we expect that case to be the +exception. "Compiling" high-level types into low-level ones is rather more +messy than one would expect. This was the motivation for making this step +explicit and isolated in a single place. After Typing, the graphs can only +contain very few operations, which makes the job of the code generators much +simpler. Example: Integer operations @@ -465,33 +481,78 @@ v3 = int_add(v1, v2) -where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 (which might be instances of Variable or possibly Constant). In our model, this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the purpose of replacing the operation called ``add`` with ``int_add`` is that code generators no longer have to worry about what kind of addition (or concatenation maybe?) it means. +where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. +This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 +(which might be instances of Variable or possibly Constant). In our model, +this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the +purpose of replacing the operation called ``add`` with ``int_add`` is that +code generators no longer have to worry about what kind of addition (or +concatenation maybe?) it means. The process in more details --------------------------- -The RPython Typer has a structure similar to that of the Annotator_: both consider each block of the flow graphs in turn, and perform some analysis on each operation. In both cases the analysis of an operation depends on the annotations of its input arguments. This is reflected in the usage of the same ``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rint.py`_). - -The analogy stops here, though: while it runs, the Annotator is in the middle of computing the annotations, so it might need to reflow and generalize until a fixpoint is reached. The Typer, by contrast, works on the final annotations that the Annotator computed, without changing them, assuming that they are globally consistent. There is no need to reflow: the Typer considers each block only once. And unlike the Annotator, the Typer completely modifies the flow graph, by replacing each operation with some low-level operations. - -In addition to replacing operations, the RTyper creates a ``concretetype`` attribute on all Variables and Constants in the flow graphs, which tells code generators which type to use for each of them. This attribute is a `low-level type`_, as described below. +The RPython Typer has a structure similar to that of the Annotator_: both +consider each block of the flow graphs in turn, and perform some analysis on +each operation. In both cases the analysis of an operation depends on the +annotations of its input arguments. This is reflected in the usage of the same +``__extend__`` syntax in the source files (compare e.g. +`annotation/binaryop.py`_ and `rpython/rint.py`_). + +The analogy stops here, though: while it runs, the Annotator is in the middle +of computing the annotations, so it might need to reflow and generalize until +a fixpoint is reached. The Typer, by contrast, works on the final annotations +that the Annotator computed, without changing them, assuming that they are +globally consistent. There is no need to reflow: the Typer considers each +block only once. And unlike the Annotator, the Typer completely modifies the +flow graph, by replacing each operation with some low-level operations. + +In addition to replacing operations, the RTyper creates a ``concretetype`` +attribute on all Variables and Constants in the flow graphs, which tells code +generators which type to use for each of them. This attribute is a +`low-level type`_, as described below. Representations --------------- -Representations -- the Repr classes -- are the most important internal classes used by the RTyper. (They are internal in the sense that they are an "implementation detail" and their instances just go away after the RTyper is finished; the code generators should only use the ``concretetype`` attributes, which are not Repr instances but `low-level types`_.) - -A representation contains all the logic about mapping a specific SomeXxx() annotation to a specific low-level type. For the time being, the RTyper assumes that each SomeXxx() instance needs only one "canonical" representation. For example, all variables annotated with SomeInteger() will correspond to the ``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, variables annotated SomeList() can correspond either to a structure holding an array of items of the correct type, or -- if the list in question is just a range() with a constant step -- a structure with just start and stop fields. - -This example shows that two representations may need very different low-level implementations for the same high-level operations. This is the reason for turning representations into explicit objects. - -The base Repr class is defined in `rpython/rmodel.py`_. Most of the ``rpython/r*.py`` files define one or a few subclasses of Repr. The method getrepr() of the RTyper will build and cache a single Repr instance per SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the same Repr instance. - -The key attribute of a Repr instance is called ``lowleveltype``, which is what gets copied into the attribute ``concretetype`` of the Variables that have been given this representation. The RTyper also computes a ``concretetype`` for Constants, to match the way they are used in the low-level operations (for example, ``int_add(x, 1)`` requires a ``Constant(1)`` with ``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time). - -In addition to ``lowleveltype``, each Repr subclass provides a set of methods called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` is turned into low-level operations. +Representations -- the Repr classes -- are the most important internal classes +used by the RTyper. (They are internal in the sense that they are an +"implementation detail" and their instances just go away after the RTyper is +finished; the code generators should only use the ``concretetype`` attributes, +which are not Repr instances but `low-level types`_.) + +A representation contains all the logic about mapping a specific SomeXxx() +annotation to a specific low-level type. For the time being, the RTyper +assumes that each SomeXxx() instance needs only one "canonical" representation. +For example, all variables annotated with SomeInteger() will correspond to the +``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, +variables annotated SomeList() can correspond either to a structure holding an +array of items of the correct type, or -- if the list in question is just a +range() with a constant step -- a structure with just start and stop fields. + +This example shows that two representations may need very different low-level +implementations for the same high-level operations. This is the reason for +turning representations into explicit objects. + +The base Repr class is defined in `rpython/rmodel.py`_. Most of the +``rpython/r*.py`` files define one or a few subclasses of Repr. The method +getrepr() of the RTyper will build and cache a single Repr instance per +SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the +same Repr instance. + +The key attribute of a Repr instance is called ``lowleveltype``, which is what +gets copied into the attribute ``concretetype`` of the Variables that have been +given this representation. The RTyper also computes a ``concretetype`` for +Constants, to match the way they are used in the low-level operations (for +example, ``int_add(x, 1)`` requires a ``Constant(1)`` with +``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a +``Constant(1)`` that must actually be a PyObject at run-time). + +In addition to ``lowleveltype``, each Repr subclass provides a set of methods +called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` +is turned into low-level operations. .. _`low-level type`: @@ -499,17 +560,30 @@ Low-Level Types --------------- -The RPython Typer uses a standard low-level model which we believe can correspond rather directly to various target languages from C to LLVM to Java. This model is implemented in the first part of `rpython/lltype.py`_. - -The second part of `rpython/lltype.py`_ is a runnable implementation of these types, for testing purposes. It allows us to write and test plain Python code using a malloc() function to obtain and manipulate structures and arrays. This is useful for example to implement and test RPython types like 'list' with its operations and methods. - -The basic assumption is that Variables (i.e. local variables and function arguments and return value) all contain "simple" values: basically, just integers or pointers. All the "container" data structures (struct and array) are allocated in the heap, and they are always manipulated via pointers. (There is no equivalent to the C notion of local variable of a ``struct`` type.) - -Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you have some older version, the ``lltype`` module might be called ``lltypes`` and you may need to add or remove a few ``Gc`` prefixes here and there):: +The RPython Typer uses a standard low-level model which we believe can +correspond rather directly to various target languages from C to LLVM to Java. +This model is implemented in the first part of `rpython/lltype.py`_. + +The second part of `rpython/lltype.py`_ is a runnable implementation of these +types, for testing purposes. It allows us to write and test plain Python code +using a malloc() function to obtain and manipulate structures and arrays. +This is useful for example to implement and test RPython types like 'list' with +its operations and methods. + +The basic assumption is that Variables (i.e. local variables and function +arguments and return value) all contain "simple" values: basically, just +integers or pointers. All the "container" data structures (struct and array) +are allocated in the heap, and they are always manipulated via pointers. +(There is no equivalent to the C notion of local variable of a ``struct`` type.) + +Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you +have some older version, the ``lltype`` module might be called ``lltypes`` and +you may need to add or remove a few ``Gc`` prefixes here and there):: >>> from pypy.rpython.lltype import * -Here are a few primitive low-level types, and the typeOf() function to figure them out:: +Here are a few primitive low-level types, and the typeOf() function to figure +them out:: >>> Signed @@ -520,15 +594,20 @@ >>> typeOf('x') -Let's say that we want to build a type "point", which is a structure with two integer fields "x" and "y":: +Let's say that we want to build a type "point", which is a structure with two +integer fields "x" and "y":: >>> POINT = GcStruct('point', ('x', Signed), ('y', Signed)) >>> POINT -The structure is a ``GcStruct``, which means a structure that can be allocated in the heap and eventually freed by some garbage collector. (For platforms where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.) +The structure is a ``GcStruct``, which means a structure that can be allocated +in the heap and eventually freed by some garbage collector. (For platforms +where we use reference counting, think about ``GcStruct`` as a struct with an +additional reference counter field.) -Giving a name ('point') to the GcStruct is only for clarity: it is used in the representation. +Giving a name ('point') to the GcStruct is only for clarity: it is used in the +representation. >>> p = malloc(POINT) >>> p @@ -539,14 +618,23 @@ >>> p -``malloc()`` allocates a structure from the heap, initalizes it to 0 (currently), and returns a pointer to it. The point of all this is to work with a very limited, easily controllable set of types, and define implementations of types like list in this elementary world. The ``malloc()`` function is a kind of placeholder, which must eventually be provided by the code generator for the target platform; but as we have just seen its Python implementation in `rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc. +``malloc()`` allocates a structure from the heap, initalizes it to 0 +(currently), and returns a pointer to it. The point of all this is to work with +a very limited, easily controllable set of types, and define implementations of +types like list in this elementary world. The ``malloc()`` function is a kind +of placeholder, which must eventually be provided by the code generator for the +target platform; but as we have just seen its Python implementation in ` +rpython/lltype.py`_ works too, which is primarily useful for testing, +interactive exploring, etc. -The argument to ``malloc()`` is the structure type directly, but it returns a pointer to the structure, as ``typeOf()`` tells you:: +The argument to ``malloc()`` is the structure type directly, but it returns a +pointer to the structure, as ``typeOf()`` tells you:: >>> typeOf(p) -For the purpose of creating structures with pointers to other structures, we can declare pointer types explicitely:: +For the purpose of creating structures with pointers to other structures, we can +declare pointer types explicitely:: >>> typeOf(p) == Ptr(POINT) True @@ -559,7 +647,8 @@ >>> b.p2.y 42 -The world of low-level types is more complicated than integers and GcStructs, though. The next pages are a reference guide. +The world of low-level types is more complicated than integers and GcStructs, +though. The next pages are a reference guide. Primitive Types @@ -571,6 +660,9 @@ Unsigned a non-signed integer in one machine word (``unsigned long``) +Float + a 64-bit float (``double``) + Char a single character (``char``) @@ -578,8 +670,8 @@ a boolean value Void - a constant. Meant for variables and function arguments that should - disappear from the generated code. + a constant. Meant for variables, function arguments, structure fields, etc. + which should disappear from the generated code. Structure Types @@ -590,13 +682,27 @@ MyStructType = Struct('somename', ('field1', Type1), ('field2', Type2)...) MyStructType = GcStruct('somename', ('field1', Type1), ('field2', Type2)...) -This declares a structure (or a Pascal ``record``) containing the specified named fields with the given types. The field names cannot start with an underscore. As noted above, you cannot directly manipulate structure objects, but only pointer to structures living in the heap. - -By contrast, the fields themselves can be of primitive, pointer or container type. When a structure contains another structure as a field we say that the latter is "inlined" in the former: the bigger structure contains the smaller one as part of its memory layout. - -A structure can also contain an inlined array (see below), but only as its last field: in this case it is a "variable-sized" structure, whose memory layout starts with the non-variable fields and ends with a variable number of array items. This number is determined when a structure is allocated in the heap. Variable-sized structures cannot be inlined in other structures. - -GcStructs have a platform-specific GC header (e.g. a reference counter); only these can be dynamically malloc()ed. The non-GC version of Struct does not have any header, and is suitable for being embedded ("inlined") inside other structures. As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure. +This declares a structure (or a Pascal ``record``) containing the specified +named fields with the given types. The field names cannot start with an +underscore. As noted above, you cannot directly manipulate structure objects, +but only pointer to structures living in the heap. + +By contrast, the fields themselves can be of primitive, pointer or container +type. When a structure contains another structure as a field we say that the +latter is "inlined" in the former: the bigger structure contains the smaller one +as part of its memory layout. + +A structure can also contain an inlined array (see below), but only as its last +field: in this case it is a "variable-sized" structure, whose memory layout +starts with the non-variable fields and ends with a variable number of array +items. This number is determined when a structure is allocated in the heap. +Variable-sized structures cannot be inlined in other structures. + +GcStructs have a platform-specific GC header (e.g. a reference counter); only +these can be dynamically malloc()ed. The non-GC version of Struct does not have +any header, and is suitable for being embedded ("inlined") inside other +structures. As an exception, a GcStruct can be embedded as the first field of a +GcStruct: the parent structure uses the same GC header as the substructure. Array Types @@ -612,23 +718,48 @@ MyArrayType = Array(('field1', Type1), ('field2', Type2)...) -You can build arrays whose items are either primitive or pointer types, or (non-GC non-varsize) structures. - -GcArrays can be malloc()ed. The length must be specified when malloc() is called, and arrays cannot be resized; this length is stored explicitely in a header. +You can build arrays whose items are either primitive or pointer types, or +(non-GC non-varsize) structures. -The non-GC version of Array can be used as the last field of a structure, to make a variable-sized structure. The whole structure can then be malloc()ed, and the length of the array is specified at this time. +GcArrays can be malloc()ed. The length must be specified when malloc() is +called, and arrays cannot be resized; this length is stored explicitely in a +header. + +The non-GC version of Array can be used as the last field of a structure, to +make a variable-sized structure. The whole structure can then be malloc()ed, +and the length of the array is specified at this time. Pointer Types +++++++++++++ -As in C, pointers provide the indirection needed to make a reference modifiable or sharable. Pointers can only point to a structure, an array, a function (see below) or a PyObject (see below). Pointers to primitive types, if needed, must be done by pointing to a structure with a single field of the required type. Pointer types are declared by:: +As in C, pointers provide the indirection needed to make a reference modifiable +or sharable. Pointers can only point to a structure, an array, a function +(see below) or a PyObject (see below). Pointers to primitive types, if needed, +must be done by pointing to a structure with a single field of the required +type. Pointer types are declared by:: Ptr(TYPE) -At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a reference to what they are pointing to. Pointers to non-GC structures that can go away when their container is deallocated (Struct, Array) must be handled with care: the bigger structure of which they are part of could be freed while the Ptr to the substructure is still in use. In general, it is a good idea to avoid passing around pointers to inlined substructures of malloc()ed structures. (The testing implementation of `rpython/lltype.py`_ checks to some extend that you are not trying to use a pointer to a structure after its container has been freed, using weak references. But pointers to non-GC structures are not officially meant to be weak references: using them after what they point to has been freed just crashes.) - -The malloc() operation allocates and returns a Ptr to a new GC structure or array. In a refcounting implementation, malloc() would allocate enough space for a reference counter before the actual structure, and initialize it to 1. Note that the testing implementation also allows malloc() to allocate a non-GC structure or array with a keyword argument ``immortal=True``. Its purpose is to declare and initialize prebuilt data structures which the code generators will turn into static immortal non-GC'ed data. +At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a +reference to what they are pointing to. Pointers to non-GC structures that can +go away when their container is deallocated (Struct, Array) must be handled +with care: the bigger structure of which they are part of could be freed while +the Ptr to the substructure is still in use. In general, it is a good idea to +avoid passing around pointers to inlined substructures of malloc()ed structures. +(The testing implementation of `rpython/lltype.py`_ checks to some extend that +you are not trying to use a pointer to a structure after its container has been +freed, using weak references. But pointers to non-GC structures are not +officially meant to be weak references: using them after what they point to has +been freed just crashes.) + +The malloc() operation allocates and returns a Ptr to a new GC structure or +array. In a refcounting implementation, malloc() would allocate enough space +for a reference counter before the actual structure, and initialize it to 1. +Note that the testing implementation also allows malloc() to allocate a non-GC +structure or array with a keyword argument ``immortal=True``. Its purpose is to +declare and initialize prebuilt data structures which the code generators will +turn into static immortal non-GC'ed data. Function Types @@ -638,9 +769,16 @@ MyFuncType = FuncType([Type1, Type2, ...], ResultType) -declares a function type taking arguments of the given types and returning a result of the given type. All these types must be primitives or pointers. The function type itself is considered to be a "container" type: if you wish, a function contains the bytes that make up its executable code. As with structures and arrays, they can only be manipulated through pointers. - -The testing implementation allows you to "create" functions by calling ``functionptr(TYPE, name, **attrs)``. The extra attributes describe the function in a way that isn't fully specified now, but the following attributes *might* be present: +declares a function type taking arguments of the given types and returning a +result of the given type. All these types must be primitives or pointers. The +function type itself is considered to be a "container" type: if you wish, a +function contains the bytes that make up its executable code. As with +structures and arrays, they can only be manipulated through pointers. + +The testing implementation allows you to "create" functions by calling +``functionptr(TYPE, name, **attrs)``. The extra attributes describe the +function in a way that isn't fully specified now, but the following attributes +*might* be present: :_callable: a Python callable, typically a function object. :graph: the flow graph of the function. @@ -649,17 +787,48 @@ The PyObject Type +++++++++++++++++ -This is a special type, for compatibility with CPython: it stands for a structure compatible with PyObject. This is also a "container" type (thinking about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated via a Ptr. A typed graph can still contain generic space operations (add, getitem, etc.) provided they are applied on objects whose low-level type is ``Ptr(PyObject)``. In fact, code generators that support this should consider that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. In this way, they can generate the correct code for fully-untyped flow graphs. +This is a special type, for compatibility with CPython: it stands for a +structure compatible with PyObject. This is also a "container" type (thinking +about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated +via a Ptr. A typed graph can still contain generic space operations (add, +getitem, etc.) provided they are applied on objects whose low-level type is +``Ptr(PyObject)``. In fact, code generators that support this should consider +that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. +In this way, they can generate the correct code for fully-untyped flow graphs. + +The testing implementation allows you to "create" PyObjects by calling +``pyobjectptr(obj)``. + + +Opaque Types +++++++++++++ + +Opaque types represent data implemented in a back-end specific way. This data cannot be inspected or manipulated. -The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``. +There is a predefined opaque type ``RuntimeTypeInfo``; at run-time, a value of type ``RuntimeTypeInfo`` represents a low-level type. In practice it is probably enough to be able to represent GcStruct and GcArray types. This is useful if we have a pointer of type ``Ptr(S)`` which can at run-time point either to a malloc'ed ``S`` alone, or to the ``S`` first field of a larger malloc'ed structure. The information about the exact larger type that it points to can be computed or passed around as a ``Ptr(RuntimeTypeInfo)``. Pointer equality on ``Ptr(RuntimeTypeInfo)`` can be used to check the type at run-time. + +At the moment, for memory management purposes, some back-ends actually require such information to be available at run-time in the following situation: when a GcStruct has another GcStruct as its first field. A reference-counting back-end needs to be able to know when a pointer to the smaller structure actually points to the larger one, so that it can also decref the extra fields. Depending on the situation, it is possible to reconstruct this information without having to store a flag in each and every instance of the smaller GcStruct. For example, the instances of a class hierarchy can be implemented by nested GcStructs, with instances of subclasses extending instances of parent classes by embedding the parent part of the instance as the first field. In this case, there is probably already a way to know the run-time class of the instance (e.g. a vtable pointer), but the back-end cannot guess this. This is the reason for which ``RuntimeTypeInfo`` was originally introduced: just after the GcStruct is created, the function attachRuntimeTypeInfo() should be called to attach to the GcStruct a low-level function of signature ``Ptr(GcStruct) -> Ptr(RuntimeTypeInfo)``. This function will be compiled by the back-end and automatically called at run-time. In the above example, it would follow the vtable pointer and fetch the opaque ``Ptr(RuntimeTypeInfo)`` from the vtable itself. (The reference-counting GenC back-end uses a pointer to the deallocation function as the opaque ``RuntimeTypeInfo``.) Implementing RPython types -------------------------- -As hinted above, the RPython types (e.g. 'list') are implemented in some "restricted-restricted Python" format by manipulating only low-level types, as provided by the testing implementation of malloc() and friends. What occurs then is that the same (tested!) very-low-level Python code -- which looks really just like C -- is then transformed into a flow graph and integrated with the rest of the user program. In other words, we replace an operation like ``add`` between two variables annotated as SomeList, with a ``direct_call`` operation invoking this very-low-level list concatenation. - -This list concatenation flow graph is then annotated as usual, with one difference: the annotator has to be taught about malloc() and the way the pointer thus obtained can be manipulated. This generates a flow graph which is hopefully completely annotated with SomePtr() annotation. Introduced just for this case, SomePtr maps directly to a low-level pointer type. This is the only change needed to the Annotator to allow it to perform type inference of our very-low-level snippets of code. +As hinted above, the RPython types (e.g. 'list') are implemented in some +"restricted-restricted Python" format by manipulating only low-level types, as +provided by the testing implementation of malloc() and friends. What occurs +then is that the same (tested!) very-low-level Python code -- which looks really +just like C -- is then transformed into a flow graph and integrated with the +rest of the user program. In other words, we replace an operation like ``add`` +between two variables annotated as SomeList, with a ``direct_call`` operation +invoking this very-low-level list concatenation. + +This list concatenation flow graph is then annotated as usual, with one +difference: the annotator has to be taught about malloc() and the way the +pointer thus obtained can be manipulated. This generates a flow graph which is +hopefully completely annotated with SomePtr() annotation. Introduced just for +this case, SomePtr maps directly to a low-level pointer type. This is the only +change needed to the Annotator to allow it to perform type inference of our +very-low-level snippets of code. See for example `rpython/rlist.py`_. @@ -677,9 +846,16 @@ Overview -------- -The task of GenC is to convert a flow graph into C code. By itself, GenC does not use the annotations in the graph. It can actually convert unannotated graphs to C. However, to make use of the annotations if they are present, an extra pass is needed: the `RPython Typer`_, whose task is to modify the flow graph according to the annotations, replacing operations with lower-level C-ish equivalents. - -XXX GenC is currently in the process of being updated to use the RPython Typer. more documentation needed when this is done. But the basic principle of creating code from flowgraphs is similar to the `Python back-end`_. +The task of GenC is to convert a flow graph into C code. By itself, GenC does +not use the annotations in the graph. It can actually convert unannotated +graphs to C. However, to make use of the annotations if they are present, an +extra pass is needed: the `RPython Typer`_, whose task is to modify the flow +graph according to the annotations, replacing operations with lower-level C-ish +equivalents. + +XXX GenC is currently in the process of being updated to use the RPython Typer. +More documentation needed when this is done. But the basic principle of creating +code from flowgraphs is similar to the `Python back-end`_. @@ -727,11 +903,11 @@ generates LLVM code that allocates enough memory for an instance of the class and then (if the class or a base class has an ``__init__`` method) tells the ``FuncRepr`` of the appropriate ``__init__`` method to generate the code for -the call to it. +the call to it. -Every representation object has a some other representations it depends on: A +Every representation object has some other representations it depends on: A ``ListRepr`` of lists instances of a class depends on the ``ClassRepr`` of -that class. To ensure that the typedef of of the class is written to the llvm +that class. To ensure that the typedef of the class is written to the llvm file before the typedef of the list, the dependency tree of representations traversed depth first when the LLVM code is written to a file. @@ -824,10 +1000,10 @@ Motivation ---------- -PyPy often makes use of `application-level`_ helper methods. -The idea of the 'geninterplevel' backend is to automatically transform -such application level implementations to their equivalent representation -at interpreter level. Then, the RPython to C translation hopefully can +PyPy often makes use of `application-level`_ helper methods. +The idea of the 'geninterplevel' backend is to automatically transform +such application level implementations to their equivalent representation +at interpreter level. Then, the RPython to C translation hopefully can produce more efficient code than always re-interpreting these methods. One property of translation from application level Python to @@ -864,26 +1040,26 @@ .. _implementation: http://codespeak.net/svn/pypy/dist/pypy/translator/geninterplevel.py -Let's try the little example from above_. You might want to look at the -flowgraph that it produces. Here, we directly run the Python translation -and look at the generated source. See also the header section of the implementation_ +Let's try the little example from above_. You might want to look at the +flowgraph that it produces. Here, we directly run the Python translation +and look at the generated source. See also the header section of the implementation_ for the interface:: >>> from pypy.translator.geninterplevel import translate_as_module >>> entrypoint, source = translate_as_module(""" - ... + ... ... def g(n): ... i = 0 ... while n: ... i = i + n ... n = n - 1 ... return i - ... + ... ... """) - + This call has invoked a PyPy interpreter running on FlowObjspace, recorded every possible codepath into a flowgraph, and then rendered the following source code:: - + >>> print source #!/bin/env python # -*- coding: LATIN-1 -*- Modified: pypy/branch/pycompiler/documentation/website/news.txt ============================================================================== --- pypy/branch/pycompiler/documentation/website/news.txt (original) +++ pypy/branch/pycompiler/documentation/website/news.txt Fri Jul 1 18:30:34 2005 @@ -12,17 +12,20 @@ Next Sprint after EuroPython 2005 1st-7th July ====================================================== -The next sprint is scheduled right after EuroPython_ 2005 in G?teborg, Sweden. -We take a day of break after the conference and start sprinting from 1st-7th -of July 2005. See the `sprint announcement`_. The sprint theme is related -strongly to `translation`_ and working towards getting a first self-contained -PyPy version. Additionally there will be a four day Pre-EuroPython sprint for -people who already are familiar with the PyPy code base. *(05/04/2005, -12/06/2005)* +The next sprint is scheduled right after EuroPython_ 2005 in +G?teborg, Sweden. We take a day of break after the conference +and start sprinting from 1st-7th of July 2005. See the +`sprint announcement`_ and the `list of people coming`_. The +sprint theme is related strongly to `translation`_ and working +towards getting a first self-contained PyPy version. +Additionally there will be a four day Pre-EuroPython sprint +for people who already are familiar with the PyPy code base. +*(05/04/2005, 12/06/2005, 22/06/2005)* .. _EuroPython: http://europython.org .. _`translation`: ../translation.html .. _`sprint announcement`: EP2005-announcement.html +.. _`list of people coming`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/EP2005-people.html First PyPy release! =================== Modified: pypy/branch/pycompiler/interpreter/eval.py ============================================================================== --- pypy/branch/pycompiler/interpreter/eval.py (original) +++ pypy/branch/pycompiler/interpreter/eval.py Fri Jul 1 18:30:34 2005 @@ -19,7 +19,7 @@ def exec_code(self, space, w_globals, w_locals): "Implements the 'exec' statement." - frame = self.create_frame(space, w_globals) + frame = self.create_frame(space, w_globals, None) frame.setdictscope(w_locals) return frame.run() @@ -107,7 +107,10 @@ if self.w_locals is None: self.w_locals = self.space.newdict([]) varnames = self.code.getvarnames() - for name, w_value in zip(varnames, self.getfastscope()): + fastscope_w = self.getfastscope() + for i in range(min(len(varnames), len(fastscope_w))): + name = varnames[i] + w_value = fastscope_w[i] if w_value is not None: w_name = self.space.wrap(name) self.space.setitem(self.w_locals, w_name, w_value) @@ -119,7 +122,7 @@ new_fastlocals_w = [None]*self.numlocals - for name, i in zip(varnames, range(self.numlocals)): + for i in range(min(len(varnames), self.numlocals)): w_name = self.space.wrap(varnames[i]) try: w_value = self.space.getitem(self.w_locals, w_name) Modified: pypy/branch/pycompiler/interpreter/function.py ============================================================================== --- pypy/branch/pycompiler/interpreter/function.py (original) +++ pypy/branch/pycompiler/interpreter/function.py Fri Jul 1 18:30:34 2005 @@ -16,7 +16,7 @@ """A function is a code object captured with some environment: an object space, a dictionary of globals, default arguments, and an arbitrary 'closure' passed to the code object.""" - + def __init__(self, space, code, w_globals=None, defs_w=[], closure=None, forcename=None): self.space = space self.name = forcename or code.co_name @@ -76,7 +76,7 @@ if not isinstance(code, PyCode) or len(code.co_freevars) == 0: raise OperationError(space.w_ValueError, space.wrap("no closure needed")) elif len(code.co_freevars) != n: - raise OperationError(space.w_ValueError, space.wrap("closure is wrong size")) + raise OperationError(space.w_ValueError, space.wrap("closure is wrong size")) closure = [] for w_cell in closure_w: cell = space.interpclass_w(w_cell) @@ -98,7 +98,7 @@ if not values_w: return space.w_None return space.newtuple(values_w) - + def fset_func_defaults(space, self, w_defaults): if not space.is_true( space.isinstance( w_defaults, space.w_tuple ) ): raise OperationError( space.w_TypeError, space.wrap("func_defaults must be set to a tuple object") ) @@ -125,10 +125,10 @@ else: self.w_module = space.w_None return self.w_module - + def fset___module__(space, self, w_module): self.w_module = w_module - + def fdel___module__(space, self): self.w_module = space.w_None @@ -140,7 +140,7 @@ if not isinstance(code, Code ): raise OperationError( space.w_TypeError, space.wrap("func_code must be set to a code object") ) self.code = code - + def fget_func_closure(space, self): if self.closure is not None: w_res = space.newtuple( [ space.wrap(i) for i in self.closure ] ) @@ -171,7 +171,7 @@ return space.type(w_obj) raise -class Method(Wrappable): +class Method(Wrappable): """A method is a function bound to a specific instance or class.""" def __init__(self, space, w_function, w_instance, w_class): @@ -179,7 +179,7 @@ self.w_function = w_function self.w_instance = w_instance # or None self.w_class = w_class # possibly space.w_None - + def descr_method__new__(space, w_subtype, w_function, w_instance, w_class=None): if space.is_w( w_instance, space.w_None ): w_instance = None @@ -218,7 +218,7 @@ instname += " " instdescr = "%sinstance" %instname msg = ("unbound method %s() must be called with %s" - "instance as first argument (got %s instead)") % (myname, clsdescr, instdescr) + "instance as first argument (got %s instead)") % (myname, clsdescr, instdescr) raise OperationError(space.w_TypeError, space.wrap(msg)) return space.call_args(self.w_function, args) @@ -241,17 +241,17 @@ def descr_method_call(self, __args__): return self.call_args(__args__) - def descr_method_repr(self): + def descr_method_repr(self): space = self.space name = self.w_function.getname(self.space, '?') - # XXX do we handle all cases sanely here? - if space.is_w(self.w_class, space.w_None): - w_class = space.type(self.w_instance) - else: - w_class = self.w_class + # XXX do we handle all cases sanely here? + if space.is_w(self.w_class, space.w_None): + w_class = space.type(self.w_instance) + else: + w_class = self.w_class typename = w_class.getname(self.space, '?') - if self.w_instance is None: - s = "" %(name, typename) + if self.w_instance is None: + s = "" %(name, typename) return space.wrap(s) else: info = "method %s of %s object" % (name, typename) Modified: pypy/branch/pycompiler/interpreter/nestedscope.py ============================================================================== --- pypy/branch/pycompiler/interpreter/nestedscope.py (original) +++ pypy/branch/pycompiler/interpreter/nestedscope.py Fri Jul 1 18:30:34 2005 @@ -73,7 +73,9 @@ # cellvars are values exported to inner scopes # freevars are values coming from outer scopes freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] try: w_value = cell.get() except ValueError: @@ -85,7 +87,9 @@ def locals2fast(self): PyInterpFrame.locals2fast(self) freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] w_name = self.space.wrap(name) try: w_value = self.space.getitem(self.w_locals, w_name) @@ -140,13 +144,13 @@ except ValueError: varname = f.getfreevarname(varindex) if f.iscellvar(varindex): - message = "local variable '%s' referenced before assignment" + message = "local variable '%s' referenced before assignment"%varname w_exc_type = f.space.w_UnboundLocalError else: message = ("free variable '%s' referenced before assignment" - " in enclosing scope") + " in enclosing scope"%varname) w_exc_type = f.space.w_NameError - raise OperationError(w_exc_type, f.space.wrap(message % varname)) + raise OperationError(w_exc_type, f.space.wrap(message)) else: f.valuestack.push(w_value) Modified: pypy/branch/pycompiler/interpreter/pycode.py ============================================================================== --- pypy/branch/pycompiler/interpreter/pycode.py (original) +++ pypy/branch/pycompiler/interpreter/pycode.py Fri Jul 1 18:30:34 2005 @@ -48,7 +48,7 @@ NESTED = 1 GENERATOR = 2 -frame_classes = {} +frame_classes = [] def setup_frame_classes(): "NOT_RPYTHON" @@ -66,6 +66,7 @@ dic[n] = func_with_new_name(x, x.__name__) return dic + frame_classes.extend([None]*4) frame_classes[0] = PyInterpFrame frame_classes[NESTED] = PyNestedScopeFrame frame_classes[GENERATOR] = type('PyGeneratorFrame', Modified: pypy/branch/pycompiler/interpreter/pyopcode.py ============================================================================== --- pypy/branch/pycompiler/interpreter/pyopcode.py (original) +++ pypy/branch/pycompiler/interpreter/pyopcode.py Fri Jul 1 18:30:34 2005 @@ -628,7 +628,7 @@ block = pyframe.FinallyBlock(f, f.next_instr + offsettoend) f.blockstack.push(block) - def CALL_FUNCTION(f, oparg, w_star=None, w_starstar=None): + def call_function(f, oparg, w_star=None, w_starstar=None): n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = {} @@ -644,18 +644,21 @@ w_result = f.space.call_args(w_function, args) f.valuestack.push(w_result) + def CALL_FUNCTION(f, oparg): + f.call_function(oparg) + def CALL_FUNCTION_VAR(f, oparg): w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs) + f.call_function(oparg, w_varargs) def CALL_FUNCTION_KW(f, oparg): w_varkw = f.valuestack.pop() - f.CALL_FUNCTION(oparg, None, w_varkw) + f.call_function(oparg, None, w_varkw) def CALL_FUNCTION_VAR_KW(f, oparg): w_varkw = f.valuestack.pop() w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs, w_varkw) + f.call_function(oparg, w_varargs, w_varkw) def MAKE_FUNCTION(f, numdefaults): w_codeobj = f.valuestack.pop() @@ -776,6 +779,7 @@ return # XXX add unicode handling file_softspace(stream, True) + print_item_to._annspecialcase_ = "specialize:argtype0" def print_newline_to(stream): stream.write("\n") Modified: pypy/branch/pycompiler/interpreter/typedef.py ============================================================================== --- pypy/branch/pycompiler/interpreter/typedef.py (original) +++ pypy/branch/pycompiler/interpreter/typedef.py Fri Jul 1 18:30:34 2005 @@ -24,16 +24,38 @@ # hint for the annotator: track individual constant instances of TypeDef return True -subclass_cache = {} -def get_unique_interplevel_subclass(cls, hasdict, wants_slots): - key = (cls, hasdict, wants_slots) - try: - return subclass_cache[key] - except KeyError: - subcls = _buildusercls(cls, hasdict, wants_slots) - subclass_cache[key] = subcls - return subcls -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" + +# we cannot specialize:memo by more than one PBC key +# so we need to work a bit to allow that + +def get_unique_interplevel_subclass(cls, hasdict, wants_slots): + if hasdict: + if wants_slots: + return get_unique_interplevel_WithDictWithSlots(cls) + else: + return get_unique_interplevel_WithDictNoSlots(cls) + else: + if wants_slots: + return get_unique_interplevel_NoDictWithSlots(cls) + else: + return get_unique_interplevel_NoDictNoSlots(cls) + +for hasdict in False, True: + for wants_slots in False, True: + name = hasdict and "WithDict" or "NoDict" + name += wants_slots and "WithSlots" or "NoSlots" + funcname = "get_unique_interplevel_%s" % (name,) + exec compile2(""" + subclass_cache_%(name)s = {} + def %(funcname)s(cls): + try: + return subclass_cache_%(name)s[cls] + except KeyError: + subcls = _buildusercls(cls, %(hasdict)r, %(wants_slots)r) + subclass_cache_%(name)s[cls] = subcls + return subcls + %(funcname)s._annspecialcase_ = "specialize:memo" + """ % locals()) def _buildusercls(cls, hasdict, wants_slots): "NOT_RPYTHON: initialization-time only" Modified: pypy/branch/pycompiler/lib/_exceptions.py ============================================================================== --- pypy/branch/pycompiler/lib/_exceptions.py (original) +++ pypy/branch/pycompiler/lib/_exceptions.py Fri Jul 1 18:30:34 2005 @@ -131,10 +131,24 @@ argc = len(args) self.args = args # modified: always assign args, no error check if argc == 4: - self.object = args[0] - self.start = args[1] - self.end = args[2] - self.reason = args[3] + if type(args[0]) == unicode: + self.object = args[0] + else: + raise TypeError('argument 0 must be unicode, not %s'%type(args[0])) + if type(args[1]) == int: + self.start = args[1] + else: + raise TypeError('argument 1 must be int, not %s'%type(args[1])) + if type(args[2]) == int: + self.end = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == str: + self.reason = args[3] + else: + raise TypeError('argument 3 must be str, not %s'%type(args[3])) + else: + raise TypeError('function takes exactly 4 arguments (%d given)'%argc) # auto-generated code, please check carefully! def __str__(self): @@ -181,9 +195,9 @@ def __init__(self, *args): argc = len(args) self.args = args - self.errno = None # default, hopefully - self.strerror = None # default, hopefully - self.filename = None # default, hopefully + self.errno = None + self.strerror = None + self.filename = None if 2 <= argc <= 3: self.errno = args[0] self.strerror = args[1] @@ -207,6 +221,50 @@ class DeprecationWarning(Warning): """Base class for warnings about deprecated features.""" +class UnicodeEncodeError(UnicodeError): + """Unicode encoding error.""" + + # auto-generated code, please check carefully! + def __init__(self, *args): + argc = len(args) + self.args = args # modified: always assign args, no error check + if argc == 5: + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == unicode: + self.object = args[1] + else: + raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) + + # auto-generated code, please check carefully! + def __str__(self): + # this is a bad hack, please supply an implementation + res = ' '.join([ + 'object=' + str(getattr(self, 'object', None)), + 'end=' + str(getattr(self, 'end', None)), + 'encoding=' + str(getattr(self, 'encoding', None)), + 'args=' + str(getattr(self, 'args', None)), + 'start=' + str(getattr(self, 'start', None)), + 'reason=' + str(getattr(self, 'reason', None)), + ]) + return res + class ArithmeticError(StandardError): """Base class for arithmetic errors.""" @@ -241,10 +299,22 @@ if argc >= 1: self.msg = args[0] if argc == 2: - self.filename = args[1][0] - self.lineno = args[1][1] - self.offset = args[1][2] - self.text = args[1][3] + if type(args[1][0]) == str: + self.filename = args[1][0] + else: + raise TypeError('argument 1 must be str, not %s'%type(args[1][0])) + if type(args[1][1]) == str: + self.lineno = args[1][1] + else: + raise TypeError('argument 2 must be str, not %s'%type(args[1][1])) + if type(args[1][2]) == str: + self.offset = args[1][2] + else: + raise TypeError('argument 3 must be str, not %s'%type(args[1][2])) + if type(args[1][3]) == str: + self.text = args[1][3] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[1][3])) def __str__(self): if type(self.msg) is not str: @@ -275,12 +345,15 @@ def __init__(self, *args): argc = len(args) if argc == 0: - self.code = None # default, hopefully + self.code = None self.args = args if argc == 1: self.code = args[0] if argc >= 2: - self.code = args + if type(args) == tuple: + self.code = args + else: + raise TypeError('argument 0 must be tuple, not %s'%type(args)) class EOFError(StandardError): """Read beyond end of file.""" @@ -311,11 +384,28 @@ argc = len(args) self.args = args # modified: always assign args, no error check if argc == 5: - self.encoding = args[0] - self.object = args[1] - self.start = args[2] - self.end = args[3] - self.reason = args[4] + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == str: + self.object = args[1] + else: + raise TypeError('argument 1 must be str, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) # auto-generated code, please check carefully! def __str__(self): @@ -363,29 +453,5 @@ class OverflowError(ArithmeticError): """Result too large to be represented.""" -class UnicodeEncodeError(UnicodeError): - """Unicode encoding error.""" - - # auto-generated code, please check carefully! - def __init__(self, *args): - argc = len(args) - self.args = args # modified: always assign args, no error check - if argc == 5: - self.encoding = args[0] - self.object = args[1] - self.start = args[2] - self.end = args[3] - self.reason = args[4] - - # auto-generated code, please check carefully! - def __str__(self): - # this is a bad hack, please supply an implementation - res = ' '.join([ - 'object=' + str(getattr(self, 'object', None)), - 'end=' + str(getattr(self, 'end', None)), - 'encoding=' + str(getattr(self, 'encoding', None)), - 'args=' + str(getattr(self, 'args', None)), - 'start=' + str(getattr(self, 'start', None)), - 'reason=' + str(getattr(self, 'reason', None)), - ]) - return res +class WindowsError(OSError): + """MS-Windows OS system call failed.""" Deleted: /pypy/branch/pycompiler/lib/inprogress__codecs.py ============================================================================== --- /pypy/branch/pycompiler/lib/inprogress__codecs.py Fri Jul 1 18:30:34 2005 +++ (empty file) @@ -1,407 +0,0 @@ -""" - - _codecs -- Provides access to the codec registry and the builtin - codecs. - - This module should never be imported directly. The standard library - module "codecs" wraps this builtin module for use within Python. - - The codec registry is accessible via: - - register(search_function) -> None - - lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) - - The builtin Unicode codecs use the following interface: - - _encode(Unicode_object[,errors='strict']) -> - (string object, bytes consumed) - - _decode(char_buffer_obj[,errors='strict']) -> - (Unicode object, bytes consumed) - - _encode() interfaces also accept non-Unicode object as - input. The objects are then converted to Unicode using - PyUnicode_FromObject() prior to applying the conversion. - - These s are available: utf_8, unicode_escape, - raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit), - mbcs (on win32). - - -Written by Marc-Andre Lemburg (mal at lemburg.com). - -Copyright (c) Corporation for National Research Initiatives. - -""" -from unicodecodec import * -#/* --- Registry ----------------------------------------------------------- */ -codec_search_path = [] -codec_search_cache = {} - -def codec_register( search_function ): - """register(search_function) - - Register a codec search function. Search functions are expected to take - one argument, the encoding name in all lower case letters, and return - a tuple of functions (encoder, decoder, stream_reader, stream_writer). - """ - - if callable(search_function): - codec_search_path.append(search_function) - -register = codec_register - -def codec_lookup(encoding): - """lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) - Looks up a codec tuple in the Python codec registry and returns - a tuple of functions. - """ - - result = codec_search_cache.get(encoding,None) - if not result: - if len(codec_search_path) == 0: - import encodings - if len(codec_search_path) == 0: - raise LookupError("no codec search functions registered: can't find encoding") - if not isinstance(encoding,str): - raise TypeError("Encoding must be a string") - for search in codec_search_path: - result=search(encoding) - if result : - if not( type(result) == tuple and len(result) == 4): - raise TypeError("codec search functions must return 4-tuples") - else: - codec_search_cache[encoding] = result - return result - if not result: - raise LookupError( "unknown encoding: %s" % encoding) - return result - - -lookup = codec_lookup - -def encode(v, encoding='defaultencoding',errors='strict'): - """encode(obj, [encoding[,errors]]) -> object - - Encodes obj using the codec registered for encoding. encoding defaults - to the default encoding. errors may be given to set a different error - handling scheme. Default is 'strict' meaning that encoding errors raise - a ValueError. Other possible values are 'ignore', 'replace' and - 'xmlcharrefreplace' as well as any other name registered with - codecs.register_error that can handle ValueErrors. - """ - if isinstance(encoding,str): - encoder = lookup(encoding)[0] - if encoder and isinstance(errors,str): - res = encoder(v,errors) - return res[0] - else: - raise TypeError("Errors must be a string") - else: - raise TypeError("Encoding must be a string") - -def decode(obj,encoding='defaultencoding',errors='strict'): - """decode(obj, [encoding[,errors]]) -> object - - Decodes obj using the codec registered for encoding. encoding defaults - to the default encoding. errors may be given to set a different error - handling scheme. Default is 'strict' meaning that encoding errors raise - a ValueError. Other possible values are 'ignore' and 'replace' - as well as any other name registerd with codecs.register_error that is - able to handle ValueErrors. - """ - if isinstance(encoding,str): - decoder = lookup(encoding)[1] - if decoder and isinstance(errors,str): - res = decoder(obj,errors) - if not isinstance(res,tuple) or len(res) != 2: - raise TypeError("encoder must return a tuple (object,integer)") - return res[0] - else: - raise TypeError("Errors must be a string") - else: - raise TypeError("Encoding must be a string") - -def latin_1_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeLatin1(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) -# XXX MBCS codec might involve ctypes ? -def mbcs_decode(): - """None - """ - pass - -def readbuffer_encode( obj,errors='strict'): - """None - """ - res = str(obj) - return res,len(res) - -def escape_encode( obj,errors='strict'): - """None - """ - s = repr(obj) - v = s[1:-1] - return v,len(v) - -def utf_8_decode( data,errors='strict',final=None): - """None - """ - res = PyUnicode_DecodeUTF8Stateful(data, len(data), errors, final) - res = u''.join(res) - return res,len(res) - -def raw_unicode_escape_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeRawUnicodeEscape(data, len(data), errors) - res = u''.join(res) - return res,len(res) - -def utf_7_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF7(data,len(data),errors) - res = u''.join(res) - return res,len(res) - -def unicode_escape_encode( obj,errors='strict'): - """None - """ - res = unicodeescape_string(obj,len(obj),0) - res = ''.join(res) - return res, len(res) - -def latin_1_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeLatin1(data,len(data),errors) - res = u''.join(res) - return res, len(res) - -def utf_16_decode( data,errors='strict',final=None): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors) - res = ''.join(res) - return res, len(res) - -def unicode_escape_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUnicodeEscape(data,len(data),errors) - res = ''.join(res) - return res, len(res) - - -def ascii_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeASCII(data,len(data),errors) - res = u''.join(res) - return res, len(res) - -def charmap_encode(obj,errors='strict',mapping='latin-1'): - """None - """ - res = PyUnicode_EncodeCharmap(obj,len(obj),mapping,errors) - res = ''.join(res) - return res, len(res) - -unicode_bytes = (len(hex(sys.maxunicode))-1)/2 - -def unicode_internal_encode( obj,errors='strict'): - """None - """ - if type(obj) == unicode: - p = [] - t = [ord(x) for x in obj] - for i in t: - for j in xrange(unicode_bytes): - p += chr(i%256) - i >>= 8 - res = ''.join(p) - return res, len(res) - else: - res = "You can do better than this" # XXX make this right - return res,len(res) - -def unicode_internal_decode( unistr,errors='strict'): - """None - """ - if type(unistr) == unicode: - return unistr,len(unistr) - else: - p=[] - i=0 - while i < len(unistr)-unicode_bytes+1: - t = 0 - for j in range(unicode_bytes): - t += ord(unistr[i+j])<<(j*8) - i += unicode_bytes - p += unichr(t) - res = u''.join(p) - return res, len(res) - -def utf_16_ex_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'native') - res = ''.join(res) - return res, len(res) -# XXX escape_decode Check if this is right -def escape_decode(data,errors='strict'): - """None - """ - return data,len(data) - -def charbuffer_encode( obj,errors='strict'): - """None - """ - res = str(obj) - res = ''.join(res) - return res, len(res) - -def charmap_decode( data,errors='strict',mapping=None): - """None - """ - res = PyUnicode_DecodeCharmap(data, len(data), mapping, errors) - res = ''.join(res) - return res, len(res) - - -def utf_7_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF7(obj,len(obj),0,0,errors) - res = ''.join(res) - return res, len(res) - -def mbcs_encode( obj,errors='strict'): - """None - """ - pass -## return (PyUnicode_EncodeMBCS( -## (obj), -## len(obj), -## errors), -## len(obj)) - - -def ascii_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeASCII(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def utf_16_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def raw_unicode_escape_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeRawUnicodeEscape(obj,len(obj)) - res = ''.join(res) - return res, len(res) - -def utf_8_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF8(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def utf_16_le_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'little') - res = ''.join(res) - return res, len(res) - -def utf_16_be_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'big') - res = ''.join(res) - return res, len(res) - -def utf_16_le_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'little') - res = ''.join(res) - return res, len(res) - -def utf_16_be_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'big') - res = ''.join(res) - return res, len(res) - -def strict_errors(exc): - if isinstance(exc,Exception): - raise exc - else: - raise TypeError("codec must pass exception instance") - -def ignore_errors(exc): - if isinstance(exc,(UnicodeEncodeError,UnicodeDecodeError,UnicodeTranslateError)): - return u'',exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -Py_UNICODE_REPLACEMENT_CHARACTER = u"\ufffd" - -def replace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - return u'?'*(exc.end-exc.start),exc.end - elif isinstance(exc,(UnicodeTranslateError,UnicodeDecodeError)): - return Py_UNICODE_REPLACEMENT_CHARACTER*(exc.end-exc.start),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -def xmlcharrefreplace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - res = [] - for ch in exc.object[exc.start:exc.end]: - res += '&#' - res += str(ord(ch)) - res += ';' - return u''.join(res),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) - -def backslashreplace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - p=[] - for c in exc.object[exc.start:exc.end]: - p.append('\\') - oc = ord(c) - if (oc >= 0x00010000): - p.append('U') - p.append("%.8x" % ord(c)) - elif (oc >= 0x100): - p.append('u') - p.append("%.4x" % ord(c)) - else: - p.append('x') - p.append("%.2x" % ord(c)) - return u''.join(p),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) - -register_error("strict",strict_errors) -register_error("ignore",ignore_errors) -register_error("replace",replace_errors) -register_error("xmlcharrefreplace",xmlcharrefreplace_errors) -register_error("backslashreplace",backslashreplace_errors) \ No newline at end of file Deleted: /pypy/branch/pycompiler/lib/unicodecodec.py ============================================================================== --- /pypy/branch/pycompiler/lib/unicodecodec.py Fri Jul 1 18:30:34 2005 +++ (empty file) @@ -1,1196 +0,0 @@ -import sys -""" Python implementation of CPythons builtin unicode codecs. - - Generally the functions in this module take a list of characters an returns - a list of characters. - - For use in the PyPy project""" - - -## indicate whether a UTF-7 character is special i.e. cannot be directly -## encoded: -## 0 - not special -## 1 - special -## 2 - whitespace (optional) -## 3 - RFC2152 Set O (optional) - -utf7_special = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, -] -unicode_latin1=[None]*256 - -codec_error_registry = {} -def lookup_error(errors): - """lookup_error(errors) -> handler - - Return the error handler for the specified error handling name - or raise a LookupError, if no handler exists under this name. - """ - - try: - err_handler = codec_error_registry[errors] - except KeyError: - raise LookupError("unknown error handler name %s"%errors) - return err_handler - -def register_error(errors, handler): - """register_error(errors, handler) - - Register the specified error handler under the name - errors. handler must be a callable object, that - will be called with an exception instance containing - information about the location of the encoding/decoding - error and must return a (replacement, new position) tuple. - """ - if callable(handler): - codec_error_registry[errors] = handler - else: - raise TypeError("handler must be callable") - -def SPECIAL(c, encodeO, encodeWS): - c = ord(c) - return (c>127 or utf7_special[c] == 1) or \ - (encodeWS and (utf7_special[(c)] == 2)) or \ - (encodeO and (utf7_special[(c)] == 3)) -def B64(n): - return ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) -def B64CHAR(c): - return (c.isalnum() or (c) == '+' or (c) == '/') -def UB64(c): - if (c) == '+' : - return 62 - elif (c) == '/': - return 63 - elif (c) >= 'a': - return ord(c) - 71 - elif (c) >= 'A': - return ord(c) - 65 - else: - return ord(c) + 4 - -def ENCODE( ch, bits) : - charvalue = 0 - out = [] -## for c in ch: -## charvalue <<= 16 -## charvalue += ord(c) - while (bits >= 6): - out += B64(ch >> (bits-6)) - bits -= 6 - return out,bits - - -def PyUnicode_DecodeUTF7(s, size, errors): - - starts = s - errmsg = "" - inShift = 0 - bitsleft = 0 - charsleft = 0 - surrogate = 0 - p = [] - errorHandler = None - exc = None - - if (size == 0): - return unicode('') - i = 0 - while i < size: - - ch = s[i] - if (inShift): - if ((ch == '-') or not B64CHAR(ch)): - inShift = 0 - i += 1 - - while (bitsleft >= 16): - outCh = ((charsleft) >> (bitsleft-16)) & 0xffff - bitsleft -= 16 - - if (surrogate): - ## We have already generated an error for the high surrogate - ## so let's not bother seeing if the low surrogate is correct or not - surrogate = 0 - elif (0xDC00 <= (outCh) and (outCh) <= 0xDFFF): - ## This is a surrogate pair. Unfortunately we can't represent - ## it in a 16-bit character - surrogate = 1 - msg = "code pairs are not supported" - out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) - p += out - bitsleft = 0 - break - else: - p += unichr(outCh ) - #p += out - if (bitsleft >= 6): -## /* The shift sequence has a partial character in it. If -## bitsleft < 6 then we could just classify it as padding -## but that is not the case here */ - msg = "partial character in shift sequence" - out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) - -## /* According to RFC2152 the remaining bits should be zero. We -## choose to signal an error/insert a replacement character -## here so indicate the potential of a misencoded character. */ - -## /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ -## if (bitsleft and (charsleft << (sizeof(charsleft) * 8 - bitsleft))): -## raise UnicodeDecodeError, "non-zero padding bits in shift sequence" - if (ch == '-') : - if ((i < size) and (s[i] == '-')) : - p += '-' - inShift = 1 - - elif SPECIAL(ch,0,0) : - raise UnicodeDecodeError,"unexpected special character" - - else: - p += ch - else: - charsleft = (charsleft << 6) | UB64(ch) - bitsleft += 6 - i+=1 -## /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); - elif ( ch == '+' ): - startinpos = i - i+=1 - if (i 0 - else: - out += chr(ord(ch)) - else: - if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)): - out += B64((charsleft) << (6-bitsleft)) - charsleft = 0 - bitsleft = 0 -## /* Characters not in the BASE64 set implicitly unshift the sequence -## so no '-' is required, except if the character is itself a '-' */ - if (B64CHAR(ch) or ch == '-'): - out += '-' - inShift = False - out += chr(ord(ch)) - else: - bitsleft += 16 - charsleft = (((charsleft) << 16) | ord(ch)) - p, bitsleft = ENCODE(charsleft, bitsleft) - out += p -## /* If the next character is special then we dont' need to terminate -## the shift sequence. If the next character is not a BASE64 character -## or '-' then the shift sequence will be terminated implicitly and we -## don't have to insert a '-'. */ - - if (bitsleft == 0): - if (i + 1 < size): - ch2 = s[i+1] - - if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)): - pass - elif (B64CHAR(ch2) or ch2 == '-'): - out += '-' - inShift = False - else: - inShift = False - else: - out += '-' - inShift = False - i+=1 - - if (bitsleft): - out += B64(charsleft << (6-bitsleft) ) - out += '-' - - return out - -unicode_empty=u'' - -##def PyUnicode_Decode(s,size,encoding,errors): -## -## if (encoding == None): -## encoding = PyUnicode_GetDefaultEncoding() -## -#### /* Shortcuts for common default encodings */ -## decoder = encodings.get(encoding,None) -## if decoder: -## return decoder(s,encoding,errors) -#### /* Decode via the codec registry */ -## buf = buffer(s) -## result = PyCodec_Decode(buf, encoding, errors) -## if (not isinstance(result,unicode)): -## raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) -## return result - -def unicodeescape_string(s, size, quotes): - - p = [] - if (quotes) : - p += 'u' - if (s.find('\'')!=-1 and s.find('"')==-1): - p += '"' - else: - p += '\'' - pos = 0 - while (pos < size): - ch = s[pos] - #/* Escape quotes */ - if (quotes and (ch == p[1] or ch == '\\')): - p += '\\' - p += ch - pos += 1 - continue - -#ifdef Py_UNICODE_WIDE - #/* Map 21-bit characters to '\U00xxxxxx' */ - elif (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x'%ord(ch) - pos += 1 - continue -#endif - #/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ - elif (ord(ch) >= 0xD800 and ord(ch) < 0xDC00): - pos += 1 - ch2 = s[pos] - - if (ord(ch2) >= 0xDC00 and ord(ch2) <= 0xDFFF): - ucs = (((ord(ch) & 0x03FF) << 10) | (ord(ch2) & 0x03FF)) + 0x00010000 - p += '\\' - p += 'U' - p += '%08x'%ucs - pos += 1 - continue - - #/* Fall through: isolated surrogates are copied as-is */ - pos -= 1 - - #/* Map 16-bit characters to '\uxxxx' */ - if (ord(ch) >= 256): - p += '\\' - p += 'u' - p += '%04x'%ord(ch) - - #/* Map special whitespace to '\t', \n', '\r' */ - elif (ch == '\t'): - p += '\\' - p += 't' - - elif (ch == '\n'): - p += '\\' - p += 'n' - - elif (ch == '\r'): - p += '\\' - p += 'r' - - #/* Map non-printable US ASCII to '\xhh' */ - elif (ch < ' ' or ch >= 0x7F) : - p += '\\' - p += 'x' - p += '%02x'%ord(ch) - #/* Copy everything else as-is */ - else: - p += chr(ord(ch)) - pos += 1 - if (quotes): - p += p[1] - return p - -def PyUnicode_DecodeASCII(s, size, errors): - -# /* ASCII is equivalent to the first 128 ordinals in Unicode. */ - if (size == 1 and ord(s) < 128) : - return [unichr(ord(s))] - if (size == 0): - return [u''] #unicode('') - p = [] - pos = 0 - while pos < len(s): - c = s[pos] - if ord(c) < 128: - p += unichr(ord(c)) - pos += 1 - else: - - res = unicode_call_errorhandler( - errors, "ascii", "ordinal not in range(128)", - s, pos, pos+1) - p += [unichr(ord(x)) for x in res[0]] - pos = res[1] - return p - -def PyUnicode_EncodeASCII(p,size,errors): - - return unicode_encode_ucs1(p, size, errors, 128) - -def PyUnicode_AsASCIIString(unistr): - - if not type(unistr) == unicode: - raise TypeError - return PyUnicode_EncodeASCII(unicode(unistr), - len(unicode), - None) - -def PyUnicode_DecodeUTF16Stateful(s,size,errors,byteorder='native',consumed=None): - - bo = 0 #/* assume native ordering by default */ - errmsg = "" - - if sys.byteorder == 'little': - ihi = 1 - ilo = 0 - else: - ihi = 0 - ilo = 1 - - if (size == 0): - return [u''] - - #/* Unpack UTF-16 encoded data */ - -## /* Check for BOM marks (U+FEFF) in the input and adjust current -## byte order setting accordingly. In native mode, the leading BOM -## mark is skipped, in all other modes, it is copied to the output -## stream as-is (giving a ZWNBSP character). */ - q = 0 - p = [] - if byteorder == 'native': - if (size >= 2): - bom = (ord(s[ihi]) << 8) | ord(s[ilo]) -#ifdef BYTEORDER_IS_LITTLE_ENDIAN - if sys.byteorder == 'little': - if (bom == 0xFEFF): - q += 2 - bo = -1 - elif bom == 0xFFFE: - q += 2 - bo = 1 - else: - if bom == 0xFEFF: - q += 2 - bo = 1 - elif bom == 0xFFFE: - q += 2 - bo = -1 - elif byteorder == 'little': - bo = -1 - else: - bo = 1 - - if (bo == -1): - #/* force LE */ - ihi = 1 - ilo = 0 - - elif (bo == 1): - #/* force BE */ - ihi = 0 - ilo = 1 - - while (q < len(s)): - - #/* remaining bytes at the end? (size should be even) */ - if (len(s)-q<2): - if (consumed): - break - errmsg = "truncated data" - startinpos = q - endinpos = len(s) - unicode_call_errorhandler() -## /* The remaining input chars are ignored if the callback -## chooses to skip the input */ - - ch = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) - q += 2 - - if (ch < 0xD800 or ch > 0xDFFF): - p += unichr(ch) - continue - - #/* UTF-16 code pair: */ - if (q >= len(s)): - errmsg = "unexpected end of data" - startinpos = q-2 - endinpos = len(s) - unicode_call_errorhandler - - if (0xD800 <= ch and ch <= 0xDBFF): - ch2 = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) - q += 2 - if (0xDC00 <= ch2 and ch2 <= 0xDFFF): - #ifndef Py_UNICODE_WIDE - if sys.maxunicode < 65536: - p += unichr(ch) - p += unichr(ch2) - else: - p += unichr((((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000) - #endif - continue - - else: - errmsg = "illegal UTF-16 surrogate" - startinpos = q-4 - endinpos = startinpos+2 - unicode_call_errorhandler - - errmsg = "illegal encoding" - startinpos = q-2 - endinpos = startinpos+2 - unicode_call_errorhandler - - return p - -def PyUnicode_EncodeUTF16(s,size,errors,byteorder='little'): - -# /* Offsets from p for storing byte pairs in the right order. */ - - def STORECHAR(CH,byteorder): - hi = chr(((CH) >> 8) & 0xff) - lo = chr((CH) & 0xff) - if byteorder == 'little': - return [lo,hi] - else: - return [hi,lo] - - p = [] - bom = sys.byteorder - if (byteorder == 'native'): - - bom = sys.byteorder - p += STORECHAR(0xFEFF,bom) - - if (size == 0): - return "" - - if (byteorder == 'little' ): - bom = 'little' - elif (byteorder == 'big'): - bom = 'big' - - - for c in s: - ch = ord(c) - ch2 = 0 - if (ch >= 0x10000) : - ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF) - ch = 0xD800 | ((ch-0x10000) >> 10) - - p += STORECHAR(ch,bom) - if (ch2): - p +=STORECHAR(ch2,bom) - - return p - - -def PyUnicode_DecodeMBCS(s, size, errors): - pass - -def PyUnicode_EncodeMBCS(p, size, errors): - pass -#### /* If there are no characters, bail now! */ -## if (size==0) -## return "" -## from ctypes import * -## WideCharToMultiByte = windll.kernel32.WideCharToMultiByte -#### /* First get the size of the result */ -## mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, s, 0, None, None); -## if (mbcssize==0) -## raise UnicodeEncodeError, "Windows cannot decode the string %s" %p -### More error handling required (check windows errors and such) -## -### /* Do the conversion */ -#### s = ' '*mbcssize -#### if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)): -#### raise UnicodeEncodeError, "Windows cannot decode the string %s" %p -## return s -def unicode_call_errorhandler(errors, encoding, - reason, input, startinpos, endinpos,decode=True): - - errorHandler = lookup_error(errors) - if decode: - exceptionObject = UnicodeDecodeError(encoding, input, startinpos, endinpos, reason) - else: - exceptionObject = UnicodeEncodeError(encoding, input, startinpos, endinpos, reason) - res = errorHandler(exceptionObject) - if isinstance(res,tuple) and isinstance(res[0],unicode) and isinstance(res[1],int): - newpos = res[1] - if (newpos<0): - newpos = len(input)+newpos - if newpos<0 or newpos>len(input): - raise IndexError( "position %d from error handler out of bounds" % newpos) - return res[0],newpos - else: - raise TypeError("encoding error handler must return (unicode, int) tuple") - -def PyUnicode_DecodeUTF8(s, size, errors): - - return PyUnicode_DecodeUTF8Stateful(s, size, errors, None) - -## /* Map UTF-8 encoded prefix byte to sequence length. zero means -## illegal prefix. see RFC 2279 for details */ -utf8_code_length = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 -] - -def PyUnicode_DecodeUTF8Stateful(s,size,errors,consumed): - - if (size == 0): - if (consumed): - consumed = 0 - return u'' - - p = [] - pos = 0 - while pos < size: - ch = s[pos] - if ord(ch) < 0x80: - p += ch - pos += 1 - continue - - n = utf8_code_length[ord(ch)] - startinpos = pos - if (startinpos + n > size): - if (consumed): - break - else: - errmsg = "unexpected end of data" - endinpos = size - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - if n == 0: - errmsg = "unexpected code byte" - endinpos = startinpos+1 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - elif n == 1: - errmsg = "internal error" - endinpos = startinpos+1 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - elif n == 2: - if ((ord(s[pos+1]) & 0xc0) != 0x80): - errmsg = "invalid data" - endinpos = startinpos+2 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos]) & 0x1f) << 6) + (ord(s[pos+1]) & 0x3f) - if c<0x80: - errmsg = "illegal encoding" - endinpos = startinpos+2 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - p += unichr(c) - pos += n - #break - elif n == 3: - if ((ord(s[pos+1]) & 0xc0) != 0x80 or - (ord(s[pos+2]) & 0xc0) != 0x80): - errmsg = "invalid data" - endinpos = startinpos+3 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos]) & 0x0f) << 12) + \ - ((ord(s[pos+1]) & 0x3f) << 6) +\ - (ord(s[pos+2]) & 0x3f) - -## /* Note: UTF-8 encodings of surrogates are considered -## legal UTF-8 sequences; -## -## XXX For wide builds (UCS-4) we should probably try -## to recombine the surrogates into a single code -## unit. -## */ - if c < 0x0800: - errmsg = "illegal encoding" - endinpos = startinpos+3 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - p += unichr(c) - pos += n - elif n == 4: -## case 4: - if ((ord(s[pos+1]) & 0xc0) != 0x80 or - (ord(s[pos+2]) & 0xc0) != 0x80 or - (ord(s[pos+3]) & 0xc0) != 0x80): - - errmsg = "invalid data" - startinpos = pos - endinpos = startinpos+4 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos+0]) & 0x7) << 18) + ((ord(s[pos+1]) & 0x3f) << 12) +\ - ((ord(s[pos+2]) & 0x3f) << 6) + (ord(s[pos+3]) & 0x3f) - #/* validate and convert to UTF-16 */ - if ((c < 0x10000) or (c > 0x10ffff)): - #/* minimum value allowed for 4 byte encoding */ - #/* maximum value allowed for UTF-16 */ - - errmsg = "illegal encoding" - startinpos = pos - endinpos = startinpos+4 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: -#ifdef Py_UNICODE_WIDE - if c> 10)) - #/* low surrogate = bottom 10 bits added to DC00 */ - p += unichr(0xDC00 + (c & 0x03FF)) - pos += n - else: -## default: -## /* Other sizes are only needed for UCS-4 */ - errmsg = "unsupported Unicode code range" - startinpos = pos - endinpos = startinpos+n - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - - #continue - - if (consumed): - consumed = pos - return p - -def PyUnicode_EncodeUTF8(s,size,errors): - - #assert(s != None) - assert(size >= 0) - p = [] - i = 0 - while i> 6))) - p += chr((0x80 | (ord(ch) & 0x3f))) - else: -## /* Encode UCS2 Unicode ordinals */ - if (ord(ch) < 0x10000): -## /* Special case: check for high surrogate */ - if (0xD800 <=ord(ch) and ord(ch) <= 0xDBFF and i != size) : - ch2 = s[i] -## /* Check for low surrogate and combine the two to -## form a UCS4 value */ - if (0xDC00 <= ord(ch2) and ord(ch2) <= 0xDFFF) : - ch3 = ((ord(ch) - 0xD800) << 10 | (ord(ch2) - 0xDC00)) + 0x10000 - i+=1 - p.extend(encodeUCS4(ch3)) - continue -## /* Fall through: handles isolated high surrogates */ - p += (chr((0xe0 | (ord(ch) >> 12)))) - p += (chr((0x80 | ((ord(ch) >> 6) & 0x3f)))) - p += (chr((0x80 | (ord(ch) & 0x3f)))) - continue - return p - -def encodeUCS4(ch): -## /* Encode UCS4 Unicode ordinals */ - p=[] - p += (chr((0xf0 | (ch >> 18)))) - p += (chr((0x80 | ((ch >> 12) & 0x3f)))) - p += (chr((0x80 | ((ch >> 6) & 0x3f)))) - p += (chr((0x80 | (ch & 0x3f)))) - return p - -#/* --- Latin-1 Codec ------------------------------------------------------ */ - -def PyUnicode_DecodeLatin1(s, size, errors): - #/* Latin-1 is equivalent to the first 256 ordinals in Unicode. */ -## if (size == 1): -## return [PyUnicode_FromUnicode(s, 1)] - pos = 0 - p = [] - while (pos < size): - p += unichr(ord(s[pos])) - pos += 1 - return p - -def unicode_encode_ucs1(p,size,errors,limit): - - if limit == 256: - reason = "ordinal not in range(256)" - encoding = "latin-1" - else: - reason = "ordinal not in range(128)" - encoding = "ascii" - - if (size == 0): - return [''] - res = [] - pos=0 - while pos < len(p): - #for ch in p: - ch = p[pos] - - if ord(ch) < limit: - res += chr(ord(ch)) - pos += 1 - else: - #/* startpos for collecting unencodable chars */ - collstart = pos - collend = pos+1 - while collend < len(p) and ord(p[collend]) >= limit: - collend += 1 - x = unicode_call_errorhandler(errors,encoding,reason,p,collstart,collend,False) - res += str(x[0]) - pos = x[1] - - return res - -def PyUnicode_EncodeLatin1(p,size,errors): - res=unicode_encode_ucs1(p, size, errors, 256) - return res - -hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10,16)] -def hexescape(s,pos,digits,message,errors): - chr = 0 - p = [] - if (pos+digits>len(s)): - message = "end of string in escape sequence" - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,len(s)) - p += x[0] - pos = x[1] - else: - try: - chr = int(s[pos:pos+digits],16) - except ValueError: - endinpos = pos - while s[endinpos] in hexdigits: - endinpos +=1 - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, - endinpos+1) - p += x[0] - pos = x[1] - #/* when we get here, chr is a 32-bit unicode character */ - else: - if chr <= sys.maxunicode: - p += [unichr(chr)] - pos += digits - - elif (chr <= 0x10ffff): - chr -= 0x10000L - p += unichr(0xD800 + (chr >> 10)) - p += unichr(0xDC00 + (chr & 0x03FF)) - pos += digits - else: - message = "illegal Unicode character" - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, - pos+1) - p += x[0] - pos = x[1] - res = p - return res,pos - -def PyUnicode_DecodeUnicodeEscape(s, size, errors): - - if (size == 0): - return u'' - - p = [] - pos = 0 - while (pos < size): -## /* Non-escape characters are interpreted as Unicode ordinals */ - if (s[pos] != '\\') : - p += s[pos] - pos += 1 - continue -## /* \ - Escapes */ - else: - pos +=1 - if pos>=len(s): - errmessage = "\\ at end of string" - unicode_call_errorhandler(errors,"unicodeescape",errmessage,s,pos-1,size) - ch = s[pos] - pos += 1 - ## /* \x escapes */ - #if ch == '\n': break; - if ch == '\\': p += '\\' - elif ch == '\'': p += '\'' - elif ch == '\"': p += '\"' - elif ch == 'b': p += '\b' - elif ch == 'f': p += '\014' #/* FF */ - elif ch == 't': p += '\t' - elif ch == 'n': p += '\n' - elif ch == 'r': - p += '\r' - - elif ch == 'v': p += '\013' #break; /* VT */ - elif ch == 'a': p += '\007' # break; /* BEL, not classic C */ - - ## /* \OOO (octal) escapes */ - elif ch in [ '0','1', '2', '3','4', '5', '6','7']: - x = ord(ch) - ord('0') - ch = s[pos] - if ('0' <= ch and ch <= '7'): - x = (x<<3) + ord(ch) - ord('0') - ch = s[pos+1] - if ('0' <= ch and ch <= '7'): - x = (x<<3) + ord(ch) - ord('0') - pos += 2 - - p += unichr(x) - ## /* hex escapes */ - ## /* \xXX */ - elif ch == 'x': - digits = 2 - message = "truncated \\xXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] - - # /* \uXXXX */ - elif ch == 'u': - digits = 4 - message = "truncated \\uXXXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] - - # /* \UXXXXXXXX */ - elif ch == 'U': - digits = 8 - message = "truncated \\UXXXXXXXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] -## /* \N{name} */ - elif ch == 'N': - message = "malformed \\N character escape" - #pos += 1 - try: - import unicodedata - except ImportError: - message = "\\N escapes not supported (can't load unicodedata module)" - unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,size) - if (s[pos] == '{'): - look = pos+1 - #/* look for the closing brace */ - while (s[look] != '}' and look < size): - look += 1 - if (look > pos+1 and look < size and s[look] == '}'): - #/* found a name. look it up in the unicode database */ - message = "unknown Unicode character name" - look += 1 - try: - chr = unicodedata.lookup(s[pos:look]) - #x = hexescape(chr,pos+1,8,message,errors) - except KeyError: - x=unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,look) - else: - x = hexescape(s,pos+1,look-pos,message,errors) - p += x[0] - pos = x[1] - else: - if (pos > size): - message = "\\ at end of string" - handler = lookup_error(errors) - x = handler(UnicodeDecodeError("unicodeescape",s,pos, - size,message)) - p += x[0] - pos = x[1] - else: - p += '\\' - p += s[pos] - return p - -def PyUnicode_EncodeRawUnicodeEscape(s,size): - - if (size == 0): - return '' - - p = [] - for ch in s: -# /* Map 32-bit characters to '\Uxxxxxxxx' */ - if (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x'%(ord(ch)) - elif (ord(ch) >= 256) : -# /* Map 16-bit characters to '\uxxxx' */ - p += '\\' - p += 'u' - p += '%04x'%(ord(ch)) -# /* Copy everything else as-is */ - else: - p += chr(ord(ch)) - - #p += '\0' - return p - -def charmapencode_output(c,mapping): - - - rep = mapping[c] - if isinstance(rep,(int,long)): - if rep<256: - return chr(rep) - else: - raise TypeError("character mapping must be in range(256)") - elif isinstance(rep,str): - return rep - elif rep == None: - raise KeyError("character maps to ") - else: - raise TypeError("character mapping must return integer, None or str") - -def PyUnicode_EncodeCharmap(p,size,mapping='latin-1',errors='strict'): - -## /* the following variable is used for caching string comparisons -## * -1=not initialized, 0=unknown, 1=strict, 2=replace, -## * 3=ignore, 4=xmlcharrefreplace */ - -# /* Default to Latin-1 */ - if mapping == 'latin-1': - return PyUnicode_EncodeLatin1(p, size, errors) - if (size == 0): - return '' - inpos = 0 - res = [] - while (inpos",p,inpos,inpos+1,False) - try: - res += [charmapencode_output(ord(y),mapping) for y in x[0]] - except KeyError: - raise UnicodeEncodeError("charmap",p,inpos,inpos+1, - "character maps to ") -## except TypeError,err: -## x = unicode_call_errorhandler(errors,"charmap", -## err,p,inpos,inpos+1,False) -## try: -## res += [charmapencode_output(ord(y),mapping) for y in x[0]] -## except KeyError: -## raise UnicodeEncodeError("charmap",p,inpos,inpos+1, -## "character maps to ") -## - #/* done with this character => adjust input position */ - inpos+=1 - return res - -def PyUnicode_DecodeCharmap(s, size, mapping, errors): - -## /* Default to Latin-1 */ - if (mapping == None): - return PyUnicode_DecodeLatin1(s, size, errors) - - if (size == 0): - return u'' - p = [] - inpos = 0 - while (inpos< len(s)): - - #/* Get mapping (char ordinal -> integer, Unicode char or None) */ - ch = s[inpos] - try: - x = mapping[ord(ch)] - if isinstance(x,int): - if x<65536: - p += unichr(x) - else: - raise TypeError("character mapping must be in range(65536)") - elif isinstance(x,unicode): - p += x - elif not x: - raise KeyError - else: - raise TypeError - except KeyError: - x = unicode_call_errorhandler(errors,"charmap", - "character maps to ",s,inpos,inpos+1) - p += x[0] -## except TypeError: -## x = unicode_call_errorhandler(errors,"charmap", -## "character mapping must return integer, None or unicode", -## s,inpos,inpos+1) -## p += x[0] - inpos +=1 - return p - -def PyUnicode_DecodeRawUnicodeEscape(s, size,errors): - - if (size == 0): - return u'' - pos = 0 - p = [] - while (pos < len(s)): - ch = s[pos] - #/* Non-escape characters are interpreted as Unicode ordinals */ - if (ch != '\\'): - p += unichr(ord(ch)) - pos += 1 - continue - startinpos = pos - #pos += 1 -## /* \u-escapes are only interpreted iff the number of leading -## backslashes is odd */ - bs = pos - while pos < size: - if (s[pos] != '\\'): - break - p += unichr(ord(s[pos])) - pos += 1 - - if (((pos - bs) & 1) == 0 or - pos >= size or - (s[pos] != 'u' and s[pos] != 'U')) : - p += s[pos] - pos += 1 - continue - - p.pop(-1) - if s[pos] == 'u': - count = 4 - else: - count = 8 - pos += 1 - - #/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ - - i = 0 - x = 0 - try: - x = int(s[pos:pos+count],16) - except ValueError: - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "truncated \\uXXXX", - s, size, pos, pos+count) - p += res[0] - pos = res[1] - else: - #ifndef Py_UNICODE_WIDE - if sys.maxunicode > 0xffff: - if (x > 0x10000): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = i = res[1] - p += res[0] - i += 1 - else: - if (x > 0x10000): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = i = res[1] - p += res[0] - - #endif - else: - p += unichr(x) - pos += count - - return p \ No newline at end of file Modified: pypy/branch/pycompiler/module/recparser/automata.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/automata.py (original) +++ pypy/branch/pycompiler/module/recparser/automata.py Fri Jul 1 18:30:34 2005 @@ -38,9 +38,9 @@ # arcMap, accept = self.states[crntState] arcMap = self.states[crntState] accept = self.accepts[crntState] - if arcMap.has_key(item): + if item in arcMap: crntState = arcMap[item] - elif arcMap.has_key(DEFAULT): + elif DEFAULT in arcMap: crntState = arcMap[DEFAULT] elif accept: return i Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/ebnfparse.py (original) +++ pypy/branch/pycompiler/module/recparser/ebnfparse.py Fri Jul 1 18:30:34 2005 @@ -123,8 +123,8 @@ def visit_alternative( self, node ): items = [ node.nodes[0].visit(self) ] - items+= node.nodes[1].visit(self) - if len(items)==1 and items[0].name.startswith(':'): + items += node.nodes[1].visit(self) + if len(items) == 1 and items[0].name.startswith(':'): return items[0] alt = Alternative( self.new_name(), items ) return self.new_item( alt ) @@ -143,10 +143,6 @@ def visit_sequence_cont( self, node ): """Returns a list of sequences (possibly empty)""" return [n.visit(self) for n in node.nodes] -## L = [] -## for n in node.nodes: -## L.append( n.visit(self) ) -## return L def visit_seq_cont_list(self, node): return node.nodes[1].visit(self) Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Fri Jul 1 18:30:34 2005 @@ -77,7 +77,7 @@ class BaseGrammarBuilder(object): """Base/default class for a builder""" - def __init__( self, rules=None, debug=0): + def __init__(self, rules=None, debug=0): self.rules = rules or {} # a dictionary of grammar rules for debug/reference self.debug = debug self.stack = [] @@ -139,7 +139,7 @@ self._is_root = False self.first_set = [] self.first_set_complete = False - self._processing = False + # self._processing = False self._trace = False def is_root(self): Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Fri Jul 1 18:30:34 2005 @@ -73,7 +73,7 @@ class TokenError(Exception): """Raised when EOF is found prematuerly""" def __init__(self, msg, strstart, token_stack): - Exception.__init__(self, msg) + # Exception.__init__(self, msg) self.strstart = strstart self.token_stack = token_stack @@ -296,9 +296,9 @@ class PythonSource(TokenSource): """This source uses Jonathan's tokenizer""" - def __init__(self, inpstring): + def __init__(self, strings): # TokenSource.__init__(self) - tokens, encoding = generate_tokens(inpstring.splitlines(True)) + tokens, encoding = generate_tokens(strings) # inpstring.splitlines(True)) self.token_stack = tokens self.encoding = encoding self._current_line = '' # the current line (as a string) Modified: pypy/branch/pycompiler/module/recparser/pythonutil.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonutil.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonutil.py Fri Jul 1 18:30:34 2005 @@ -1,4 +1,5 @@ -__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", "ast_eval_input" ] +__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", + "ast_eval_input" ] import grammar import pythonparse @@ -22,7 +23,7 @@ pyf = file(filename) text = pyf.read() pyf.close() - builder = TupleBuilder( PYTHON_PARSER.rules, lineno=False) + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder) nested_tuples = builder.stack[-1] if hasattr(builder, '_source_encoding'): @@ -30,6 +31,17 @@ return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) return nested_tuples +def annotateme(text): + strings = text.split('\n') + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) + pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder) +## nested_tuples = builder.stack[-1] +## if hasattr(builder, '_source_encoding'): +## # XXX: maybe the parser could fix that instead ? +## return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) +## return nested_tuples + return 0 + def ast_single_input( text ): builder = TupleBuilder( PYTHON_PARSER.rules ) pythonparse.parse_python_source( text, PYTHON_PARSER, "single_input", builder ) Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/tuplebuilder.py (original) +++ pypy/branch/pycompiler/module/recparser/tuplebuilder.py Fri Jul 1 18:30:34 2005 @@ -2,8 +2,6 @@ from grammar import BaseGrammarBuilder from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET - -class def _expand_nodes(nodes): expanded = [] for n in nodes: Modified: pypy/branch/pycompiler/module/sys/state.py ============================================================================== --- pypy/branch/pycompiler/module/sys/state.py (original) +++ pypy/branch/pycompiler/module/sys/state.py Fri Jul 1 18:30:34 2005 @@ -76,11 +76,17 @@ def get(space): return space.fromcache(State) -def pypy_getudir(space): +def _pypy_getudir(space): """NOT_RPYTHON""" from pypy.tool.udir import udir return space.wrap(str(udir)) -pypy_getudir._annspecialcase_ = "override:ignore" +_pypy_getudir._annspecialcase_ = "override:ignore" + +# we need the inderaction because this function will live in a dictionary with other +# RPYTHON functions and share call sites with them. Better it not be a special-case +# directly. +def pypy_getudir(space): + return _pypy_getudir(space) def getdefaultencoding(space): return space.wrap(sys.getdefaultencoding()) Deleted: /pypy/branch/pycompiler/objspace/dummy.py ============================================================================== --- /pypy/branch/pycompiler/objspace/dummy.py Fri Jul 1 18:30:34 2005 +++ (empty file) @@ -1,146 +0,0 @@ -from pypy.interpreter.baseobjspace import ObjSpace, W_Root, BaseWrappable -from pypy.interpreter.module import Module -from pypy.interpreter.error import OperationError - -from pypy.tool.cache import Cache - -class W_Obj(W_Root): - - def is_true(self): - return True - - def str_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def int_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def float_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def unwrap(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - -class W_Str(W_Obj): - def __init__(self, s): - self.s = s - - def is_true(self): - return self.s != "" - - def str_w(self, space): - return self.s - - def unwrap(self, space): - return self.s - -class W_Int(W_Obj): - def __init__(self, i): - self.i = i - - def is_true(self): - return self.i != 0 - - def int_w(self, space): - return self.i - - def unwrap(self, space): - return self.i - -class W_None(W_Obj): - - def unwrap(self, space): - return None - -class W_Special(W_Obj): - def __init__(self, spec): - self.spec = spec - -class BuiltinModule(Module): - def __init__(self, space): - Module.__init__(self, space, space.wrap('__builtin__'), space.wrap({})) - - def pick_builtin(self, w_globals): - return self - -class DummyObjSpace(ObjSpace): - - def __init__(self): - """NOT_RPYTHON""" - self.builtin = BuiltinModule(self) - - self.sys = Module(self, self.wrap('sys'), self.wrap({})) - self.sys.recursionlimit = 1000 - - self.w_None = W_None() - self.w_NotImplemented = W_Special(NotImplemented) - self.w_Ellpisis = W_Special(Ellipsis) - self.w_False = self.wrap(0) - self.w_True = self.wrap(1) - self.w_tuple = W_Special(tuple) - self.w_type = W_Special(type) - self.w_str = W_Special(str) - - for en in ObjSpace.ExceptionTable: - setattr(self, 'w_'+en, self.wrap(en)) - - self._gatewaycache = Cache() - - for n, symbol, arity, ign in ObjSpace.MethodTable+[('newdict',"",1,[]), ('newlist',"",1,[]), - ('newtuple',"",1,[]), ('newslice',"",3,[]), ]: - source = ("""if 1: - def %s(self, %s): - return W_Root() -""" % (n, ', '.join(["w_a%d" % i for i in range(arity)]))) - #print source - exec source - - del n, symbol, arity, ign, i - - def wrap(self, obj): - if obj is None: - return self.w_None - if isinstance(obj, str): - return W_Str(obj) - if isinstance(obj, int): - return W_Int(obj) - return W_Root() - wrap._specialize_ = "argtypes" - - def call_args(self, w_obj, args): - return W_Root() - - def is_true(self, w_obj): - if isinstance(w_obj, W_Obj): - return w_obj.is_true() - return True - - def str_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.str_w(self) - - def int_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.int_w(self) - - def float_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.float_w(self) - - def unwrap(self, w_obj): - if isinstance(w_obj, BaseWrappable): - return w_obj - return w_obj.unwrap() - - def _freeze_(self): - return True - -if __name__ == '__main__': - dummy_space = DummyObjSpace() - print dummy_space.eval("a+b",dummy_space.wrap({'a': 1,'b': 2}),dummy_space.wrap({})) Modified: pypy/branch/pycompiler/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/pycompiler/objspace/flow/flowcontext.py (original) +++ pypy/branch/pycompiler/objspace/flow/flowcontext.py Fri Jul 1 18:30:34 2005 @@ -20,8 +20,9 @@ class SpamBlock(Block): - - __slots__ = "dead framestate fillcolor".split() + # make slots optional, for debugging + if hasattr(Block, '__slots__'): + __slots__ = "dead framestate fillcolor".split() def __init__(self, framestate): Block.__init__(self, framestate.getvariables()) @@ -36,8 +37,9 @@ class EggBlock(Block): - - __slots__ = "prevblock booloutcome last_exception fillcolor".split() + # make slots optional, for debugging + if hasattr(Block, '__slots__'): + __slots__ = "prevblock booloutcome last_exception fillcolor".split() def __init__(self, inputargs, prevblock, booloutcome): Block.__init__(self, inputargs) Modified: pypy/branch/pycompiler/objspace/flow/model.py ============================================================================== --- pypy/branch/pycompiler/objspace/flow/model.py (original) +++ pypy/branch/pycompiler/objspace/flow/model.py Fri Jul 1 18:30:34 2005 @@ -31,7 +31,6 @@ __metaclass__ = type class FunctionGraph(object): - __slots__ = """func source name startblock returnblock exceptblock""".split() def __init__(self, name, startblock, return_var=None): self.name = name # function name (possibly mangled already) @@ -304,9 +303,9 @@ class Atom: def __init__(self, name): - self.name = name + self.__name__ = name # make save_global happy def __repr__(self): - return self.name + return self.__name__ last_exception = Atom('last_exception') # if Block().exitswitch == Constant(last_exception), it means that we are @@ -331,11 +330,6 @@ import inspect # for getmro class traverse: - edgedef = { - FunctionGraph : ('startblock',), - Block : ('exits',), - Link : ('target',), - } def __init__(self, visitor, functiongraph): """ send the visitor over all (reachable) nodes. @@ -343,6 +337,7 @@ or otherwise is callable itself. """ self.visitor = visitor + self.visitor_cache = {} self.seen = {} self.visit(functiongraph) @@ -352,26 +347,32 @@ # do the visit cls = node.__class__ - for subclass in inspect.getmro(cls): - consume = getattr(self.visitor, "visit_" + subclass.__name__, None) - if consume: - break - else: - consume = getattr(self.visitor, 'visit', self.visitor) + try: + consume = self.visitor_cache[cls] + except KeyError: + for subclass in inspect.getmro(cls): + consume = getattr(self.visitor, "visit_" + subclass.__name__, None) + if consume: + break + else: + consume = getattr(self.visitor, 'visit', self.visitor) + + assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor) + + self.visitor_cache[cls] = consume - assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor) self.seen[id(node)] = consume(node) # recurse - for dispclass, attrs in self.edgedef.items(): - for subclass in inspect.getmro(cls): - if subclass == dispclass: - for attr in attrs: - for obj in flattenobj(getattr(node, attr)): - self.visit(obj) - return - - raise ValueError, "could not dispatch %r" % cls + if isinstance(node, Block): + for obj in node.exits: + self.visit(obj) + elif isinstance(node, Link): + self.visit(node.target) + elif isinstance(node, FunctionGraph): + self.visit(node.startblock) + else: + raise ValueError, "could not dispatch %r" % cls def flatten(funcgraph): l = [] Modified: pypy/branch/pycompiler/objspace/flow/objspace.py ============================================================================== --- pypy/branch/pycompiler/objspace/flow/objspace.py (original) +++ pypy/branch/pycompiler/objspace/flow/objspace.py Fri Jul 1 18:30:34 2005 @@ -465,11 +465,12 @@ inplace_add inplace_sub inplace_mul inplace_truediv inplace_floordiv inplace_div inplace_mod inplace_divmod inplace_pow""", FloatingPointError) -_add_except_ovf("""neg abs invert add sub mul truediv - floordiv div mod divmod pow lshift +_add_exceptions("""truediv divmod inplace_add inplace_sub inplace_mul inplace_truediv inplace_floordiv inplace_div inplace_mod inplace_pow - inplace_lshift""") + inplace_lshift""", OverflowError) # without a _ovf version +_add_except_ovf("""neg abs add sub mul + floordiv div mod pow lshift""") # with a _ovf version del _add_exceptions, _add_except_ovf def extract_cell_content(c): Modified: pypy/branch/pycompiler/objspace/flow/operation.py ============================================================================== --- pypy/branch/pycompiler/objspace/flow/operation.py (original) +++ pypy/branch/pycompiler/objspace/flow/operation.py Fri Jul 1 18:30:34 2005 @@ -5,6 +5,7 @@ from pypy.interpreter.baseobjspace import ObjSpace import operator, types, __future__ from pypy.tool.sourcetools import compile2 +from pypy.rpython.rarithmetic import ovfcheck, ovfcheck_lshift FunctionByName = {} # dict {"operation_name": } OperationName = {} # dict {: "operation_name"} @@ -100,12 +101,44 @@ def userdel(x): x.__del__() +def neg_ovf(x): + return ovfcheck(-x) + +def abs_ovf(x): + return ovfcheck(abs(x)) + +def add_ovf(x, y): + return ovfcheck(x + y) + +def sub_ovf(x, y): + return ovfcheck(x - y) + +def mul_ovf(x, y): + return ovfcheck(x * y) + +def floordiv_ovf(x, y): + return ovfcheck(operator.floordiv(x, y)) + +def div_ovf(x, y): + return ovfcheck(operator.div(x, y)) + +def mod_ovf(x, y): + return ovfcheck(x % y) + +def pow_ovf(*two_or_three_args): + return ovfcheck(pow(*two_or_three_args)) + +def lshift_ovf(x, y): + return ovfcheck_lshift(x, y) + # ____________________________________________________________ # The following table can list several times the same operation name, # if multiple built-in functions correspond to it. The first one should # be picked, though, as the best built-in for the given operation name. # Lines ('name', operator.name) are added automatically. + +# INTERNAL ONLY, use the dicts declared at the top of the file. Table = [ ('id', id), ('type', new_style_type), @@ -120,6 +153,8 @@ ('delattr', delattr), ('nonzero', bool), ('nonzero', operator.truth), + ('is_true', bool), + ('is_true', operator.truth), ('abs' , abs), ('hex', hex), ('oct', oct), @@ -150,6 +185,17 @@ ('set', set), ('delete', delete), ('userdel', userdel), + # --- operations added by graph transformations --- + ('neg_ovf', neg_ovf), + ('abs_ovf', abs_ovf), + ('add_ovf', add_ovf), + ('sub_ovf', sub_ovf), + ('mul_ovf', mul_ovf), + ('floordiv_ovf', floordiv_ovf), + ('div_ovf', div_ovf), + ('mod_ovf', mod_ovf), + ('pow_ovf', pow_ovf), + ('lshift_ovf', lshift_ovf), ] def setup(): @@ -164,11 +210,12 @@ for name, func in Table: if name not in FunctionByName: FunctionByName[name] = func - assert func not in OperationName - OperationName[func] = name + if func not in OperationName: + OperationName[func] = name # check that the result is complete for line in ObjSpace.MethodTable: name = line[0] Arity[name] = line[2] assert name in FunctionByName setup() +del Table # INTERNAL ONLY, use the dicts declared at the top of the file Modified: pypy/branch/pycompiler/objspace/std/floatobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/floatobject.py (original) +++ pypy/branch/pycompiler/objspace/std/floatobject.py Fri Jul 1 18:30:34 2005 @@ -241,7 +241,7 @@ def nonzero__Float(space, w_float): return space.newbool(w_float.floatval != 0.0) -######## coersion must be done later +######## coercion must be done later later = """ def float_coerce(space, w_float): if w_float.__class__ == W_FloatObject: Modified: pypy/branch/pycompiler/objspace/std/floattype.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/floattype.py (original) +++ pypy/branch/pycompiler/objspace/std/floattype.py Fri Jul 1 18:30:34 2005 @@ -1,21 +1,22 @@ from pypy.objspace.std.stdtypedef import * from pypy.interpreter.error import OperationError -from pypy.objspace.std.strutil import ParseStringError +from pypy.objspace.std.strutil import string_to_float, ParseStringError def descr__new__(space, w_floattype, w_x=0.0): from pypy.objspace.std.floatobject import W_FloatObject w_value = w_x # 'x' is the keyword argument name in CPython if space.is_true(space.isinstance(w_value, space.w_str)): + strvalue = space.str_w(w_value) try: - value = float(space.str_w(w_value)) - except ValueError, e: + value = string_to_float(strvalue) + except ParseStringError, e: raise OperationError(space.w_ValueError, - space.wrap(str(e))) + space.wrap(e.msg)) elif space.is_true(space.isinstance(w_value, space.w_unicode)): + from unicodeobject import unicode_to_decimal_w + strvalue = unicode_to_decimal_w(space, w_value) try: - # XXX can produce unwrapped long - from unicodeobject import unicode_to_decimal_w - value = float(unicode_to_decimal_w(space, w_value)) + value = string_to_float(strvalue) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/branch/pycompiler/objspace/std/inttype.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/inttype.py (original) +++ pypy/branch/pycompiler/objspace/std/inttype.py Fri Jul 1 18:30:34 2005 @@ -22,7 +22,7 @@ value = w_value.intval elif space.is_true(space.isinstance(w_value, space.w_str)): try: - value = string_to_int(space, space.str_w(w_value)) + value = string_to_int(space.str_w(w_value)) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -32,7 +32,7 @@ from unicodeobject import unicode_to_decimal_w string = unicode_to_decimal_w(space, w_value) try: - value = string_to_int(space, string) + value = string_to_int(string) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -68,7 +68,7 @@ space.wrap("int() can't convert non-string " "with explicit base")) try: - value = string_to_int(space, s, base) + value = string_to_int(s, base) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/branch/pycompiler/objspace/std/listobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/listobject.py (original) +++ pypy/branch/pycompiler/objspace/std/listobject.py Fri Jul 1 18:30:34 2005 @@ -597,20 +597,23 @@ assert isinstance(b, KeyContainer) return CustomCompareSort.lt(self, a.w_key, b.w_key) -SortClass = { - (False, False): SimpleSort, - (True, False): CustomCompareSort, - (False, True) : CustomKeySort, - (True, True) : CustomKeyCompareSort, - } - def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse): has_cmp = not space.is_w(w_cmp, space.w_None) has_key = not space.is_w(w_keyfunc, space.w_None) has_reverse = space.is_true(w_reverse) # create and setup a TimSort instance - sorterclass = SortClass[has_cmp, has_key] + if has_cmp: + if has_key: + sorterclass = CustomKeyCompareSort + else: + sorterclass = CustomCompareSort + else: + if has_key: + sorterclass = CustomKeySort + else: + sorterclass = SimpleSort + sorter = sorterclass(w_list.ob_item, w_list.ob_size) sorter.space = space sorter.w_cmp = w_cmp Modified: pypy/branch/pycompiler/objspace/std/model.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/model.py (original) +++ pypy/branch/pycompiler/objspace/std/model.py Fri Jul 1 18:30:34 2005 @@ -136,7 +136,6 @@ specialnames = [operatorsymbol] self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__'] self.extras = extras - self.unbound_versions = {} # transform '+' => 'add' etc. for line in ObjSpace.MethodTable: realname, symbolname = line[:2] Modified: pypy/branch/pycompiler/objspace/std/mro.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/mro.py (original) +++ pypy/branch/pycompiler/objspace/std/mro.py Fri Jul 1 18:30:34 2005 @@ -37,7 +37,13 @@ cycle.append(candidate) nextblockinglist = blockinglist(candidate, orderlists) candidate = nextblockinglist[0] - del cycle[:cycle.index(candidate)] + # avoid the only use of list.index in the PyPy code base: + i = 0 + for c in cycle: + if c == candidate: + break + i += 1 + del cycle[:i] cycle.append(candidate) cycle.reverse() names = [cls.__name__ for cls in cycle] Modified: pypy/branch/pycompiler/objspace/std/objspace.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/objspace.py (original) +++ pypy/branch/pycompiler/objspace/std/objspace.py Fri Jul 1 18:30:34 2005 @@ -66,7 +66,6 @@ self.w_Ellipsis = self.wrap(Ellipsis(self)) # types - self.types_w = {} for typedef in self.model.pythontypes: w_type = self.gettypeobject(typedef) setattr(self, 'w_' + typedef.name, w_type) @@ -180,7 +179,7 @@ return ec def gettypeobject(self, typedef): - # types_w maps each StdTypeDef instance to its + # stdtypedef.TypeCache maps each StdTypeDef instance to its # unique-for-this-space W_TypeObject instance return self.fromcache(stdtypedef.TypeCache).getorbuild(typedef) Modified: pypy/branch/pycompiler/objspace/std/stringobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/stringobject.py (original) +++ pypy/branch/pycompiler/objspace/std/stringobject.py Fri Jul 1 18:30:34 2005 @@ -348,10 +348,10 @@ if len(fillchar) != 1: raise OperationError(space.w_TypeError, space.wrap("rjust() argument 2 must be a single character")) - d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self = d * fillchar + u_self return space.wrap(u_self) @@ -368,6 +368,7 @@ d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self += d * fillchar return space.wrap(u_self) @@ -585,6 +586,7 @@ d = u_arg - len(u_self) if d>0: offset = d//2 + fillchar = fillchar[0] # annotator hint: it's a single character u_centered = offset * fillchar + u_self + (d - offset) * fillchar else: u_centered = u_self Modified: pypy/branch/pycompiler/objspace/std/strutil.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/strutil.py (original) +++ pypy/branch/pycompiler/objspace/std/strutil.py Fri Jul 1 18:30:34 2005 @@ -86,7 +86,7 @@ else: return -1 -def string_to_int(space, s, base=10): +def string_to_int(s, base=10): """Utility to converts a string to an integer (or possibly a long). If base is 0, the proper base is guessed based on the leading characters of 's'. Raises ParseStringError in case of error. @@ -134,3 +134,110 @@ return w_result w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) +def break_up_float(s): + i = 0 + + sign = '' + before_point = '' + after_point = '' + exponent = '' + + if s[i] in '+-': + sign = s[i] + i += 1 + + while i < len(s) and s[i] in '0123456789': + before_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] == '.': + i += 1 + while i < len(s) and s[i] in '0123456789': + after_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] not in 'eE': + raise ParseStringError("invalid string literal for float()") + + i += 1 + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + if s[i] in '-+': + exponent += s[i] + i += 1 + + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + while i < len(s) and s[i] in '0123456789': + exponent += s[i] + i += 1 + + if i != len(s): + raise ParseStringError("invalid string literal for float()") + + return sign, before_point, after_point, exponent + + +def string_to_float(s): + s = strip_spaces(s) + + if not s: + raise ParseStringError("empty string for float()") + + sign, before_point, after_point, exponent = break_up_float(s) + + if not before_point and not after_point: + raise ParseStringError("invalid string literal for float()") + + r = 0.0 + i = len(before_point) - 1 + j = 0 + while i >= 0: + d = float(ord(before_point[i]) - ord('0')) + r += d * (10.0 ** j) + i -= 1 + j += 1 + + i = 0 + while i < len(after_point): + d = float(ord(after_point[i]) - ord('0')) + r += d * (10.0 ** (-i-1)) + i += 1 + + if exponent: + # XXX this fails for float('0.' + '0'*100 + '1e400') + # XXX later! + try: + e = string_to_int(exponent) + except ParseStringOverflowError: + if exponent[0] == '-': + e = -400 + else: + e = 400 + if e > 0: + if e >= 400: + r = 1e200 * 1e200 + else: + while e > 0: + r *= 10.0 + e -= 1 + else: + if e <= -400: + r = 0.0 + else: + while e < 0: + r /= 10.0 + e += 1 + + if sign == '-': + r = -r + + return r Modified: pypy/branch/pycompiler/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/pycompiler/objspace/std/test/test_floatobject.py Fri Jul 1 18:30:34 2005 @@ -56,9 +56,11 @@ def test_float_string(self): assert 42 == float("42") + assert 42.25 == float("42.25") def test_float_unicode(self): - assert 42.3 == float(unicode("42.3")) + # u00A0 and u2000 are some kind of spaces + assert 42.75 == float(unichr(0x00A0)+unicode("42.75")+unichr(0x2000)) def test_float_long(self): assert 42.0 == float(42L) Modified: pypy/branch/pycompiler/objspace/std/test/test_strutil.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/test/test_strutil.py (original) +++ pypy/branch/pycompiler/objspace/std/test/test_strutil.py Fri Jul 1 18:30:34 2005 @@ -1,6 +1,9 @@ import autopath +import py, random from pypy.objspace.std.strutil import * +import py + objspacename = 'std' class TestStrUtil: @@ -24,7 +27,7 @@ (' -123456789 ', -123456789), ] for s, expected in cases: - assert string_to_int(space, s) == expected + assert string_to_int(s) == expected assert string_to_w_long(space, s).longval() == expected def test_string_to_int_base(self): @@ -54,12 +57,12 @@ ('0X', 16, 0), # " " ] for s, base, expected in cases: - assert string_to_int(space, s, base) == expected - assert string_to_int(space, '+'+s, base) == expected - assert string_to_int(space, '-'+s, base) == -expected - assert string_to_int(space, s+'\n', base) == expected - assert string_to_int(space, ' +'+s, base) == expected - assert string_to_int(space, '-'+s+' ', base) == -expected + assert string_to_int(s, base) == expected + assert string_to_int('+'+s, base) == expected + assert string_to_int('-'+s, base) == -expected + assert string_to_int(s+'\n', base) == expected + assert string_to_int(' +'+s, base) == expected + assert string_to_int('-'+s+' ', base) == -expected def test_string_to_int_error(self): space = self.space @@ -78,16 +81,16 @@ '@', ] for s in cases: - raises(ParseStringError, string_to_int, space, s) - raises(ParseStringError, string_to_int, space, ' '+s) - raises(ParseStringError, string_to_int, space, s+' ') - raises(ParseStringError, string_to_int, space, '+'+s) - raises(ParseStringError, string_to_int, space, '-'+s) + raises(ParseStringError, string_to_int, s) + raises(ParseStringError, string_to_int, ' '+s) + raises(ParseStringError, string_to_int, s+' ') + raises(ParseStringError, string_to_int, '+'+s) + raises(ParseStringError, string_to_int, '-'+s) def test_string_to_int_overflow(self): import sys space = self.space - raises(ParseStringOverflowError, string_to_int, space, + raises(ParseStringOverflowError, string_to_int, str(sys.maxint*17)) def test_string_to_int_base_error(self): @@ -107,11 +110,11 @@ ('12.3', 16), ] for s, base in cases: - raises(ParseStringError, string_to_int, space, s, base) - raises(ParseStringError, string_to_int, space, ' '+s, base) - raises(ParseStringError, string_to_int, space, s+' ', base) - raises(ParseStringError, string_to_int, space, '+'+s, base) - raises(ParseStringError, string_to_int, space, '-'+s, base) + raises(ParseStringError, string_to_int, s, base) + raises(ParseStringError, string_to_int, ' '+s, base) + raises(ParseStringError, string_to_int, s+' ', base) + raises(ParseStringError, string_to_int, '+'+s, base) + raises(ParseStringError, string_to_int, '-'+s, base) def test_string_to_w_long(self): space = self.space @@ -124,3 +127,72 @@ assert string_to_w_long(space, '123L', 22).longval() == 10648 + 968 + 66 + 21 assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3 assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319 + + +def test_break_up_float(): + assert break_up_float('1') == ('', '1', '', '') + assert break_up_float('+1') == ('+', '1', '', '') + assert break_up_float('-1') == ('-', '1', '', '') + + assert break_up_float('.5') == ('', '', '5', '') + + assert break_up_float('1.2e3') == ('', '1', '2', '3') + assert break_up_float('1.2e+3') == ('', '1', '2', '+3') + assert break_up_float('1.2e-3') == ('', '1', '2', '-3') + + # some that will get thrown out on return: + assert break_up_float('.') == ('', '', '', '') + assert break_up_float('+') == ('+', '', '', '') + assert break_up_float('-') == ('-', '', '', '') + assert break_up_float('e1') == ('', '', '', '1') + + py.test.raises(ParseStringError, break_up_float, 'e') + + +def test_string_to_float(): + assert string_to_float('0') == 0.0 + assert string_to_float('1') == 1.0 + assert string_to_float('-1.5') == -1.5 + assert string_to_float('1.5E2') == 150.0 + assert string_to_float('2.5E-1') == 0.25 + assert string_to_float('1e1111111111111') == float('1e1111111111111') + assert string_to_float('1e-1111111111111') == float('1e-1111111111111') + assert string_to_float('-1e1111111111111') == float('-1e1111111111111') + assert string_to_float('-1e-1111111111111') == float('-1e-1111111111111') + assert string_to_float('1e111111111111111111111') == float('1e111111111111111111111') + assert string_to_float('1e-111111111111111111111') == float('1e-111111111111111111111') + assert string_to_float('-1e111111111111111111111') == float('-1e111111111111111111111') + assert string_to_float('-1e-111111111111111111111') == float('-1e-111111111111111111111') + + valid_parts = [['', ' ', ' \f\n\r\t\v'], + ['', '+', '-'], + ['00', '90', '.5', '2.4', '3.', '0.07', + '12.3489749871982471987198371293717398256187563298638726' + '2187362820947193247129871083561249818451804287437824015' + '013816418758104762348932657836583048761487632840726386'], + ['', 'e0', 'E+1', 'E-01', 'E42'], + ['', ' ', ' \f\n\r\t\v'], + ] + invalid_parts = [['#'], + ['++', '+-', '-+', '--'], + ['', '1.2.3', '.', '5..6'], + ['E+', 'E-', 'e', 'e++', 'E++2'], + ['#'], + ] + for part0 in valid_parts[0]: + for part1 in valid_parts[1]: + for part2 in valid_parts[2]: + for part3 in valid_parts[3]: + for part4 in valid_parts[4]: + s = part0+part1+part2+part3+part4 + assert (abs(string_to_float(s) - float(s)) <= + 1E-13 * abs(float(s))) + + for j in range(len(invalid_parts)): + for invalid in invalid_parts[j]: + for i in range(20): + parts = [random.choice(lst) for lst in valid_parts] + parts[j] = invalid + s = ''.join(parts) + print repr(s) + py.test.raises(ParseStringError, string_to_float, s) Modified: pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py (original) +++ pypy/branch/pycompiler/objspace/std/test/test_unicodestring.py Fri Jul 1 18:30:34 2005 @@ -72,4 +72,4 @@ assert int(u'12345') == 12345 def test_float_from_unicode(self): - assert float(u'123.456e89') == 123.456e89 + assert float(u'123.456e89') == float('123.456e89') Modified: pypy/branch/pycompiler/objspace/std/tupleobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/tupleobject.py (original) +++ pypy/branch/pycompiler/objspace/std/tupleobject.py Fri Jul 1 18:30:34 2005 @@ -86,7 +86,9 @@ items2 = w_tuple2.wrappeditems if len(items1) != len(items2): return space.w_False - for item1, item2 in zip(items1, items2): + for i in range(len(items1)): + item1 = items1[i] + item2 = items2[i] if not space.is_true(space.eq(item1, item2)): return space.w_False return space.w_True Modified: pypy/branch/pycompiler/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/unicodeobject.py (original) +++ pypy/branch/pycompiler/objspace/std/unicodeobject.py Fri Jul 1 18:30:34 2005 @@ -4,7 +4,6 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject from pypy.objspace.std import slicetype -from pypy.objspace.std.strutil import string_to_int, string_to_long, ParseStringError from pypy.rpython.rarithmetic import intmask from pypy.module.unicodedata import unicodedb @@ -782,7 +781,7 @@ else: retval, length = encoder(unistr, errors) if not isinstance(retval,str): - raise TypeError("encoder did not return an unicode object (type=%s)" % + raise TypeError("encoder did not return a string object (type=%s)" % type(retval).__name__) return retval Modified: pypy/branch/pycompiler/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/pycompiler/objspace/std/unicodetype.py (original) +++ pypy/branch/pycompiler/objspace/std/unicodetype.py Fri Jul 1 18:30:34 2005 @@ -46,9 +46,6 @@ import codecs, sys def unicode_from_encoded_object(obj, encoding, errors): - # Fix later for buffer - if type(obj).__name__ == 'buffer': - obj = obj.buf if encoding is None: encoding = sys.getdefaultencoding() decoder = codecs.getdecoder(encoding) @@ -105,7 +102,7 @@ # help the annotator! also the ._value depends on W_UnicodeObject layout assert isinstance(w_value, W_UnicodeObject) w_newobj = space.allocate_instance(W_UnicodeObject, w_unicodetype) - w_newobj.__init__(space, w_value._value) + W_UnicodeObject.__init__(w_newobj, space, w_value._value) return w_newobj # ____________________________________________________________ Modified: pypy/branch/pycompiler/rpython/annlowlevel.py ============================================================================== --- pypy/branch/pycompiler/rpython/annlowlevel.py (original) +++ pypy/branch/pycompiler/rpython/annlowlevel.py Fri Jul 1 18:30:34 2005 @@ -4,7 +4,7 @@ from pypy.annotation import model as annmodel from pypy.annotation.specialize import decide_callable -from pypy.translator.annrpython import BasicAnnotatorPolicy +from pypy.annotation.policy import BasicAnnotatorPolicy def not_const(s_obj): # xxx move it somewhere else if s_obj.is_constant(): @@ -26,7 +26,7 @@ def __hash__(self): return hash(self.val) def __str__(self): - return getattr(self.val, '__name__', self.val) + 'Const' + return getattr(self.val, '__name__', repr(self.val)) + 'Const' class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy): @@ -56,7 +56,7 @@ (ll_function, args), key = decide_callable(annotator.bookkeeper, None, ll_function, args, mono=True, unpacked=True) args_s, kwds_s = args.unpack() assert not kwds_s - oldblocks = annotator.annotated.keys() + oldblocks = annotator.annotated.copy() s = annotator.build_types(ll_function, args_s) newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks] # invoke annotation simplifications for the new blocks Modified: pypy/branch/pycompiler/rpython/exceptiondata.py ============================================================================== --- pypy/branch/pycompiler/rpython/exceptiondata.py (original) +++ pypy/branch/pycompiler/rpython/exceptiondata.py Fri Jul 1 18:30:34 2005 @@ -1,27 +1,44 @@ from pypy.annotation import model as annmodel from pypy.rpython import rclass from pypy.rpython.annlowlevel import annotate_lowlevel_helper -from pypy.rpython.lltype import * +from pypy.rpython.lltype import Array, malloc, Ptr, PyObject, pyobjectptr +from pypy.rpython.lltype import FuncType, functionptr, Signed class ExceptionData: """Public information for the code generators to help with exceptions.""" + # the exceptions that can be implicitely raised by some operations + standardexceptions = [TypeError, OverflowError, ValueError, + ZeroDivisionError, MemoryError] + def __init__(self, rtyper): + self.make_standard_exceptions(rtyper) # (NB. rclass identifies 'Exception' and 'object') r_type = rclass.getclassrepr(rtyper, None) r_instance = rclass.getinstancerepr(rtyper, None) r_type.setup() r_instance.setup() + self.r_exception_type = r_type + self.r_exception_value = r_instance self.lltype_of_exception_type = r_type.lowleveltype self.lltype_of_exception_value = r_instance.lowleveltype + + def make_helpers(self, rtyper): # create helper functions self.ll_exception_match = self.make_exception_matcher(rtyper) self.ll_type_of_exc_inst = self.make_type_of_exc_inst(rtyper) self.ll_pyexcclass2exc = self.make_pyexcclass2exc(rtyper) + def make_standard_exceptions(self, rtyper): + bk = rtyper.annotator.bookkeeper + for cls in self.standardexceptions: + classdef = bk.getclassdef(cls) + rclass.getclassrepr(rtyper, classdef).setup() + + def make_exception_matcher(self, rtyper): # ll_exception_matcher(real_exception_vtable, match_exception_vtable) s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type) @@ -72,7 +89,7 @@ for cls in table.keys(): add_class(cls) assert table == {} - print sortedtable + #print sortedtable A = Array(('pycls', Ptr(PyObject)), ('excinst', self.lltype_of_exception_value)) Modified: pypy/branch/pycompiler/rpython/lltype.py ============================================================================== --- pypy/branch/pycompiler/rpython/lltype.py (original) +++ pypy/branch/pycompiler/rpython/lltype.py Fri Jul 1 18:30:34 2005 @@ -1,4 +1,4 @@ -import weakref +import weakref, operator import py from pypy.rpython.rarithmetic import r_uint from pypy.tool.uid import Hashable @@ -22,6 +22,8 @@ del seeing[seeingkey] return safe +safe_equal = saferecursive(operator.eq, True) + class frozendict(dict): def __hash__(self): @@ -32,8 +34,8 @@ class LowLevelType(object): def __eq__(self, other): - return self.__class__ is other.__class__ and self.__dict__ == other.__dict__ - __eq__ = saferecursive(__eq__, True) + return self.__class__ is other.__class__ and ( + self is other or safe_equal(self.__dict__, other.__dict__)) def __ne__(self, other): return not (self == other) @@ -55,6 +57,14 @@ finally: TLS.nested_hash_level -= 1 + # due to this dynamic hash value, we must forbid + # pickling, until we have an algorithm for that + def __reduce_ex__(self, *args): + raise Exception('%s insts cannot be pickled, yet. __hash__ is not' + ' constant during reconstruction.' % + self.__class__.__name__) + __reduce__ = __reduce_ex__ + def __repr__(self): return '<%s>' % (self,) @@ -151,7 +161,21 @@ return _struct(self, n) class GcStruct(Struct): - pass + _runtime_type_info = None + + def _attach_runtime_type_info_funcptr(self, funcptr): + if self._runtime_type_info is None: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj + if funcptr is not None: + T = typeOf(funcptr) + if (not isinstance(T, Ptr) or + not isinstance(T.TO, FuncType) or + len(T.TO.ARGS) != 1 or + T.TO.RESULT != Ptr(RuntimeTypeInfo) or + castable(T.TO.ARGS[0], Ptr(self)) < 0): + raise TypeError("expected a runtime type info function " + "implementation, got: %s" % funcptr) + self._runtime_type_info.query_funcptr = funcptr class Array(ContainerType): __name__ = 'array' @@ -213,9 +237,20 @@ def _container_example(self): def ex(*args): - return self.RESULT._example() + return self.RESULT._defl() return _func(self, _callable=ex) +class OpaqueType(ContainerType): + + def __init__(self, tag): + self.tag = tag + self.__name__ = tag + + def __str__(self): + return "%s (opaque)" % self.tag + +RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo") + class PyObjectType(ContainerType): __name__ = 'PyObject' def __str__(self): @@ -264,6 +299,7 @@ Char = Primitive("Char", '\x00') Bool = Primitive("Bool", False) Void = Primitive("Void", None) +UniChar = Primitive("UniChar", u'\x00') class Ptr(LowLevelType): @@ -278,17 +314,8 @@ def _needsgc(self): return self.TO._gcstatus() - def _str_flags(self): - if self._needsgc(): - return 'gc' - else: - return '' - - def _str_flavor(self): - return 'ptr(%s)' % self._str_flags() - def __str__(self): - return '%s to %s' % (self._str_flavor(), self.TO) + return '* %s' % (self.TO, ) def _defl(self, parent=None, parentindex=None): return _ptr(self, None) @@ -313,6 +340,9 @@ if isinstance(val, str): assert len(val) == 1 return Char + if isinstance(val, unicode): + assert len(val) == 1 + return UniChar if val is None: return Void # maybe return val._TYPE @@ -426,9 +456,14 @@ def __ne__(self, other): return not (self == other) + def __hash__(self): + raise TypeError("pointer objects are not hashable") + def __nonzero__(self): return self._obj is not None + # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, + # use _obj if necessary instead ! def _setobj(self, pointing_to, immortal=False): if pointing_to is None: obj0 = None @@ -520,7 +555,7 @@ return '<%s>' % (self,) def __str__(self): - return '%s to %s' % (self._TYPE._str_flavor(), self._obj) + return '* %s' % (self._obj, ) def __call__(self, *args): if isinstance(self._T, FuncType): @@ -650,7 +685,36 @@ return '<%s>' % (self,) def __str__(self): - return "func %s" % self._name + return "fn %s" % self._name + + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + return hash(frozendict(self.__dict__)) + +class _opaque(object): + def __init__(self, TYPE, **attrs): + self._TYPE = TYPE + self._name = "?" + self.__dict__.update(attrs) + + def _parentstructure(self): + return None + + def _check(self): + pass + + def __repr__(self): + return '<%s>' % (self,) + + def __str__(self): + return "%s %s" % (self._TYPE.__name__, self._name) + class _pyobject(Hashable): _TYPE = PyObject @@ -681,14 +745,59 @@ def functionptr(TYPE, name, **attrs): if not isinstance(TYPE, FuncType): - raise TypeError, "function() for FuncTypes only" + raise TypeError, "functionptr() for FuncTypes only" + try: + hash(tuple(attrs.items())) + except TypeError: + raise TypeError("'%r' must be hashable"%attrs) o = _func(TYPE, _name=name, **attrs) return _ptr(Ptr(TYPE), o) def nullptr(T): return Ptr(T)._defl() +def opaqueptr(TYPE, name, **attrs): + if not isinstance(TYPE, OpaqueType): + raise TypeError, "opaqueptr() for OpaqueTypes only" + o = _opaque(TYPE, _name=name, **attrs) + return _ptr(Ptr(TYPE), o, immortal=attrs.get('immortal', True)) + def pyobjectptr(obj): o = _pyobject(obj) return _ptr(Ptr(PyObject), o) +def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None): + if not isinstance(GCSTRUCT, GcStruct): + raise TypeError, "expected a GcStruct: %s" % GCSTRUCT + GCSTRUCT._attach_runtime_type_info_funcptr(funcptr) + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) + +def getRuntimeTypeInfo(GCSTRUCT): + if not isinstance(GCSTRUCT, GcStruct): + raise TypeError, "expected a GcStruct: %s" % GCSTRUCT + if GCSTRUCT._runtime_type_info is None: + raise ValueError, "no attached runtime type info for %s" % GCSTRUCT + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) + +def runtime_type_info(p): + T = typeOf(p) + if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct): + raise TypeError, "runtime_type_info on non-GcStruct pointer: %s" % p + top_parent = struct = p._obj + while True: + parent = top_parent._parentstructure() + if parent is None: + break + top_parent = parent + result = getRuntimeTypeInfo(top_parent._TYPE) + static_info = getRuntimeTypeInfo(T.TO) + query_funcptr = getattr(static_info._obj, 'query_funcptr', None) + if query_funcptr is not None: + T = typeOf(query_funcptr).TO.ARGS[0] + result2 = query_funcptr(cast_pointer(T, p)) + if result != result2: + raise RuntimeError, ("runtime type-info function for %s:\n" + " returned: %s,\n" + "should have been: %s" % (p, result2, result)) + return result + Modified: pypy/branch/pycompiler/rpython/normalizecalls.py ============================================================================== --- pypy/branch/pycompiler/rpython/normalizecalls.py (original) +++ pypy/branch/pycompiler/rpython/normalizecalls.py Fri Jul 1 18:30:34 2005 @@ -1,15 +1,17 @@ +import types from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, checkgraph -from pypy.annotation.model import * +from pypy.annotation import model as annmodel from pypy.tool.sourcetools import has_varargs from pypy.rpython.rmodel import TyperError def normalize_function_signatures(annotator): - # make sure that all functions called in a group have exactly - # the same signature, by hacking their flow graphs if needed - callables = annotator.getpbccallables() + """Make sure that all functions called in a group have exactly + the same signature, by hacking their flow graphs if needed. + """ call_families = annotator.getpbccallfamilies() + # for methods, we create or complete a corresponding function-only # family with call patterns that have the extra 'self' argument for family in call_families.infos(): @@ -29,10 +31,51 @@ argcount = pattern[0] pattern = (argcount+1,) + pattern[1:] func_family.patterns[pattern] = True + + # for classes that appear in families, unify their __init__ as well. + for family in call_families.infos(): + prevkey = None + for _, klass in family.objects: + if isinstance(klass, (type, types.ClassType)): + try: + initfunc = klass.__init__.im_func + except AttributeError: + continue + if prevkey is None: + prevkey = (None, initfunc) + else: + call_families.union((None, initfunc), prevkey) + + # for bound method objects, make sure the im_func shows up too. + for family in call_families.infos(): + first = family.objects.keys()[0][1] + for _, callable in family.objects: + if isinstance(callable, types.MethodType): + # for bound methods families for now just accept and check that + # they all refer to the same function + if not isinstance(first, types.MethodType): + raise TyperError("call family with both bound methods and " + "%r" % (first,)) + if first.im_func is not callable.im_func: + raise TyperError("call family of bound methods: should all " + "refer to the same function") + # create a family for the common im_func + if isinstance(first, types.MethodType): + _, _, func_family = call_families.find((None, first.im_func)) + for pattern in family.patterns: + argcount = pattern[0] + pattern = (argcount+1,) + pattern[1:] + func_family.patterns[pattern] = True + # find the most general signature of each family for family in call_families.infos(): + # collect functions in this family, ignoring: + # - methods: taken care of above + # - bound methods: their im_func will also show up + # - classes: their __init__ unbound methods are also families functions = [func for classdef, func in family.objects - if classdef is None] # ignore methods now + if classdef is None and + not isinstance(func, (type, types.ClassType, types.MethodType))] if len(functions) > 1: # otherwise, nothing to do if len(family.patterns) > 1: raise TyperError("don't support multiple call patterns " @@ -40,61 +83,125 @@ functions)) pattern, = family.patterns shape_cnt, shape_keys, shape_star, shape_stst = pattern - assert not shape_keys, "XXX not implemented" assert not shape_star, "XXX not implemented" assert not shape_stst, "XXX not implemented" + # for the first 'shape_cnt' arguments we need to generalize to # a common type - generalizedargs = [] graph_bindings = {} - default_values = {} + graph_argorders = {} for func in functions: assert not has_varargs(func), "XXX not implemented" - graph = annotator.translator.getflowgraph(func) + try: + graph = annotator.translator.flowgraphs[func] + except KeyError: + raise TyperError("the skipped %r must not show up in a " + "call family" % (func,)) graph_bindings[graph] = [annotator.binding(v) for v in graph.getargs()] - for i in range(shape_cnt): + argorder = range(shape_cnt) + for key in shape_keys: + i = list(func.func_code.co_varnames).index(key) + assert i not in argorder + argorder.append(i) + graph_argorders[graph] = argorder + + call_nbargs = shape_cnt + len(shape_keys) + generalizedargs = [] + for i in range(call_nbargs): args_s = [] - for bindings in graph_bindings.values(): - args_s.append(bindings[i]) - s_value = unionof(*args_s) + for graph, bindings in graph_bindings.items(): + j = graph_argorders[graph][i] + args_s.append(bindings[j]) + s_value = annmodel.unionof(*args_s) generalizedargs.append(s_value) + result_s = [annotator.binding(graph.getreturnvar()) + for graph in graph_bindings] + generalizedresult = annmodel.unionof(*result_s) + for func in functions: graph = annotator.translator.getflowgraph(func) bindings = graph_bindings[graph] - if generalizedargs != bindings: #NB. bindings can also be longer + argorder = graph_argorders[graph] + need_reordering = (argorder != range(call_nbargs)) + need_conversion = (generalizedargs != bindings) + if need_reordering or need_conversion: oldblock = graph.startblock - vlist = [] - for i in range(len(generalizedargs)): - v = Variable(graph.getargs()[i]) - annotator.setbinding(v, generalizedargs[i]) - vlist.append(v) - newblock = Block(vlist) - # add the defaults as constants + inlist = [] + for s_value, j in zip(generalizedargs, argorder): + v = Variable(graph.getargs()[j]) + annotator.setbinding(v, s_value) + inlist.append(v) + newblock = Block(inlist) + # prepare the output args of newblock: + # 1. collect the positional arguments + outlist = inlist[:shape_cnt] + # 2. add defaults and keywords defaults = func.func_defaults or () - for i in range(len(generalizedargs), len(bindings)): + for j in range(shape_cnt, len(bindings)): try: - default = defaults[i-len(bindings)] - except IndexError: - raise TyperError("call pattern has %d arguments, " - "but %r takes at least %d " - "arguments" % ( - len(generalizedargs), func, - len(bindings) - len(defaults))) - vlist.append(Constant(default)) - newblock.closeblock(Link(vlist, oldblock)) + i = argorder.index(j) + v = inlist[i] + except ValueError: + try: + default = defaults[j-len(bindings)] + except IndexError: + raise TyperError( + "call pattern has %d positional arguments, " + "but %r takes at least %d arguments" % ( + shape_cnt, func, + len(bindings) - len(defaults))) + v = Constant(default) + outlist.append(v) + newblock.closeblock(Link(outlist, oldblock)) oldblock.isstartblock = False newblock.isstartblock = True graph.startblock = newblock # finished checkgraph(graph) annotator.annotated[newblock] = annotator.annotated[oldblock] - # XXX convert the return value too + graph.normalized_for_calls = True + # convert the return value too + annotator.setbinding(graph.getreturnvar(), generalizedresult) + + +def specialize_pbcs_by_memotables(annotator): + memo_tables = annotator.bookkeeper.memo_tables + access_sets = annotator.getpbcaccesssets() + for memo_table in memo_tables: + arglist_s = memo_table.arglist_s + assert len(arglist_s) == 1, "XXX implement >1 arguments" + arg1 = arglist_s[0] + assert isinstance(arg1, annmodel.SomePBC) + + if None in arg1.prebuiltinstances: + raise TyperError("unsupported: memo call with an argument that can be None") + pbcs = arg1.prebuiltinstances.keys() + _, _, access_set = access_sets.find(pbcs[0]) + # enforce a structure where we can uniformly access + # our memofield later + for pbc in pbcs[1:]: + _, _, access_set = access_sets.union(pbcs[0], pbc) + + # we can have multiple memo_tables per PBC + i = 0 + while 1: + fieldname = "memofield_%d" % i + if fieldname in access_set.attrs: + i += 1 + continue + memo_table.fieldname = fieldname + break + access_set.attrs[fieldname] = memo_table.s_result + for pbc in pbcs: + value = memo_table.table[(pbc,)] + access_set.values[(pbc, fieldname)] = value def perform_normalizations(annotator): annotator.frozen += 1 try: normalize_function_signatures(annotator) + specialize_pbcs_by_memotables(annotator) finally: annotator.frozen -= 1 Modified: pypy/branch/pycompiler/rpython/rarithmetic.py ============================================================================== --- pypy/branch/pycompiler/rpython/rarithmetic.py (original) +++ pypy/branch/pycompiler/rpython/rarithmetic.py Fri Jul 1 18:30:34 2005 @@ -159,7 +159,7 @@ def intmask(n): if isinstance(n, int): - return n + return int(n) # possibly bool->int if isinstance(n, r_uint): n = long(n) n &= LONG_MASK Modified: pypy/branch/pycompiler/rpython/rbool.py ============================================================================== --- pypy/branch/pycompiler/rpython/rbool.py (original) +++ pypy/branch/pycompiler/rpython/rbool.py Fri Jul 1 18:30:34 2005 @@ -1,7 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr +from pypy.rpython.robject import PyObjRepr, pyobj_repr debug = False @@ -22,6 +23,9 @@ raise TyperError("not a bool: %r" % (value,)) return value + def get_ll_eq_function(self): + return None + def rtype_is_true(_, hop): vlist = hop.inputargs(Bool) return vlist[0] @@ -46,3 +50,16 @@ if debug: print 'explicit cast_bool_to_int' return llops.genop('cast_bool_to_int', [v], resulttype=Signed) return NotImplemented + +class __extend__(pairtype(PyObjRepr, BoolRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Bool: + return llops.gencapicall('PyObject_IsTrue', [v], resulttype=Bool) + return NotImplemented + +class __extend__(pairtype(BoolRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Bool: + return llops.gencapicall('PyBool_FromLong', [v], + resulttype = pyobj_repr) + return NotImplemented Modified: pypy/branch/pycompiler/rpython/rbuiltin.py ============================================================================== --- pypy/branch/pycompiler/rpython/rbuiltin.py (original) +++ pypy/branch/pycompiler/rpython/rbuiltin.py Fri Jul 1 18:30:34 2005 @@ -2,11 +2,13 @@ from pypy.annotation import model as annmodel from pypy.rpython import lltype from pypy.rpython import rarithmetic -from pypy.rpython.lltype import Void, Signed from pypy.rpython.rtyper import TyperError -from pypy.rpython.rrange import rtype_builtin_range -from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython import rptr +from pypy.rpython.robject import pyobj_repr +from pypy.rpython.rfloat import float_repr, FloatRepr +from pypy.rpython import rclass class __extend__(annmodel.SomeBuiltin): @@ -22,14 +24,16 @@ return BuiltinMethodRepr(rtyper.getrepr(self.s_self), self.methodname) def rtyper_makekey(self): - key = (getattr(self, 'const', None), self.methodname) - if self.s_self is not None: - key += (self.s_self.rtyper_makekey(),) - return key + if self.s_self is None: + # built-in function case + return getattr(self, 'const', None) + else: + # built-in method case + return (self.methodname, self.s_self.rtyper_makekey()) class BuiltinFunctionRepr(Repr): - lowleveltype = Void + lowleveltype = lltype.Void def __init__(self, builtinfunc): self.builtinfunc = builtinfunc @@ -40,8 +44,9 @@ except KeyError: raise TyperError("don't know about built-in function %r" % ( self.builtinfunc,)) - hop.r_s_popfirstarg() - return bltintyper(hop) + hop2 = hop.copy() + hop2.r_s_popfirstarg() + return bltintyper(hop2) class BuiltinMethodRepr(Repr): @@ -61,9 +66,10 @@ raise TyperError("missing %s.%s" % ( self.self_repr.__class__.__name__, name)) # hack based on the fact that 'lowleveltype == self_repr.lowleveltype' - assert hop.args_r[0] is self - hop.args_r[0] = self.self_repr - return bltintyper(hop) + hop2 = hop.copy() + assert hop2.args_r[0] is self + hop2.args_r[0] = self.self_repr + return bltintyper(hop2) ##class __extend__(pairtype(SomeBuiltin, SomeObject)): @@ -89,12 +95,76 @@ assert hop.nb_args == 1 return hop.args_r[0].rtype_float(hop) +def rtype_builtin_chr(hop): + assert hop.nb_args == 1 + return hop.args_r[0].rtype_chr(hop) + +def rtype_builtin_unichr(hop): + assert hop.nb_args == 1 + return hop.args_r[0].rtype_unichr(hop) + +def rtype_builtin_list(hop): + return hop.args_r[0].rtype_bltn_list(hop) + +def rtype_builtin_isinstance(hop): + instance_repr = rclass.getinstancerepr(hop.rtyper, None) + class_repr = rclass.get_type_repr(hop.rtyper) + + v_obj, v_cls = hop.inputargs(instance_repr, class_repr) + + v_objcls = hop.gendirectcall(rclass.ll_type, v_obj) + return hop.gendirectcall(rclass.ll_issubclass, v_objcls, v_cls) + + #def rtype_builtin_range(hop): see rrange.py +#def rtype_builtin_xrange(hop): see rrange.py + def rtype_intmask(hop): - vlist = hop.inputargs(Signed) + vlist = hop.inputargs(lltype.Signed) return vlist[0] +def rtype_r_uint(hop): + vlist = hop.inputargs(lltype.Unsigned) + return vlist[0] + +def rtype_builtin_min(hop): + rint1, rint2 = hop.args_r + assert isinstance(rint1, IntegerRepr) + assert isinstance(rint2, IntegerRepr) + assert rint1.lowleveltype == rint2.lowleveltype + v1, v2 = hop.inputargs(rint1, rint2) + return hop.gendirectcall(ll_min, v1, v2) + +def ll_min(i1, i2): + if i1 < i2: + return i1 + return i2 + +def rtype_builtin_max(hop): + rint1, rint2 = hop.args_r + assert isinstance(rint1, IntegerRepr) + assert isinstance(rint2, IntegerRepr) + assert rint1.lowleveltype == rint2.lowleveltype + v1, v2 = hop.inputargs(rint1, rint2) + return hop.gendirectcall(ll_max, v1, v2) + +def ll_max(i1, i2): + if i1 > i2: + return i1 + return i2 + +def rtype_math_floor(hop): + vlist = hop.inputargs(lltype.Float) + return hop.genop('float_floor', vlist, resulttype=lltype.Float) + +def rtype_math_fmod(hop): + vlist = hop.inputargs(lltype.Float, lltype.Float) + return hop.genop('float_fmod', vlist, resulttype=lltype.Float) + +import math +##def ll_floor(f1): +## return float(int((f1) # collect all functions import __builtin__ @@ -103,33 +173,70 @@ if name.startswith('rtype_builtin_'): original = getattr(__builtin__, name[14:]) BUILTIN_TYPER[original] = value - +BUILTIN_TYPER[math.floor] = rtype_math_floor +BUILTIN_TYPER[math.fmod] = rtype_math_fmod # annotation of low-level types def rtype_malloc(hop): assert hop.args_s[0].is_constant() if hop.nb_args == 1: - vlist = hop.inputargs(Void) + vlist = hop.inputargs(lltype.Void) return hop.genop('malloc', vlist, resulttype = hop.r_result.lowleveltype) else: - vlist = hop.inputargs(Void, Signed) + vlist = hop.inputargs(lltype.Void, lltype.Signed) return hop.genop('malloc_varsize', vlist, resulttype = hop.r_result.lowleveltype) def rtype_const_result(hop): - return hop.inputconst(Void, hop.s_result.const) + return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) def rtype_cast_pointer(hop): assert hop.args_s[0].is_constant() assert isinstance(hop.args_r[1], rptr.PtrRepr) - v_type, v_input = hop.inputargs(Void, hop.args_r[1]) + v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1]) return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) +def rtype_runtime_type_info(hop): + assert isinstance(hop.args_r[0], rptr.PtrRepr) + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('runtime_type_info', vlist, + resulttype = rptr.PtrRepr(lltype.Ptr(lltype.RuntimeTypeInfo))) + BUILTIN_TYPER[lltype.malloc] = rtype_malloc BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result +BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result +BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask +BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint + +import time + +def rtype_time_clock(hop): + c = hop.inputconst(pyobj_repr, time.clock) + v = hop.genop('simple_call', [c], resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, float_repr) + +BUILTIN_TYPER[time.clock] = rtype_time_clock + + +def rtype_time_time(hop): + c = hop.inputconst(pyobj_repr, time.time) + v = hop.genop('simple_call', [c], resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, float_repr) + +BUILTIN_TYPER[time.time] = rtype_time_time + +import math + +def rtype_math_exp(hop): + vlist = hop.inputargs(lltype.Float) + # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR + return hop.llops.gencapicall('exp', vlist, resulttype=lltype.Float, + includes=("math.h",)) # XXX clean up needed + +BUILTIN_TYPER[math.exp] = rtype_math_exp Modified: pypy/branch/pycompiler/rpython/rclass.py ============================================================================== --- pypy/branch/pycompiler/rpython/rclass.py (original) +++ pypy/branch/pycompiler/rpython/rclass.py Fri Jul 1 18:30:34 2005 @@ -2,8 +2,12 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, inputconst +from pypy.rpython.lltype import ForwardReference, GcForwardReference +from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc +from pypy.rpython.lltype import cast_pointer, castable, nullptr +from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf +from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo # # There is one "vtable" per user class, with the following structure: @@ -11,6 +15,8 @@ # # struct object_vtable { # struct object_vtable* parenttypeptr; +# RuntimeTypeInfo * rtti; +# array { char } * name; # } # # Every other class X, with parent Y, has the structure: @@ -34,7 +40,10 @@ OBJECT_VTABLE = ForwardReference() TYPEPTR = Ptr(OBJECT_VTABLE) -OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR))) +OBJECT_VTABLE.become(Struct('object_vtable', + ('parenttypeptr', TYPEPTR), + ('rtti', Ptr(RuntimeTypeInfo)), + ('name', Ptr(Array(Char))))) OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) OBJECTPTR = Ptr(OBJECT) @@ -55,6 +64,7 @@ else: result = ClassRepr(rtyper, classdef) rtyper.class_reprs[classdef] = result + rtyper.reprs_must_call_setup.append(result) return result def getinstancerepr(rtyper, classdef): @@ -67,6 +77,7 @@ else: result = InstanceRepr(rtyper,classdef) rtyper.instance_reprs[classdef] = result + rtyper.reprs_must_call_setup.append(result) return result class MissingRTypeAttribute(TyperError): @@ -149,10 +160,10 @@ count = 0 for x, classdef in s_value.prebuiltinstances.items(): if isclassdef(classdef): - if classdef.commonbase(self.classdef) != self.classdef: - raise TyperError("methods from PBC set %r don't belong " - "in %r" % (s_value.prebuiltinstances, - self.classdef.cls)) + #if classdef.commonbase(self.classdef) != self.classdef: + # raise TyperError("methods from PBC set %r don't belong " + # "in %r" % (s_value.prebuiltinstances, + # self.classdef.cls)) count += 1 classdef = True debound[x] = classdef @@ -183,8 +194,7 @@ """Return a ptr to the vtable of this type.""" if self.vtable is None: self.vtable = malloc(self.vtable_type, immortal=True) - if self.classdef is not None: - self.setup_vtable(self.vtable, self) + self.setup_vtable(self.vtable, self) # vtable = self.vtable if cast_to_typeptr: @@ -195,8 +205,20 @@ """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: - # initialize the 'parenttypeptr' field - vtable.parenttypeptr = rsubcls.rbase.getvtable() + # initialize the 'parenttypeptr' and 'name' fields + if rsubcls.classdef is not None: + vtable.parenttypeptr = rsubcls.rbase.getvtable() + rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) + rinstance.setup() + vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) + if rsubcls.classdef is None: + name = 'object' + else: + name = rsubcls.classdef.cls.__name__ + vtable.name = malloc(Array(Char), len(name)+1, immortal=True) + for i in range(len(name)): + vtable.name[i] = name[i] + vtable.name[len(name)] = '\x00' else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls @@ -282,6 +304,7 @@ self.object_type = OBJECT else: self.object_type = GcForwardReference() + self.prebuiltinstances = {} # { id(x): (x, _ptr) } self.lowleveltype = Ptr(self.object_type) def __repr__(self): @@ -327,34 +350,59 @@ allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields + attachRuntimeTypeInfo(self.object_type) self.initialized = True - def convert_const(self, value, targetptr=None, vtable=None): + def setup_final_touch(self): + self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, + ll_runtime_type_info, + OBJECT) + + def convert_const(self, value): if value is None: return nullptr(self.object_type) - # we will need the vtable pointer, so ask it first, to let - # ClassRepr.convert_const() perform all the necessary checks on 'value' - if vtable is None: - vtable = self.rclass.convert_const(value.__class__) - if targetptr is None: - targetptr = malloc(self.object_type) - # - if self.classdef is None: - # instantiate 'object': should be disallowed, but it's convenient - # to write convert_const() this way and use itself recursively - targetptr.typeptr = cast_vtable_to_typeptr(vtable) - else: - # build the parent part of the instance - self.rbase.convert_const(value, - targetptr = targetptr.super, - vtable = vtable) - # add instance attributes from this level + try: + classdef = self.rtyper.annotator.getuserclasses()[value.__class__] + except KeyError: + raise TyperError("no classdef: %r" % (value.__class__,)) + if classdef != self.classdef: + # if the class does not match exactly, check that 'value' is an + # instance of a subclass and delegate to that InstanceRepr + if classdef is None: + raise TyperError("not implemented: object() instance") + if classdef.commonbase(self.classdef) != self.classdef: + raise TyperError("not an instance of %r: %r" % ( + self.classdef.cls, value)) + rinstance = getinstancerepr(self.rtyper, classdef) + result = rinstance.convert_const(value) + return cast_pointer(self.lowleveltype, result) + # common case + try: + return self.prebuiltinstances[id(value)][1] + except KeyError: + self.setup() + result = malloc(self.object_type) + self.prebuiltinstances[id(value)] = value, result + self.initialize_prebuilt_instance(value, classdef, result) + return result + + def get_ll_eq_function(self): + return None + + def initialize_prebuilt_instance(self, value, classdef, result): + if self.classdef is not None: + # recursively build the parent part of the instance + self.rbase.initialize_prebuilt_instance(value, classdef, + result.super) + # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): attrvalue = getattr(value, name) - # XXX RECURSIVE PREBUILT DATA STRUCTURES XXX llattrvalue = r.convert_const(attrvalue) - setattr(targetptr, mangled_name, llattrvalue) - return targetptr + setattr(result, mangled_name, llattrvalue) + else: + # OBJECT part + rclass = getclassrepr(self.rtyper, classdef) + result.typeptr = rclass.getvtable() #def parentpart(self, vinst, llops): # """Return the pointer 'vinst' cast to the parent type.""" @@ -372,33 +420,31 @@ raise MissingRTypeAttribute(attr) return self.rbase.getfieldrepr(attr) - def getfield(self, vinst, attr, llops, start_repr=None): + def getfield(self, vinst, attr, llops, force_cast=False): """Read the given attribute (or __class__ for the type) of 'vinst'.""" - if start_repr is None: - start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) - vinst = llops.convertvar(vinst, start_repr, self) + if force_cast: + vinst = llops.genop('cast_pointer', [vinst], resulttype=self) return llops.genop('getfield', [vinst, cname], resulttype=r) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - return self.rbase.getfield(vinst, attr, llops, start_repr=start_repr) + return self.rbase.getfield(vinst, attr, llops, force_cast=True) - def setfield(self, vinst, attr, vvalue, llops, start_repr=None): + def setfield(self, vinst, attr, vvalue, llops, force_cast=False): """Write the given attribute (or __class__ for the type) of 'vinst'.""" - if start_repr is None: - start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) - vinst = llops.convertvar(vinst, start_repr, self) + if force_cast: + vinst = llops.genop('cast_pointer', [vinst], resulttype=self) llops.genop('setfield', [vinst, cname, vvalue]) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - self.rbase.setfield(vinst, attr, vvalue, llops, start_repr=start_repr) + self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True) def new_instance(self, llops): """Build a new instance, without calling __init__.""" @@ -408,21 +454,22 @@ ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) # initialize instance attributes from their defaults from the class - flds = self.allinstancefields.keys() - flds.sort() - mro = list(self.classdef.getmro()) - for fldname in flds: - if fldname == '__class__': - continue - mangled_name, r = self.allinstancefields[fldname] - if r.lowleveltype == Void: - continue - for clsdef in mro: - if fldname in clsdef.cls.__dict__: - value = clsdef.cls.__dict__[fldname] - cvalue = inputconst(r, value) - self.setfield(vptr, fldname, cvalue, llops) - break + if self.classdef is not None: + flds = self.allinstancefields.keys() + flds.sort() + mro = list(self.classdef.getmro()) + for fldname in flds: + if fldname == '__class__': + continue + mangled_name, r = self.allinstancefields[fldname] + if r.lowleveltype == Void: + continue + for clsdef in mro: + if fldname in clsdef.cls.__dict__: + value = clsdef.cls.__dict__[fldname] + cvalue = inputconst(r, value) + self.setfield(vptr, fldname, cvalue, llops) + break return vptr def rtype_type(self, hop): @@ -437,7 +484,8 @@ elif attr in self.rclass.allmethods: # special case for methods: represented as their 'self' only # (see MethodsPBCRepr) - return vinst + return hop.r_result.get_method_from_instance(self, vinst, + hop.llops) else: vcls = self.getfield(vinst, '__class__', hop.llops) return self.rclass.getclsfield(vcls, attr, hop.llops) @@ -448,6 +496,20 @@ vinst, vattr, vvalue = hop.inputargs(self, Void, r_value) self.setfield(vinst, attr, vvalue, hop.llops) + def ll_str(i, r): + instance = cast_pointer(OBJECTPTR, i) + from pypy.rpython import rstr + nameLen = len(instance.typeptr.name) + nameString = malloc(rstr.STR, nameLen-1) + i = 0 + while i < nameLen - 1: + nameString.chars[i] = instance.typeptr.name[i] + i += 1 + return rstr.ll_strconcat(rstr.instance_str_prefix, + rstr.ll_strconcat(nameString, + rstr.instance_str_suffix)) + ll_str = staticmethod(ll_str) + class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): @@ -478,6 +540,13 @@ rinstance = getinstancerepr(hop.rtyper, classdef) return rinstance.new_instance(hop.llops) +def instance_annotation_for_cls(rtyper, cls): + try: + classdef = rtyper.annotator.getuserclasses()[cls] + except KeyError: + raise TyperError("no classdef: %r" % (cls,)) + return annmodel.SomeInstance(classdef) + # ____________________________________________________________ # # Low-level implementation of operations on classes and instances @@ -494,3 +563,6 @@ return False subcls = subcls.parenttypeptr return True + +def ll_runtime_type_info(obj): + return obj.typeptr.rtti Modified: pypy/branch/pycompiler/rpython/rfloat.py ============================================================================== --- pypy/branch/pycompiler/rpython/rfloat.py (original) +++ pypy/branch/pycompiler/rpython/rfloat.py Fri Jul 1 18:30:34 2005 @@ -1,9 +1,13 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Ptr from pypy.rpython.rmodel import Repr, TyperError, FloatRepr from pypy.rpython.rmodel import IntegerRepr, BoolRepr - +from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.lltype import PyObject, Array, Char +from pypy.rpython.rstr import STR +from pypy.rpython.lltype import functionptr, FuncType, malloc +from pypy.rpython import rstr debug = False @@ -37,17 +41,25 @@ rtype_inplace_mul = rtype_mul def rtype_div(_, hop): - return _rtype_template(hop, 'div') + # turn 'div' on floats into 'truediv' + return _rtype_template(hop, 'truediv') + + rtype_inplace_div = rtype_div + rtype_truediv = rtype_div + rtype_inplace_truediv = rtype_div + + def rtype_mod(_, hop): + return _rtype_template(hop, 'mod') - rtype_inplace_div = rtype_div + rtype_inplace_mod = rtype_mod def rtype_pow(_, hop): s_float3 = hop.args_s[2] if s_float3.is_constant() and s_float3.const is None: vlist = hop.inputargs(Float, Float, Void)[:2] + return hop.genop('float_pow', vlist, resulttype=Float) else: - vlist = hop.inputargs(Float, Float, Float) - return hop.genop('float_pow', vlist, resulttype=Float) + raise TyperError("cannot handle pow with three float arguments") def rtype_inplace_pow(_, hop): return _rtype_template(hop, 'pow') @@ -74,6 +86,9 @@ def rtype_ge(_, hop): return _rtype_compare_template(hop, 'ge') +class __extend__(pairtype(rstr.StringRepr, FloatRepr)): + def rtype_mod(_, hop): + return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) #Helpers FloatRepr,FloatRepr @@ -94,6 +109,9 @@ raise TyperError("not a float: %r" % (value,)) return float(value) + def get_ll_eq_function(self): + return None + def rtype_is_true(_, hop): vlist = hop.inputargs(Float) return hop.genop('float_is_true', vlist, resulttype=Bool) @@ -112,6 +130,34 @@ rtype_float = rtype_pos + def ll_str(f, repr): + pyfloat = pyfloat_fromdouble_ptr(f) + pystring = pyobject_str_ptr(pyfloat) + stringsize = pystring_size_ptr(pystring) + + ret = malloc(STR, stringsize) + + tollchararray_ptr(pystring, ret.chars) + + return ret + + ll_str = staticmethod(ll_str) + +PyObjectPtr = Ptr(PyObject) + +pystring_size_ptr = functionptr(FuncType([PyObjectPtr], Signed), + "PyString_Size", + external="C") +pyfloat_fromdouble_ptr = functionptr(FuncType([Float], PyObjectPtr), + "PyFloat_FromDouble", + external="C") +pyobject_str_ptr = functionptr(FuncType([PyObjectPtr], PyObjectPtr), + "PyObject_Str", + external="C") +tollchararray_ptr = functionptr(FuncType([PyObjectPtr, Ptr(Array(Char))], Void), + "PyString_ToLLCharArray", + external="C") + # # _________________________ Conversions _________________________ @@ -131,3 +177,17 @@ if debug: print 'explicit cast_bool_to_float' return llops.genop('cast_bool_to_float', [v], resulttype=Float) return NotImplemented + +class __extend__(pairtype(PyObjRepr, FloatRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Float: + return llops.gencapicall('PyFloat_AsDouble', [v], + resulttype=Float) + return NotImplemented + +class __extend__(pairtype(FloatRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Float: + return llops.gencapicall('PyFloat_FromDouble', [v], + resulttype=pyobj_repr) + return NotImplemented Modified: pypy/branch/pycompiler/rpython/rint.py ============================================================================== --- pypy/branch/pycompiler/rpython/rint.py (original) +++ pypy/branch/pycompiler/rpython/rint.py Fri Jul 1 18:30:34 2005 @@ -1,8 +1,12 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.objspace.flow.objspace import op_appendices +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \ + UniChar, GcArray, malloc, Array +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \ + inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.rarithmetic import intmask, r_uint debug = False @@ -24,10 +28,10 @@ class __extend__(pairtype(IntegerRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: + if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned: if debug: print 'explicit cast_int_to_uint' return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) - if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned: + if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: if debug: print 'explicit cast_uint_to_int' return llops.genop('cast_uint_to_int', [v], resulttype=Signed) return v @@ -40,7 +44,6 @@ def rtype_add_ovf(_, hop): return _rtype_template(hop, 'add_ovf') - rtype_inplace_add_ovf = rtype_add_ovf def rtype_sub(_, hop): return _rtype_template(hop, 'sub') @@ -48,24 +51,40 @@ def rtype_sub_ovf(_, hop): return _rtype_template(hop, 'sub_ovf') - rtype_inplace_sub_ovf = rtype_sub_ovf def rtype_mul(_, hop): return _rtype_template(hop, 'mul') rtype_inplace_mul = rtype_mul + def rtype_mul_ovf(_, hop): + return _rtype_template(hop, 'mul_ovf') + def rtype_div(_, hop): - return _rtype_template(hop, 'div') + # turn 'div' on integers into 'floordiv' + return _rtype_template(hop, 'floordiv', [ZeroDivisionError]) rtype_inplace_div = rtype_div + def rtype_div_ovf(_, hop): + return _rtype_template(hop, 'div_ovf', [ZeroDivisionError]) + def rtype_floordiv(_, hop): - return _rtype_template(hop, 'floordiv') + return _rtype_template(hop, 'floordiv', [ZeroDivisionError]) rtype_inplace_floordiv = rtype_floordiv + def rtype_floordiv_ovf(_, hop): + return _rtype_template(hop, 'floordiv_ovf', [ZeroDivisionError]) + + def rtype_truediv(_, hop): + return _rtype_template(hop, 'truediv', [ZeroDivisionError]) + rtype_inplace_truediv = rtype_truediv + def rtype_mod(_, hop): - return _rtype_template(hop, 'mod') + return _rtype_template(hop, 'mod', [ZeroDivisionError]) rtype_inplace_mod = rtype_mod + def rtype_mod_ovf(_, hop): + return _rtype_template(hop, 'mod_ovf', [ZeroDivisionError]) + def rtype_xor(_, hop): return _rtype_template(hop, 'xor') rtype_inplace_xor = rtype_xor @@ -79,38 +98,40 @@ rtype_inplace_or = rtype_or_ def rtype_lshift(_, hop): - return _rtype_template(hop, 'lshift') + return _rtype_template(hop, 'lshift', [ValueError]) rtype_inplace_lshift = rtype_lshift def rtype_lshift_ovf(_, hop): - return _rtype_template(hop, 'lshift_ovf') - rtype_inplace_lshift_ovf = rtype_lshift_ovf + return _rtype_template(hop, 'lshift_ovf', [ValueError]) def rtype_rshift(_, hop): - return _rtype_template(hop, 'rshift') + return _rtype_template(hop, 'rshift', [ValueError]) rtype_inplace_rshift = rtype_rshift - def rtype_rshift_ovf(_, hop): - return _rtype_template(hop, 'rshift_ovf') - rtype_inplace_rshift_ovf = rtype_rshift_ovf - - def rtype_pow(_, hop): + def rtype_pow(_, hop, suffix=''): + if hop.has_implicit_exception(ZeroDivisionError): + suffix += '_zer' s_int3 = hop.args_s[2] if hop.s_result.unsigned: if s_int3.is_constant() and s_int3.const is None: vlist = hop.inputargs(Unsigned, Unsigned, Void)[:2] else: vlist = hop.inputargs(Unsigned, Unsigned, Unsigned) - return hop.genop('uint_pow', vlist, resulttype=Unsigned) + return hop.genop('uint_pow' + suffix, vlist, resulttype=Unsigned) else: if s_int3.is_constant() and s_int3.const is None: vlist = hop.inputargs(Signed, Signed, Void)[:2] else: vlist = hop.inputargs(Signed, Signed, Signed) - return hop.genop('int_pow', vlist, resulttype=Signed) + return hop.genop('int_pow' + suffix, vlist, resulttype=Signed) + + def rtype_pow_ovf(_, hop): + if hop.s_result.unsigned: + raise TyperError("forbidden uint_pow_ovf") + return self.rtype_pow(_, hop, suffix='_ovf') def rtype_inplace_pow(_, hop): - return _rtype_template(hop, 'pow') + return _rtype_template(hop, 'pow', [ZeroDivisionError]) #comparisons: eq is_ ne lt le gt ge @@ -136,8 +157,15 @@ #Helper functions -def _rtype_template(hop, func): +def _rtype_template(hop, func, implicit_excs=[]): + func1 = func + for implicit_exc in implicit_excs: + if hop.has_implicit_exception(implicit_exc): + appendix = op_appendices[implicit_exc] + func += '_' + appendix if hop.s_result.unsigned: + if func1.endswith('_ovf'): + raise TyperError("forbidden uint_" + func) vlist = hop.inputargs(Unsigned, Unsigned) return hop.genop('uint_'+func, vlist, resulttype=Unsigned) else: @@ -163,14 +191,29 @@ class __extend__(IntegerRepr): def convert_const(self, value): - if not isinstance(value, int): # can be bool + if not isinstance(value, (int, r_uint)): # can be bool raise TyperError("not an integer: %r" % (value,)) - return int(value) + if self.lowleveltype == Signed: + return intmask(value) + if self.lowleveltype == Unsigned: + return r_uint(value) + raise NotImplementedError + + def get_ll_eq_function(self): + return None def rtype_float(_, hop): vlist = hop.inputargs(Float) return vlist[0] + def rtype_chr(_, hop): + vlist = hop.inputargs(Signed) + return hop.genop('cast_int_to_char', vlist, resulttype=Char) + + def rtype_unichr(_, hop): + vlist = hop.inputargs(Signed) + return hop.genop('cast_int_to_unichar', vlist, resulttype=UniChar) + def rtype_is_true(self, hop): if self.lowleveltype == Unsigned: vlist = hop.inputargs(Unsigned) @@ -191,8 +234,7 @@ def rtype_abs_ovf(_, hop): if hop.s_result.unsigned: - vlist = hop.inputargs(Unsigned) - return vlist[0] + raise TyperError("forbidden uint_abs_ovf") else: vlist = hop.inputargs(Signed) return hop.genop('int_abs_ovf', vlist, resulttype=Signed) @@ -213,6 +255,13 @@ vlist = hop.inputargs(Signed) return hop.genop('int_neg', vlist, resulttype=Signed) + def rtype_neg_ovf(_, hop): + if hop.s_result.unsigned: + raise TyperError("forbidden uint_neg_ovf") + else: + vlist = hop.inputargs(Signed) + return hop.genop('int_neg_ovf', vlist, resulttype=Signed) + def rtype_pos(_, hop): if hop.s_result.unsigned: vlist = hop.inputargs(Unsigned) @@ -230,6 +279,82 @@ vlist = hop.inputargs(Float) return vlist[0] + def ll_str(i, repr): + from pypy.rpython.rstr import STR + temp = malloc(CHAR_ARRAY, 20) + len = 0 + sign = 0 + if i < 0: + sign = 1 + i = -i + if i == 0: + len = 1 + temp[0] = '0' + else: + while i: + temp[len] = chr(i%10+ord('0')) + i //= 10 + len += 1 + len += sign + result = malloc(STR, len) + if sign: + result.chars[0] = '-' + j = 1 + else: + j = 0 + while j < len: + result.chars[j] = temp[len-j-1] + j += 1 + return result + ll_str = staticmethod(ll_str) + + def rtype_hex(_, hop): + varg = hop.inputarg(hop.args_r[0], 0) + true = inputconst(Bool, True) + return hop.gendirectcall(ll_int2hex, varg, true) + + + +CHAR_ARRAY = GcArray(Char) + +hex_chars = malloc(Array(Char), 16, immortal=True) + +for i in range(16): + hex_chars[i] = "%x"%i + +def ll_int2hex(i, addPrefix): + from pypy.rpython.rstr import STR + temp = malloc(CHAR_ARRAY, 20) + len = 0 + sign = 0 + if i < 0: + sign = 1 + i = -i + if i == 0: + len = 1 + temp[0] = '0' + else: + while i: + temp[len] = hex_chars[i%16] + i //= 16 + len += 1 + len += sign + if addPrefix: + len += 2 + result = malloc(STR, len) + j = 0 + if sign: + result.chars[0] = '-' + j = 1 + if addPrefix: + result.chars[j] = '0' + result.chars[j+1] = 'x' + j += 2 + while j < len: + result.chars[j] = temp[len-j-1] + j += 1 + return result + # # _________________________ Conversions _________________________ Modified: pypy/branch/pycompiler/rpython/rlist.py ============================================================================== --- pypy/branch/pycompiler/rpython/rlist.py (original) +++ pypy/branch/pycompiler/rpython/rlist.py Fri Jul 1 18:30:34 2005 @@ -1,11 +1,15 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.rclass import InstanceRepr +from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct +from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive +from pypy.rpython.lltype import Bool +from pypy.rpython import rstr # ____________________________________________________________ # @@ -44,6 +48,7 @@ else: self.item_repr = item_repr self.listitem = listitem + self.list_cache = {} # setup() needs to be called to finish this initialization def setup(self): @@ -51,9 +56,35 @@ self.item_repr = self._item_repr_computer() if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(("item", ITEM)) + ITEMARRAY = GcArray(ITEM) self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) + def convert_const(self, listobj): + # get object from bound list method + listobj = getattr(listobj, '__self__', listobj) + if not isinstance(listobj, list): + raise TyperError("expected a list: %r" % (listobj,)) + try: + key = Constant(listobj) + return self.list_cache[key] + except KeyError: + self.setup() + result = malloc(self.LIST, immortal=True) + self.list_cache[key] = result + result.items = malloc(self.LIST.items.TO, len(listobj)) + r_item = self.item_repr + for i in range(len(listobj)): + x = listobj[i] + result.items[i] = r_item.convert_const(x) + return result + + def get_eqfunc(self): + return inputconst(Void, self.item_repr.get_ll_eq_function()) + + def rtype_bltn_list(self,hop): + v_lst = hop.inputarg(self,0) + return hop.gendirectcall(ll_copy,v_lst) + def rtype_len(self, hop): v_lst, = hop.inputargs(self) return hop.gendirectcall(ll_len, v_lst) @@ -62,13 +93,76 @@ v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) + def rtype_method_index(self, hop): + v_lst, v_value = hop.inputargs(self, self.item_repr) + return hop.gendirectcall(ll_listindex, v_lst, v_value, self.get_eqfunc()) + + def rtype_method_insert(self, hop): + v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr) + arg1 = hop.args_s[1] + args = v_lst, v_index, v_value + if arg1.is_constant() and arg1.const == 0: + llfn = ll_prepend + args = v_lst, v_value + elif arg1.nonneg: + llfn = ll_insert_nonneg + else: + llfn = ll_insert + hop.gendirectcall(llfn, *args) + def rtype_method_extend(self, hop): v_lst1, v_lst2 = hop.inputargs(self, self) hop.gendirectcall(ll_extend, v_lst1, v_lst2) + + def rtype_method_reverse(self, hop): + v_lst, = hop.inputargs(self) + hop.gendirectcall(ll_reverse,v_lst) + + def rtype_method_pop(self, hop): + if hop.nb_args == 2: + args = hop.inputargs(self, Signed) + assert hasattr(args[1], 'concretetype') + arg1 = hop.args_s[1] + if arg1.is_constant() and arg1.const == 0: + llfn = ll_pop_zero + args = args[:1] + elif hop.args_s[1].nonneg: + llfn = ll_pop_nonneg + else: + llfn = ll_pop + else: + args = hop.inputargs(self) + llfn = ll_pop_default + return hop.gendirectcall(llfn, *args) def make_iterator_repr(self): return ListIteratorRepr(self) + def ll_str(l, listrepr): + items = l.items + length = len(items) + item_repr = listrepr.item_repr + + temp = malloc(TEMP, length) + i = 0 + while i < length: + temp[i] = item_repr.ll_str(items[i], item_repr) + i += 1 + + return rstr.ll_strconcat( + rstr.list_str_open_bracket, + rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep, + temp), + rstr.list_str_close_bracket)) + ll_str = staticmethod(ll_str) + + +class __extend__(pairtype(ListRepr, Repr)): + + def rtype_contains((r_lst, _), hop): + v_lst, v_any = hop.inputargs(r_lst, r_lst.item_repr) + return hop.gendirectcall(ll_listcontains, v_lst, v_any, r_lst.get_eqfunc()) + class __extend__(pairtype(ListRepr, IntegerRepr)): @@ -79,7 +173,7 @@ else: llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) - + def rtype_setitem((r_lst, r_int), hop): v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr) if hop.args_s[1].nonneg: @@ -135,12 +229,33 @@ hop.gendirectcall(ll_extend, v_lst1, v_lst2) return v_lst1 + def rtype_eq((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc()) + + def rtype_ne((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc()) + return hop.genop('bool_not', [flag], resulttype=Bool) + + # ____________________________________________________________ # # 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_copy(l): + items = l.items + length = len(items) + new_lst = ll_newlist(typeOf(l), length) + i = 0 + new_items = new_lst.items + while i < length: + new_items[i] = items[i] + i += 1 + return new_lst + def ll_len(l): return len(l.items) @@ -148,65 +263,132 @@ length = len(l.items) newitems = malloc(typeOf(l).TO.items.TO, length+1) i = 0 - while i= len(l.items): raise StopIteration iter.index = index + 1 - return l.items[index].item + return l.items[index] Modified: pypy/branch/pycompiler/rpython/rmodel.py ============================================================================== --- pypy/branch/pycompiler/rpython/rmodel.py (original) +++ pypy/branch/pycompiler/rpython/rmodel.py Fri Jul 1 18:30:34 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pair, pairtype, extendabletype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import Void, Bool, Float, Signed, Char +from pypy.rpython.lltype import Void, Bool, Float, Signed, Char, UniChar from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject from pypy.rpython.lltype import FuncType, functionptr @@ -10,7 +10,7 @@ """ An instance of Repr is associated with each instance of SomeXxx. It defines the chosen representation for the SomeXxx. The Repr subclasses generally follows the SomeXxx subclass hierarchy, but there are numerous - exceptions. For example, the anotator uses SomeIter for any iterator, but + exceptions. For example, the annotator uses SomeIter for any iterator, but we need different representations according to the type of container we are iterating over. """ @@ -22,6 +22,11 @@ def setup(self): "For recursive data structure, which must be initialized in two steps." + def setup_final_touch(self): + """Same as setup(), called a bit later, for effects that are only + needed after the typer finished (as opposed to needed for other parts + of the typer itself).""" + def __getattr__(self, name): # Assume that when an attribute is missing, it's because setup() needs # to be called @@ -32,6 +37,9 @@ raise AttributeError("%s instance has no attribute %s" % ( self.__class__.__name__, name)) + def _freeze_(self): + return True + def convert_const(self, value): "Convert the given constant value to the low-level repr of 'self'." if self.lowleveltype != Void: @@ -44,6 +52,9 @@ self, value)) return value + def get_ll_eq_function(self): + raise TyperError, 'no equality function for %r' % self + # default implementation of some operations def rtype_getattr(self, hop): @@ -61,6 +72,10 @@ else: raise TyperError("getattr() with a non-constant attribute name") + def rtype_str(self, hop): + vrepr = inputconst(Void, self) + return hop.gendirectcall(self.ll_str, hop.args_v[0], vrepr) + def rtype_nonzero(self, hop): return self.rtype_is_true(hop) # can call a subclass' rtype_is_true() @@ -72,6 +87,14 @@ else: return hop.genop('int_is_true', [vlen], resulttype=Bool) + def rtype_id(self, hop): + if not isinstance(self.lowleveltype, Ptr): + raise TyperError('id() of an instance of the non-pointer %r' % ( + self,)) + vobj, = hop.inputargs(self) + # XXX + return hop.genop('cast_ptr_to_int', [vobj], resulttype=Signed) + def rtype_iter(self, hop): r_iter = self.make_iterator_repr() return r_iter.newiter(hop) @@ -93,6 +116,23 @@ def rtyper_makekey(self): return None +# ____ generic binary operations _____________________________ + + +class __extend__(pairtype(Repr, Repr)): + + def rtype_is_((robj1, robj2), hop): + if (not isinstance(robj1.lowleveltype, Ptr) or + not isinstance(robj2.lowleveltype, Ptr)): + raise TyperError('is of instances of the non-pointers: %r, %r' % ( + robj1, robj2)) + if robj1.lowleveltype != robj2.lowleveltype: + raise TyperError('is of instances of different pointer types: %r, %r' % ( + robj1, robj2)) + + v_list = hop.inputargs(robj1, robj2) + return hop.genop('ptr_eq', v_list, resulttype=Bool) + # ____________________________________________________________ class TyperError(Exception): @@ -143,6 +183,9 @@ class CharRepr(StringRepr): lowleveltype = Char +class UniCharRepr(Repr): + lowleveltype = UniChar + class VoidRepr(Repr): lowleveltype = Void impossible_repr = VoidRepr() @@ -168,8 +211,10 @@ except (AssertionError, AttributeError): realtype = '???' if realtype != lltype: - raise TyperError("inputconst(reqtype = %s, value = %s)" % ( - reqtype, value)) + raise TyperError("inputconst(reqtype = %s, value = %s):\n" + "expected a %r,\n" + " got a %r" % (reqtype, value, + lltype, realtype)) c = Constant(value) c.concretetype = lltype return c @@ -188,3 +233,4 @@ lloutput = getconcretetype(graph.getreturnvar()) FT = FuncType(llinputs, lloutput) return functionptr(FT, func.func_name, graph = graph, _callable = func) + Modified: pypy/branch/pycompiler/rpython/robject.py ============================================================================== --- pypy/branch/pycompiler/rpython/robject.py (original) +++ pypy/branch/pycompiler/rpython/robject.py Fri Jul 1 18:30:34 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pair, pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr -from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr, nullptr +from pypy.rpython.rmodel import Repr, TyperError, VoidRepr, inputconst from pypy.rpython import rclass from pypy.tool.sourcetools import func_with_new_name @@ -32,6 +32,14 @@ constpyobj_repr = PyObjRepr() constpyobj_repr.lowleveltype = Void + +class __extend__(pairtype(VoidRepr, PyObjRepr)): + # conversion used to return a PyObject* when a function can really only + # raise an exception, in which case the return value is a VoidRepr + def convert_from_to(_, v, llops): + return inputconst(Ptr(PyObject), nullptr(PyObject)) + + # ____________________________________________________________ # # All operations involving a PyObjRepr are "replaced" by themselves, @@ -46,7 +54,7 @@ funcname = 'rtype_' + opname func = func_with_new_name(rtype_op, funcname) - assert funcname not in cls.__dict__ # can be in Repr; overriden then. + assert funcname not in cls.__dict__ # can be in Repr; overridden then. setattr(cls, funcname, func) Modified: pypy/branch/pycompiler/rpython/rpbc.py ============================================================================== --- pypy/branch/pycompiler/rpython/rpbc.py (original) +++ pypy/branch/pycompiler/rpython/rpbc.py Fri Jul 1 18:30:34 2005 @@ -1,28 +1,33 @@ import types -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef -from pypy.rpython.lltype import typeOf, Void -from pypy.rpython.rmodel import Repr, TyperError +from pypy.objspace.flow.model import Constant +from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct, Bool +from pypy.rpython.lltype import Ptr, malloc, nullptr +from pypy.rpython.rmodel import Repr, TyperError, inputconst from pypy.rpython import rclass - +from pypy.rpython.rtyper import HighLevelOp +from pypy.rpython import robject class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): # for now, we require that the PBC fits neatly into one of the Repr # categories below, and doesn't for example mix functions, classes # and methods. - callb = rtyper.annotator.getpbccallables() + call_families = rtyper.annotator.getpbccallfamilies() choices = {} for x, classdef in self.prebuiltinstances.items(): cdefflag = isclassdef(classdef) + if not cdefflag: + classdef = None # consider unbound methods as plain functions if isinstance(x, types.MethodType) and x.im_self is None: x = x.im_func # callable or frozen object? - if x in callb: + if (classdef, x) in call_families: # what type of callable? if isinstance(x, types.FunctionType): if cdefflag: @@ -32,13 +37,13 @@ choice = FunctionsPBCRepr elif isinstance(x, (type, types.ClassType)): choice = ClassesPBCRepr - #elif isinstance(x, types.MethodType): - # choice = ConstMethodsPBCRepr + elif isinstance(x, types.MethodType): + choice = MethodOfFrozenPBCRepr else: raise TyperError("don't know about callable %r" % (x,)) else: # frozen object - choice = FrozenPBCRepr + choice = getFrozenPBCRepr if cdefflag: raise TyperError("unexpected classdef in PBC set %r" % ( @@ -56,22 +61,185 @@ lst.sort() return tuple(lst) - # ____________________________________________________________ -class FrozenPBCRepr(Repr): +def getFrozenPBCRepr(rtyper, s_pbc): + if len(s_pbc.prebuiltinstances) <= 1: + if s_pbc.const is None: + return none_frozen_pbc_repr + return single_frozen_pbc_repr + else: + pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys() + if pbc is not None] + access_sets = rtyper.annotator.getpbcaccesssets() + _, _, access = access_sets.find(pbcs[0]) + for obj in pbcs[1:]: + _, _, access1 = access_sets.find(obj) + assert access1 is access # XXX not implemented + try: + return rtyper.pbc_reprs[access] + except KeyError: + result = MultipleFrozenPBCRepr(rtyper, access) + rtyper.pbc_reprs[access] = result + rtyper.reprs_must_call_setup.append(result) + return result + + +class SingleFrozenPBCRepr(Repr): """Representation selected for a single non-callable pre-built constant.""" lowleveltype = Void - def __init__(self, rtyper, s_pbc): - assert len(s_pbc.prebuiltinstances) == 1 # XXX not implemented - def rtype_getattr(_, hop): if not hop.s_result.is_constant(): raise TyperError("getattr on a constant PBC returns a non-constant") return hop.inputconst(hop.r_result, hop.s_result.const) +single_frozen_pbc_repr = SingleFrozenPBCRepr() + +# __ None ____________________________________________________ +class NoneFrozenPBCRepr(SingleFrozenPBCRepr): + + def rtype_is_true(self, hop): + return Constant(False, Bool) + +none_frozen_pbc_repr = NoneFrozenPBCRepr() + + +def rtype_is_None(robj1, rnone2, hop, pos=0): + if not isinstance(robj1.lowleveltype, Ptr): + raise TyperError('is None of instance of the non-pointer: %r' % (robj1)) + v1 = hop.inputarg(robj1, pos) + return hop.genop('ptr_iszero', [v1], resulttype=Bool) + +class __extend__(pairtype(Repr, NoneFrozenPBCRepr)): + + def rtype_is_((robj1, rnone2), hop): + return rtype_is_None(robj1, rnone2, hop) + +class __extend__(pairtype(NoneFrozenPBCRepr, Repr)): + + def rtype_is_((rnone1, robj2), hop): + return rtype_is_None(robj2, rnone1, hop, pos=1) + +class __extend__(pairtype(NoneFrozenPBCRepr, robject.PyObjRepr)): + + def convert_from_to(_, v, llops): + return inputconst(robject.pyobj_repr, None) + +# ____________________________________________________________ + +class MultipleFrozenPBCRepr(Repr): + """Representation selected for multiple non-callable pre-built constants.""" + initialized = False + + def __init__(self, rtyper, access_set): + self.rtyper = rtyper + self.access_set = access_set + self.pbc_type = ForwardReference() + self.lowleveltype = Ptr(self.pbc_type) + self.pbc_cache = {} + + def setup(self): + if self.initialized: + assert self.initialized == True + return + self.initialized = "in progress" + llfields = [] + llfieldmap = {} + attrlist = self.access_set.attrs.keys() + attrlist.sort() + for attr in attrlist: + s_value = self.access_set.attrs[attr] + r_value = self.rtyper.getrepr(s_value) + mangled_name = 'pbc_' + attr + llfields.append((mangled_name, r_value.lowleveltype)) + llfieldmap[attr] = mangled_name, r_value + self.pbc_type.become(Struct('pbc', *llfields)) + self.llfieldmap = llfieldmap + self.initialized = True + + def convert_const(self, pbc): + if pbc is None: + return nullptr(self.pbc_type) + if isinstance(pbc, types.MethodType) and pbc.im_self is None: + value = pbc.im_func # unbound method -> bare function +## if pbc not in self.access_set.objects: +## raise TyperError("not found in PBC set: %r" % (pbc,)) + try: + return self.pbc_cache[pbc] + except KeyError: + self.setup() + result = malloc(self.pbc_type, immortal=True) + self.pbc_cache[pbc] = result + for attr, (mangled_name, r_value) in self.llfieldmap.items(): + try: + thisattrvalue = self.access_set.values[(pbc, attr)] + except KeyError: + thisattrvalue = getattr(pbc, attr) + llvalue = r_value.convert_const(thisattrvalue) + setattr(result, mangled_name, llvalue) + return result + + def rtype_is_true(self, hop): + if hop.s_result.is_constant(): + assert hop.s_result.const is True # custom __nonzero__ on PBCs? + return hop.inputconst(Bool, hop.s_result.const) + else: + # None is a nullptr, which is false; everything else is true. + vlist = hop.inputargs(self) + return hop.genop('ptr_nonzero', vlist, resulttype=Bool) + + def rtype_getattr(self, hop): + attr = hop.args_s[1].const + vpbc, vattr = hop.inputargs(self, Void) + return self.getfield(vpbc, attr, hop.llops) + + def getfield(self, vpbc, attr, llops): + mangled_name, r_value = self.llfieldmap[attr] + cmangledname = inputconst(Void, mangled_name) + return llops.genop('getfield', [vpbc, cmangledname], + resulttype = r_value) + + +# ____________________________________________________________ + + +class MethodOfFrozenPBCRepr(Repr): + """Representation selected for a PBC of method object(s) of frozen PBCs. + It assumes that all methods are the same function bound to different PBCs. + The low-level representation can then be a pointer to that PBC.""" + + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.function = s_pbc.prebuiltinstances.keys()[0].im_func + im_selves = {} + for pbc, not_a_classdef in s_pbc.prebuiltinstances.items(): + assert pbc.im_func is self.function + assert not isclassdef(not_a_classdef) + im_selves[pbc.im_self] = True + self.s_im_self = annmodel.SomePBC(im_selves) + self.r_im_self = rtyper.getrepr(self.s_im_self) + self.lowleveltype = self.r_im_self.lowleveltype + + def convert_const(self, method): + if getattr(method, 'im_func', None) is not self.function: + raise TyperError("not a method bound on %r: %r" % (self.function, + method)) + return self.r_im_self.convert_const(method.im_self) + + def rtype_simple_call(self, hop): + s_function = annmodel.SomePBC({self.function: True}) + hop2 = hop.copy() + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' + hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + if isinstance(hop2.args_v[0], Constant): + hop2.args_v[0] = hop.inputarg(self, 0) + c = Constant(self.function) + hop2.v_s_insertfirstarg(c, s_function) # insert 'function' + # now hop2 looks like simple_call(function, self, args...) + return hop2.dispatch() + # ____________________________________________________________ @@ -124,6 +292,8 @@ ## assert not shape_stst, "XXX not implemented" def convert_const(self, value): + if isinstance(value, types.MethodType) and value.im_self is None: + value = value.im_func # unbound method -> bare function if value not in self.function_signatures: raise TyperError("%r not in %r" % (value, self.s_pbc.prebuiltinstances)) @@ -132,12 +302,40 @@ def rtype_simple_call(self, hop): f, rinputs, rresult = self.function_signatures.itervalues().next() - vlist = hop.inputargs(self, *rinputs) + defaultclist = [] + if len(rinputs) != hop.nb_args-1: # argument count mismatch + assert not getattr(f._obj.graph, 'normalized_for_calls', False), ( + "normalization bug") + assert len(self.function_signatures) == 1, "normalization bug too" + func, = self.function_signatures.keys() + defaults = func.func_defaults or () + if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs): + rinputs = list(rinputs) + defaults = list(defaults) + while len(rinputs) != hop.nb_args-1: + c = hop.inputconst(rinputs.pop(), defaults.pop()) + defaultclist.insert(0, c) + else: + if hop.nb_args-1 > len(rinputs): + raise RTyperError("too many arguments in function call") + else: + raise RTyperError("not enough arguments in function call") + vlist = hop.inputargs(self, *rinputs) + defaultclist if self.lowleveltype == Void: assert len(self.function_signatures) == 1 vlist[0] = hop.inputconst(typeOf(f), f) - return hop.genop('direct_call', vlist, resulttype = rresult) + v = hop.genop('direct_call', vlist, resulttype = rresult) + return hop.llops.convertvar(v, rresult, hop.r_result) + def rtype_call_args(self, hop): + f, rinputs, rresult = self.function_signatures.itervalues().next() + # the function arguments may have been normalized by normalizecalls() + # already + if not f._obj.graph.normalized_for_calls: + assert False, "XXX do stuff here" + vlist = hop.inputargs(self, Void, *rinputs) + return hop.genop('direct_call', vlist[:1] + vlist[2:], + resulttype = rresult) # ____________________________________________________________ @@ -183,30 +381,36 @@ "methods can be found: %r" % ( s_pbc.prebuiltinstances,)) # the low-level representation is just the bound 'self' argument. - self.r_instance = rclass.getinstancerepr(rtyper, self.classdef) - self.lowleveltype = self.r_instance.lowleveltype + self.s_im_self = annmodel.SomeInstance(self.classdef) + self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) + self.lowleveltype = self.r_im_self.lowleveltype + + def convert_const(self, method): + if getattr(method, 'im_func', None) is None: + raise TyperError("not a bound method: %r" % method) + return self.r_im_self.convert_const(method.im_self) + + def get_method_from_instance(self, r_inst, v_inst, llops): + # The 'self' might have to be cast to a parent class + # (as shown for example in test_rclass/test_method_both_A_and_B) + return llops.convertvar(v_inst, r_inst, self.r_im_self) def rtype_simple_call(self, hop): - # XXX the graph of functions used as methods may need to be hacked - # XXX so that its 'self' argument accepts a pointer to an instance of - # XXX the common base class. This is needed to make the direct_call - # XXX below well-typed. - r_class = self.r_instance.rclass + r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] assert isinstance(r_func, FunctionsPBCRepr) - # - # XXX try to unify with FunctionsPBCRepr.rtype_simple_call() - f, rinputs, rresult = r_func.function_signatures.itervalues().next() - vlist = hop.inputargs(self, *rinputs[1:]) # ignore the self from r_func - if r_func.lowleveltype == Void: - assert len(r_func.function_signatures) == 1 - vfunc = hop.inputconst(typeOf(f), f) - else: - vinst = vlist[0] - vcls = self.r_instance.getfield(vinst, '__class__', hop.llops) - vfunc = r_class.getclsfield(vcls, self.methodname, hop.llops) - vlist.insert(0, vfunc) - return hop.genop('direct_call', vlist, resulttype = rresult) + s_func = r_func.s_pbc + + hop2 = hop.copy() + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' + hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + + v_im_self = hop.inputarg(self, arg=0) + v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) + v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) + hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' + # now hop2 looks like simple_call(function, self, args...) + return hop2.dispatch() # ____________________________________________________________ @@ -232,5 +436,37 @@ ## s_pbc.prebuiltinstances,)) def rtype_simple_call(self, hop): - return rclass.rtype_new_instance(self.s_pbc.const, hop) - # XXX call __init__ somewhere + klass = self.s_pbc.const + v_instance = rclass.rtype_new_instance(klass, hop) + try: + initfunc = klass.__init__.im_func + except AttributeError: + assert hop.nb_args == 1, ("arguments passed to __init__, " + "but no __init__!") + else: + if initfunc == Exception.__init__.im_func: + return v_instance # ignore __init__ and arguments completely + s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass) + s_init = annmodel.SomePBC({initfunc: True}) + hop2 = hop.copy() + hop2.r_s_popfirstarg() # discard the class pointer argument + hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' + c = Constant(initfunc) + hop2.v_s_insertfirstarg(c, s_init) # add 'initfunc' + hop2.s_result = annmodel.SomePBC({None: True}) + hop2.r_result = self.rtyper.getrepr(hop2.s_result) + # now hop2 looks like simple_call(initfunc, instance, args...) + hop2.dispatch() + return v_instance + +# ____________________________________________________________ + +def rtype_call_memo(hop): + memo_table = hop.args_v[0].value + fieldname = memo_table.fieldname + assert hop.nb_args == 2, "XXX" + + r_pbc = hop.args_r[1] + assert isinstance(r_pbc, MultipleFrozenPBCRepr) + v_table, v_pbc = hop.inputargs(Void, r_pbc) + return r_pbc.getfield(v_pbc, fieldname, hop.llops) Modified: pypy/branch/pycompiler/rpython/rptr.py ============================================================================== --- pypy/branch/pycompiler/rpython/rptr.py (original) +++ pypy/branch/pycompiler/rpython/rptr.py Fri Jul 1 18:30:34 2005 @@ -7,15 +7,15 @@ class __extend__(annmodel.SomePtr): def rtyper_makerepr(self, rtyper): - if self.is_constant() and not self.const: # constant NULL - return nullptr_repr - else: - return PtrRepr(self.ll_ptrtype) +## if self.is_constant() and not self.const: # constant NULL +## return nullptr_repr +## else: + return PtrRepr(self.ll_ptrtype) def rtyper_makekey(self): - if self.is_constant() and not self.const: - return None - else: - return self.ll_ptrtype +## if self.is_constant() and not self.const: +## return None +## else: + return self.ll_ptrtype class PtrRepr(Repr): @@ -83,18 +83,18 @@ # # Null Pointers -class NullPtrRepr(Repr): - lowleveltype = Void +##class NullPtrRepr(Repr): +## lowleveltype = Void - def rtype_is_true(self, hop): - return hop.inputconst(Bool, False) +## def rtype_is_true(self, hop): +## return hop.inputconst(Bool, False) -nullptr_repr = NullPtrRepr() +##nullptr_repr = NullPtrRepr() -class __extend__(pairtype(NullPtrRepr, PtrRepr)): - def convert_from_to((r_null, r_ptr), v, llops): - # nullptr to general pointer - return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) +##class __extend__(pairtype(NullPtrRepr, PtrRepr)): +## def convert_from_to((r_null, r_ptr), v, llops): +## # nullptr to general pointer +## return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) # ____________________________________________________________ # Modified: pypy/branch/pycompiler/rpython/rrange.py ============================================================================== --- pypy/branch/pycompiler/rpython/rrange.py (original) +++ pypy/branch/pycompiler/rpython/rrange.py Fri Jul 1 18:30:34 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr -from pypy.rpython.lltype import * +from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void # ____________________________________________________________ # @@ -33,8 +33,8 @@ class __extend__(pairtype(RangeRepr, IntegerRepr)): def rtype_getitem((r_rng, r_int), hop): - v_lst, v_index = hop.inputargs(r_lst, Signed) - cstep = hop.inputconst(Signed, self.step) + v_lst, v_index = hop.inputargs(r_rng, Signed) + cstep = hop.inputconst(Signed, r_rng.step) if hop.args_s[1].nonneg: llfn = ll_rangeitem_nonneg else: @@ -59,12 +59,7 @@ def ll_rangeitem(l, i, step): if i<0: - # XXX ack. cannot call ll_rangelen() here for now :-( - if step > 0: - length = (l.stop - l.start + (step-1)) // step - else: - length = (l.start - l.stop - (step+1)) // (-step) - #assert length >= 0 + length = ll_rangelen(l, step) i += length return l.start + i*step @@ -97,6 +92,8 @@ "XXX not implemented") #return hop.gendirectcall(ll_range2list, vstart, vstop, vstep) +rtype_builtin_xrange = rtype_builtin_range + # ____________________________________________________________ # # Iteration. Modified: pypy/branch/pycompiler/rpython/rslice.py ============================================================================== --- pypy/branch/pycompiler/rpython/rslice.py (original) +++ pypy/branch/pycompiler/rpython/rslice.py Fri Jul 1 18:30:34 2005 @@ -1,9 +1,9 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr import sys +from pypy.rpython.lltype import GcStruct, Signed, Ptr, Void,malloc # ____________________________________________________________ # Modified: pypy/branch/pycompiler/rpython/rstr.py ============================================================================== --- pypy/branch/pycompiler/rpython/rstr.py (original) +++ pypy/branch/pycompiler/rpython/rstr.py Fri Jul 1 18:30:34 2005 @@ -1,11 +1,18 @@ from weakref import WeakValueDictionary from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr -from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst +from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst, UniCharRepr from pypy.rpython.rarithmetic import intmask from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.rtuple import TupleRepr +from pypy.rpython import rint +from pypy.rpython.rslice import SliceRepr +from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc +from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf +from pypy.rpython.rclass import InstanceRepr + # ____________________________________________________________ # @@ -13,13 +20,11 @@ # # struct str { # hash: Signed -# chars: array { -# Char ch -# } +# chars: array of Char # } STR = GcStruct('str', ('hash', Signed), - ('chars', Array(('ch', Char)))) + ('chars', Array(Char))) class __extend__(annmodel.SomeString): @@ -34,8 +39,17 @@ def rtyper_makekey(self): return None +class __extend__(annmodel.SomeUnicodeCodePoint): + def rtyper_makerepr(self, rtyper): + return unichar_repr + def rtyper_makekey(self): + return None CONST_STR_CACHE = WeakValueDictionary() +string_repr = StringRepr() +char_repr = CharRepr() +unichar_repr = UniCharRepr() + class __extend__(StringRepr): lowleveltype = Ptr(STR) @@ -43,6 +57,7 @@ def convert_const(self, value): if value is None: return nullptr(STR) + value = getattr(value, '__self__', value) # for bound string methods if not isinstance(value, str): raise TyperError("not a str: %r" % (value,)) try: @@ -50,11 +65,14 @@ except KeyError: p = malloc(STR, len(value)) for i in range(len(value)): - p.chars[i].ch = value[i] + p.chars[i] = value[i] ll_strhash(p) # precompute the hash CONST_STR_CACHE[value] = p return p + def get_ll_eq_function(self): + return ll_streq + def rtype_len(_, hop): v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strlen, v_str) @@ -78,6 +96,47 @@ v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strhash, v_str) + def rtype_method_startswith(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_startswith, v_str, v_value) + + def rtype_method_endswith(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_endswith, v_str, v_value) + + def rtype_method_join(_, hop): + r_lst = hop.args_r[1] + s_item = r_lst.listitem.s_value + if s_item == annmodel.SomeImpossibleValue(): + return inputconst(string_repr, "") + elif not s_item.__class__ == annmodel.SomeString: + raise TyperError("join of non-string list: %r" % r_lst) + v_str, v_lst = hop.inputargs(string_repr, r_lst) + cname = inputconst(Void, "items") + v_items = hop.genop("getfield", [v_lst, cname], + resulttype=Ptr(GcArray(Ptr(STR)))) + return hop.gendirectcall(ll_join, v_str, v_items) + + def rtype_method_split(_, hop): + v_str, v_chr = hop.inputargs(string_repr, char_repr) + c = hop.inputconst(Void, hop.r_result.lowleveltype) + return hop.gendirectcall(ll_split_chr, c, v_str, v_chr) + + def rtype_method_replace(_, hop): + if not (hop.args_r[1] == char_repr and hop.args_r[2] == char_repr): + raise TyperError, 'replace only works for char args' + v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr) + return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2) + + def ll_str(s, r): + if typeOf(s) == Char: + return ll_chr2str(s) + else: + return s + ll_str = staticmethod(ll_str) + + def make_iterator_repr(self): + return string_iterator_repr class __extend__(pairtype(StringRepr, IntegerRepr)): def rtype_getitem(_, hop): @@ -88,6 +147,21 @@ llfn = ll_stritem return hop.gendirectcall(llfn, v_str, v_index) + def rtype_mod(_, hop): + return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) + + +class __extend__(pairtype(StringRepr, SliceRepr)): + + def rtype_getitem((r_str, r_slic), hop): + if r_slic == startonly_slice_repr: + v_str, v_start = hop.inputargs(r_str, startonly_slice_repr) + return hop.gendirectcall(ll_stringslice_startonly, v_str, v_start) + if r_slic == startstop_slice_repr: + v_str, v_slice = hop.inputargs(r_str, startstop_slice_repr) + return hop.gendirectcall(ll_stringslice, v_str, v_slice) + raise TyperError(r_slic) + class __extend__(pairtype(StringRepr, StringRepr)): def rtype_add(_, hop): @@ -95,8 +169,140 @@ return hop.gendirectcall(ll_strconcat, v_str1, v_str2) rtype_inplace_add = rtype_add + def rtype_eq(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_streq, v_str1, v_str2) + + def rtype_ne(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_streq, v_str1, v_str2) + return hop.genop('bool_not', [vres], resulttype=Bool) + + def rtype_lt(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_lt', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_le(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_le', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_ge(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_ge', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_gt(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_mod(_, hop): + return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) + +class __extend__(pairtype(StringRepr, CharRepr)): + def rtype_contains(_, hop): + v_str, v_chr = hop.inputargs(string_repr, char_repr) + return hop.gendirectcall(ll_contains, v_str, v_chr) + +def parse_fmt_string(fmt): + # we support x, d, s, 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 = '' + assert f in 'xdsrf' + + 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) + + for i, thing in enumerate(things): + if isinstance(thing, tuple): + code = thing[0] + vitem, r_arg = argsiter.next() + rep = inputconst(Void, r_arg) + if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) + elif code == 'd': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) + elif code == 'f': + #assert isinstance(r_arg, FloatRepr) + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) + elif code == 'x': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, + inputconst(Bool, False)) + else: + assert 0 + else: + vchunk = inputconst(string_repr, thing) + i = inputconst(Signed, i) + hop.genop('setarrayitem', [vtemp, i, vchunk]) + + return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp) + + +class __extend__(pairtype(StringRepr, TupleRepr)): + def rtype_mod(_, hop): + r_tuple = hop.args_r[1] + v_tuple = hop.args_v[1] + + sourcevars = [] + for fname, r_arg in zip(r_tuple.fieldnames, r_tuple.items_r): + cname = hop.inputconst(Void, fname) + vitem = hop.genop("getfield", [v_tuple, cname], + resulttype=r_arg) + sourcevars.append((vitem, r_arg)) + + return do_stringformat(hop, sourcevars) + + class __extend__(CharRepr): + def convert_const(self, value): + if not isinstance(value, str) or len(value) != 1: + raise TyperError("not a character: %r" % (value,)) + return value + + def get_ll_eq_function(self): + return None + def rtype_len(_, hop): return hop.inputconst(Signed, 1) @@ -108,6 +314,70 @@ vlist = hop.inputargs(char_repr) return hop.genop('cast_char_to_int', vlist, resulttype=Signed) + def rtype_method_isspace(_, hop): + vlist = hop.inputargs(char_repr) + return hop.gendirectcall(ll_char_isspace, vlist[0]) + +class __extend__(pairtype(CharRepr, IntegerRepr)): + + def rtype_mul(_, hop): + v_char, v_int = hop.inputargs(char_repr, Signed) + return hop.gendirectcall(ll_char_mul, v_char, v_int) + rtype_inplace_mul = rtype_mul + +class __extend__(pairtype(CharRepr, CharRepr)): + def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') + def rtype_ne(_, hop): return _rtype_compare_template(hop, 'ne') + def rtype_lt(_, hop): return _rtype_compare_template(hop, 'lt') + def rtype_le(_, hop): return _rtype_compare_template(hop, 'le') + def rtype_gt(_, hop): return _rtype_compare_template(hop, 'gt') + def rtype_ge(_, hop): return _rtype_compare_template(hop, 'ge') + +#Helper functions for comparisons + +def _rtype_compare_template(hop, func): + vlist = hop.inputargs(char_repr, char_repr) + return hop.genop('char_'+func, vlist, resulttype=Bool) + +class __extend__(UniCharRepr): + + def convert_const(self, value): + if not isinstance(value, unicode) or len(value) != 1: + raise TyperError("not a unicode character: %r" % (value,)) + return value + + def get_ll_eq_function(self): + return None + +## def rtype_len(_, hop): +## return hop.inputconst(Signed, 1) +## +## def rtype_is_true(_, hop): +## assert not hop.args_s[0].can_be_None +## return hop.inputconst(Bool, True) + + def rtype_ord(_, hop): + vlist = hop.inputargs(unichar_repr) + return hop.genop('cast_unichar_to_int', vlist, resulttype=Signed) + + +class __extend__(pairtype(UniCharRepr, UniCharRepr)): + def rtype_eq(_, hop): return _rtype_unchr_compare_template(hop, 'eq') + def rtype_ne(_, hop): return _rtype_unchr_compare_template(hop, 'ne') +## def rtype_lt(_, hop): return _rtype_unchr_compare_template(hop, 'lt') +## def rtype_le(_, hop): return _rtype_unchr_compare_template(hop, 'le') +## def rtype_gt(_, hop): return _rtype_unchr_compare_template(hop, 'gt') +## def rtype_ge(_, hop): return _rtype_unchr_compare_template(hop, 'ge') + +#Helper functions for comparisons + +def _rtype_unchr_compare_template(hop, func): + vlist = hop.inputargs(unichar_repr, unichar_repr) + return hop.genop('unichar_'+func, vlist, resulttype=Bool) + + +# +# _________________________ Conversions _________________________ class __extend__(pairtype(CharRepr, StringRepr)): def convert_from_to((r_from, r_to), v, llops): @@ -122,16 +392,17 @@ return llops.gendirectcall(ll_stritem_nonneg, v, c_zero) return NotImplemented - -string_repr = StringRepr() -char_repr = CharRepr() - -# -# _________________________ Conversions _________________________ - -##class __extend__(pairtype(PyObjRepr, StringRepr)): -## def convert_from_to((r_from, r_to), v, llops): -## XXX +class __extend__(pairtype(PyObjRepr, StringRepr)): + def convert_from_to((r_from, r_to), v, llops): + v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed) + cstr = inputconst(Void, STR) + v_result = llops.genop('malloc_varsize', [cstr, v_len], + resulttype=Ptr(STR)) + cchars = inputconst(Void, "chars") + v_chars = llops.genop('getsubstruct', [v_result, cchars], + resulttype=Ptr(STR.chars)) + llops.gencapicall('PyString_ToLLCharArray', [v, v_chars]) + return v_result class __extend__(pairtype(StringRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): @@ -141,11 +412,8 @@ resulttype=Ptr(STR.chars)) v_size = llops.genop('getarraysize', [v_chars], resulttype=Signed) - czero = inputconst(Signed, 0) - v_char0ptr = llops.genop('getarraysubstruct', [v_chars, czero], - resulttype=Ptr(STR.chars.OF)) - return llops.gencapicall('PyString_FromStringAndSize_Hack', - [v_char0ptr, v_size], + return llops.gencapicall('PyString_FromLLCharArrayAndSize', + [v_chars, v_size], resulttype=pyobj_repr) # ____________________________________________________________ @@ -153,17 +421,31 @@ # Low-level methods. These can be run for testing, but are meant to # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. +# +def ll_char_isspace(ch): + # XXX: + #return ord(ch) in (9, 10, 11, 12, 13, 32) + c = ord(ch) + return 9 <= c <= 13 or c == 32 + +def ll_char_mul(ch, times): + newstr = malloc(STR, times) + j = 0 + while j < times: + newstr.chars[j] = ch + j += 1 + return newstr def ll_strlen(s): return len(s.chars) def ll_stritem_nonneg(s, i): - return s.chars[i].ch + return s.chars[i] def ll_stritem(s, i): - if i<0: + if i < 0: i += len(s.chars) - return s.chars[i].ch + return s.chars[i] def ll_str_is_true(s): # check if a string is True, allowing for None @@ -171,7 +453,7 @@ def ll_chr2str(ch): s = malloc(STR, 1) - s.chars[0].ch = ch + s.chars[0] = ch return s def ll_strhash(s): @@ -184,10 +466,10 @@ if length == 0: x = -1 else: - x = ord(s.chars[0].ch) << 7 - i = 1 + x = ord(s.chars[0]) << 7 + i = 0 while i < length: - x = (1000003*x) ^ ord(s.chars[i].ch) + x = (1000003*x) ^ ord(s.chars[i]) i += 1 x ^= length if x == 0: @@ -201,13 +483,240 @@ newstr = malloc(STR, len1 + len2) j = 0 while j < len1: - newstr.chars[j].ch = s1.chars[j].ch + newstr.chars[j] = s1.chars[j] j += 1 i = 0 while i < len2: - newstr.chars[j].ch = s2.chars[i].ch + newstr.chars[j] = s2.chars[i] i += 1 j += 1 return newstr - +def ll_strcmp(s1, s2): + chars1 = s1.chars + chars2 = s2.chars + len1 = len(chars1) + len2 = len(chars2) + + if len1 < len2: + cmplen = len1 + else: + cmplen = len2 + i = 0 + while i < cmplen: + diff = ord(chars1[i]) - ord(chars2[i]) + if diff != 0: + return diff + i += 1 + return len1 - len2 + +def ll_streq(s1, s2): + len1 = len(s1.chars) + len2 = len(s2.chars) + 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 + +emptystr = string_repr.convert_const("") + +def ll_join(s, items): + s_chars = s.chars + s_len = len(s_chars) + num_items = len(items) + if num_items == 0: + return emptystr + itemslen = 0 + i = 0 + while i < num_items: + itemslen += len(items[i].chars) + i += 1 + result = malloc(STR, itemslen + s_len * (num_items - 1)) + res_chars = result.chars + res_index = 0 + i = 0 + item_chars = items[i].chars + item_len = len(item_chars) + j = 0 + while j < item_len: + res_chars[res_index] = item_chars[j] + j += 1 + res_index += 1 + i += 1 + while i < num_items: + j = 0 + while j < s_len: + res_chars[res_index] = s_chars[j] + j += 1 + res_index += 1 + + item_chars = items[i].chars + item_len = len(item_chars) + j = 0 + while j < item_len: + res_chars[res_index] = item_chars[j] + j += 1 + res_index += 1 + i += 1 + return result + +def ll_stringslice_startonly(s1, start): + len1 = len(s1.chars) + newstr = malloc(STR, len1 - start) + j = 0 + while start < len1: + newstr.chars[j] = s1.chars[start] + start += 1 + j += 1 + return newstr + +def ll_stringslice(s1, slice): + start = slice.start + stop = slice.stop + newstr = malloc(STR, stop - start) + j = 0 + while start < stop: + newstr.chars[j] = s1.chars[start] + start += 1 + j += 1 + return newstr + +def ll_split_chr(LISTPTR, s, c): + chars = s.chars + strlen = len(chars) + count = 1 + i = 0 + while i < strlen: + if chars[i] == c: + count += 1 + i += 1 + res = malloc(LISTPTR.TO) + items = res.items = malloc(LISTPTR.TO.items.TO, count) + + i = 0 + j = 0 + resindex = 0 + while j < strlen: + if chars[j] == c: + item = items[resindex] = malloc(STR, j - i) + newchars = item.chars + k = i + while k < j: + newchars[k - i] = chars[k] + k += 1 + resindex += 1 + i = j + 1 + j += 1 + item = items[resindex] = malloc(STR, j - i) + newchars = item.chars + k = i + while k < j: + newchars[k - i] = chars[k] + k += 1 + resindex += 1 + + return res + +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 + +# ____________________________________________________________ +# +# Iteration. + +class StringIteratorRepr(Repr): + lowleveltype = Ptr(GcStruct('stringiter', + ('string', string_repr.lowleveltype), + ('index', Signed))) + def newiter(self, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_striter, v_str) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + return hop.gendirectcall(ll_strnext, v_iter) + +string_iterator_repr = StringIteratorRepr() + +def ll_striter(string): + iter = malloc(string_iterator_repr.lowleveltype.TO) + iter.string = string + iter.index = 0 + return iter + +def ll_strnext(iter): + chars = iter.string.chars + index = iter.index + if index >= len(chars): + raise StopIteration + iter.index = index + 1 + return chars[index] + +# 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>") + +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/branch/pycompiler/rpython/rtuple.py ============================================================================== --- pypy/branch/pycompiler/rpython/rtuple.py (original) +++ pypy/branch/pycompiler/rpython/rtuple.py Fri Jul 1 18:30:34 2005 @@ -1,9 +1,9 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed, malloc # ____________________________________________________________ # @@ -19,6 +19,7 @@ class __extend__(annmodel.SomeTuple): def rtyper_makerepr(self, rtyper): return TupleRepr([rtyper.getrepr(s_item) for s_item in self.items]) + def rtyper_makekey(self): keys = [s_item.rtyper_makekey() for s_item in self.items] return tuple(keys) @@ -40,10 +41,50 @@ setattr(p, name, r.convert_const(obj)) return p + #def get_eqfunc(self): + # return inputconst(Void, self.item_repr.get_ll_eq_function()) + def rtype_len(self, hop): return hop.inputconst(Signed, len(self.items_r)) - + def rtype_bltn_list(self, hop): + from pypy.rpython import rlist + nitems = len(self.items_r) + vtup = hop.inputarg(self, 0) + c1 = inputconst(Void, hop.r_result.lowleveltype) + c2 = inputconst(Signed, nitems) + vlist = hop.gendirectcall(rlist.ll_newlist, c1, c2) + for index in range(nitems): + name = self.fieldnames[index] + ritem = self.items_r[index] + cname = hop.inputconst(Void, name) + vitem = hop.genop('getfield', [vtup, cname], resulttype = ritem) + vitem = hop.llops.convertvar(vitem, ritem, hop.r_result.item_repr) + cindex = inputconst(Signed, index) + hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem) + return vlist + +class __extend__(pairtype(TupleRepr, Repr)): + def rtype_contains((r_tup, r_item), hop): + v_tup = hop.args_v[0] + if not isinstance(v_tup, Constant): + raise TyperError("contains() on non-const tuple") + t = v_tup.value + typ = type(t[0]) + for x in t[1:]: + if type(x) is not typ: + raise TyperError("contains() on mixed-type tuple " + "constant %r" % (v_tup,)) + d = {} + for x in t: + d[x] = None + hop2 = hop.copy() + _, _ = hop2.r_s_popfirstarg() + v_dict = Constant(d) + s_dict = hop.rtyper.annotator.bookkeeper.immutablevalue(d) + hop2.v_s_insertfirstarg(v_dict, s_dict) + return hop2.dispatch() + class __extend__(pairtype(TupleRepr, IntegerRepr)): def rtype_getitem((r_tup, r_int), hop): @@ -56,12 +97,23 @@ cname = hop.inputconst(Void, name) return hop.genop('getfield', [v_tuple, cname], resulttype = llresult) +class __extend__(pairtype(TupleRepr, TupleRepr)): + + def rtype_add((r_tup1, r_tup2), hop): + v_tuple, v_tuple1 = hop.inputargs(r_tup1.items_r, r_tup2.items_r) + items_r = r_tup1.items_r + r_tup2.items_r + res = TupleRepr(items_r) + vlist = v_tuple + v_tuple1 + return newtuple(hop.llops, res, vlist) + rtype_inplace_add = rtype_add + + # ____________________________________________________________ # # Irregular operations. def newtuple(llops, r_tuple, items_v): - c1 = inputconst(Void, r_tuple.lowleveltype) + c1 = inputconst(Void, r_tuple.lowleveltype.TO) v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) for i in range(len(r_tuple.items_r)): cname = inputconst(Void, r_tuple.fieldnames[i]) Modified: pypy/branch/pycompiler/rpython/rtyper.py ============================================================================== --- pypy/branch/pycompiler/rpython/rtyper.py (original) +++ pypy/branch/pycompiler/rpython/rtyper.py Fri Jul 1 18:30:34 2005 @@ -1,11 +1,27 @@ +""" +RTyper: converts high-level operations into low-level operations in flow graphs. + +The main class, with code to walk blocks and dispatch individual operations +to the care of the rtype_*() methods implemented in the other r* modules. +For each high-level operation 'hop', the rtype_*() methods produce low-level +operations that are collected in the 'llops' list defined here. When necessary, +conversions are inserted. + +This logic borrows a bit from pypy.translator.annrpython, without the fixpoint +computation part. +""" + +from __future__ import generators import sys +import py from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, last_exception from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType -from pypy.rpython.lltype import FuncType, functionptr, typeOf +from pypy.rpython.lltype import FuncType, functionptr, typeOf, RuntimeTypeInfo +from pypy.rpython.lltype import attachRuntimeTypeInfo, Primitive from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr @@ -13,14 +29,10 @@ from pypy.rpython.annlowlevel import annotate_lowlevel_helper from pypy.rpython.exceptiondata import ExceptionData - -debug = False +log = py.log.Producer("rtyper") +py.log.setconsumer("rtyper", None) crash_on_first_typeerror = True -# XXX copied from pypy.translator.typer and modified. -# We'll remove pypy.translator.typer at some point. -# It also borrows a bit from pypy.translator.annrpython. - class RPythonTyper: def __init__(self, annotator): @@ -30,12 +42,14 @@ self.specialized_ll_functions = {} self.class_reprs = {} self.instance_reprs = {} + self.pbc_reprs = {} self.typererror = None # make the primitive_to_repr constant mapping self.primitive_to_repr = {} for s_primitive, lltype in annmodel.annotation_to_ll_map: r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r + self.exceptiondata = ExceptionData(self) def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -89,8 +103,8 @@ self.call_all_setups() specialize_more_blocks() - self.exceptiondata = ExceptionData(self) - specialize_more_blocks() + self.exceptiondata.make_helpers(self) + specialize_more_blocks() # for the helpers just made if self.typererror: exc, value, tb = self.typererror @@ -104,17 +118,51 @@ def call_all_setups(self): # make sure all reprs so far have had their setup() called + must_setup_more = [] while self.reprs_must_call_setup: - self.reprs_must_call_setup.pop().setup() + r = self.reprs_must_call_setup.pop() + r.setup() + must_setup_more.append(r) + for r in must_setup_more: + r.setup_final_touch() def setconcretetype(self, v): assert isinstance(v, Variable) v.concretetype = self.bindingrepr(v).lowleveltype + def typedconstant(self, c, using_repr=None): + """Make a copy of the Constant 'c' and give it a concretetype.""" + assert isinstance(c, Constant) + if using_repr is None: + using_repr = self.bindingrepr(c) + if not hasattr(c, 'concretetype'): + c = inputconst(using_repr, c.value) + else: + if c.concretetype != Void: + assert typeOf(c.value) == using_repr.lowleveltype + return c + + def setup_block_entry(self, block): + if block.operations == () and len(block.inputargs) == 2: + # special case for exception blocks: force them to return an + # exception type and value in a standardized format + v1, v2 = block.inputargs + v1.concretetype = self.exceptiondata.lltype_of_exception_type + v2.concretetype = self.exceptiondata.lltype_of_exception_value + return [self.exceptiondata.r_exception_type, + self.exceptiondata.r_exception_value] + else: + # normal path + result = [] + for a in block.inputargs: + r = self.bindingrepr(a) + a.concretetype = r.lowleveltype + result.append(r) + return result + def specialize_block(self, block): # give the best possible types to the input args - for a in block.inputargs: - self.setconcretetype(a) + self.setup_block_entry(block) # specialize all the operations, as far as possible if block.operations == (): # return or except block @@ -124,12 +172,11 @@ for v in block.getvariables(): varmapping[v] = v # records existing Variables - for op in block.operations: + for hop in self.highlevelops(block, newops): try: - hop = HighLevelOp(self, op, newops) self.translate_hl_to_ll(hop, varmapping) except TyperError, e: - self.gottypererror(e, block, op, newops) + self.gottypererror(e, block, hop.spaceop, newops) return # cannot continue this block: no op.result.concretetype block.operations[:] = newops @@ -147,15 +194,27 @@ assert block.exitswitch == Constant(last_exception) r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) - for a in [link.last_exception, link.last_exc_value]: - if isinstance(a, Variable): - self.setconcretetype(a) + + a = link.last_exception + if isinstance(a, Variable): + a.concretetype = self.exceptiondata.lltype_of_exception_type + elif isinstance(a, Constant): + link.last_exception = self.typedconstant( + a, using_repr=self.exceptiondata.r_exception_type) + + a = link.last_exc_value + if isinstance(a, Variable): + a.concretetype = self.exceptiondata.lltype_of_exception_value + elif isinstance(a, Constant): + link.last_exc_value = self.typedconstant( + a, using_repr=self.exceptiondata.r_exception_value) + + inputargs_reprs = self.setup_block_entry(link.target) for i in range(len(link.args)): a1 = link.args[i] - a2 = link.target.inputargs[i] - r_a2 = self.bindingrepr(a2) + r_a2 = inputargs_reprs[i] if isinstance(a1, Constant): - link.args[i] = inputconst(r_a2, a1.value) + link.args[i] = self.typedconstant(a1, using_repr=r_a2) continue # the Constant was typed, done r_a1 = self.bindingrepr(a1) if r_a1 == r_a2: @@ -179,34 +238,49 @@ block.operations.extend(newops) link.args[i] = a1 + def highlevelops(self, block, llops): + # enumerate the HighLevelOps in a block. + if block.operations: + for op in block.operations[:-1]: + yield HighLevelOp(self, op, [], llops) + # look for exception links for the last operation + if block.exitswitch == Constant(last_exception): + exclinks = block.exits[1:] + else: + exclinks = [] + yield HighLevelOp(self, block.operations[-1], exclinks, llops) + def translate_hl_to_ll(self, hop, varmapping): - if debug: - print hop.spaceop.opname, hop.args_s + log.translating(hop.spaceop.opname, hop.args_s) + resultvar = hop.dispatch() op = hop.spaceop - translate_meth = getattr(self, 'translate_op_'+op.opname, - self.missing_operation) - resultvar = translate_meth(hop) if resultvar is None: # no return value if hop.s_result != annmodel.SomeImpossibleValue(): raise TyperError("the annotator doesn't agree that '%s' " "has no return value" % op.opname) op.result.concretetype = Void - elif isinstance(resultvar, Variable): + else: + assert isinstance(resultvar, (Variable, Constant)) # for simplicity of the translate_meth, resultvar is usually not # op.result here. We have to replace resultvar with op.result # in all generated operations. + if hop.s_result.is_constant(): + if isinstance(resultvar, Constant) and \ + isinstance(hop.r_result.lowleveltype, Primitive): + assert resultvar.value == hop.s_result.const resulttype = resultvar.concretetype op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: raise TyperError("inconsistent type for the result of '%s':\n" - "annotator says %s,\n" - "whose lltype is %r\n" - "but rtype* says %r" % ( + "annotator says %s,\n" + "whose repr is %r\n" + "but rtype_%s returned %r" % ( op.opname, hop.s_result, - op.result.concretetype, resulttype)) + hop.r_result, op.opname, resulttype)) # figure out if the resultvar is a completely fresh Variable or not - if (resultvar not in self.annotator.bindings and + if (isinstance(resultvar, Variable) and + resultvar not in self.annotator.bindings and resultvar not in varmapping): # fresh Variable: rename it to the previously existing op.result varmapping[resultvar] = op.result @@ -214,18 +288,6 @@ # renaming unsafe. Insert a 'same_as' operation... hop.llops.append(SpaceOperation('same_as', [resultvar], op.result)) - else: - # translate_meth() returned a Constant - assert isinstance(resultvar, Constant) - if not hop.s_result.is_constant(): - raise TyperError("the annotator doesn't agree that '%s' " - "returns a constant" % op.opname) - if resultvar.value != hop.s_result.const: - raise TyperError("constant mismatch: %r vs %r" % ( - resultvar.value, hop.s_result.const)) - op.result.concretetype = hop.r_result.lowleveltype - hop.llops.append(SpaceOperation('same_as', [resultvar], - op.result)) def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. @@ -261,11 +323,20 @@ _registeroperations(locals()) del _registeroperations + # this one is not in BINARY_OPERATIONS + def translate_op_contains(self, hop): + r_arg1 = hop.args_r[0] + r_arg2 = hop.args_r[1] + return pair(r_arg1, r_arg2).rtype_contains(hop) + # __________ irregular operations __________ def translate_op_newlist(self, hop): return rlist.rtype_newlist(hop) + def translate_op_newdict(self, hop): + return rdict.rtype_newdict(hop) + def translate_op_alloc_and_set(self, hop): return rlist.rtype_alloc_and_set(hop) @@ -275,6 +346,9 @@ def translate_op_newslice(self, hop): return rslice.rtype_newslice(hop) + def translate_op_call_memo(self, hop): + return rpbc.rtype_call_memo(hop) + def missing_operation(self, hop): raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname) @@ -285,23 +359,52 @@ return self.bindingrepr(v).lowleveltype return getfunctionptr(self.annotator.translator, func, getconcretetype) + def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): + self.call_all_setups() # compute ForwardReferences now + if ARG_GCSTRUCT is None: + ARG_GCSTRUCT = GCSTRUCT + args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] + s, spec_function = annotate_lowlevel_helper(self.annotator, + func, args_s) + if (not isinstance(s, annmodel.SomePtr) or + s.ll_ptrtype != Ptr(RuntimeTypeInfo)): + raise TyperError("runtime type info function %r returns %r, " + "excepted Ptr(RuntimeTypeInfo)" % (func, s)) + funcptr = self.getfunctionptr(spec_function) + attachRuntimeTypeInfo(GCSTRUCT, funcptr) # ____________________________________________________________ -class HighLevelOp: - nb_popped = 0 +class HighLevelOp(object): - def __init__(self, rtyper, spaceop, llops): + def __init__(self, rtyper, spaceop, exceptionlinks, llops): self.rtyper = rtyper self.spaceop = spaceop self.nb_args = len(spaceop.args) self.llops = llops + self.args_v = list(spaceop.args) self.args_s = [rtyper.binding(a) for a in spaceop.args] self.s_result = rtyper.binding(spaceop.result) self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] self.r_result = rtyper.getrepr(self.s_result) rtyper.call_all_setups() # compute ForwardReferences now + self.exceptionlinks = exceptionlinks + + def copy(self): + result = HighLevelOp.__new__(HighLevelOp) + for key, value in self.__dict__.items(): + if type(value) is list: # grunt + value = value[:] + setattr(result, key, value) + return result + + def dispatch(self): + op = self.spaceop + rtyper = self.rtyper + translate_meth = getattr(rtyper, 'translate_op_'+op.opname, + rtyper.missing_operation) + return translate_meth(self) def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, @@ -311,7 +414,7 @@ """ if not isinstance(converted_to, Repr): converted_to = self.rtyper.primitive_to_repr[converted_to] - v = self.spaceop.args[self.nb_popped + arg] + v = self.args_v[arg] if isinstance(v, Constant): return inputconst(converted_to, v.value) assert hasattr(v, 'concretetype') @@ -326,9 +429,10 @@ inputconst = staticmethod(inputconst) # export via the HighLevelOp class def inputargs(self, *converted_to): - assert len(converted_to) == self.nb_args, ( - "operation argument count mismatch: '%s' has %d+%d arguments" % ( - self.spaceop.opname, self.nb_popped, self.nb_args)) + if len(converted_to) != self.nb_args: + raise TyperError("operation argument count mismatch:\n" + "'%s' has %d arguments, rtyper wants %d" % ( + self.spaceop.opname, self.nb_args, len(converted_to))) vars = [] for i in range(len(converted_to)): vars.append(self.inputarg(converted_to[i], i)) @@ -342,10 +446,23 @@ def r_s_popfirstarg(self): "Return and discard the first argument." - self.nb_popped += 1 self.nb_args -= 1 + self.args_v.pop(0) return self.args_r.pop(0), self.args_s.pop(0) + def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg): + r_newfirstarg = self.rtyper.getrepr(s_newfirstarg) + self.args_v.insert(0, v_newfirstarg) + self.args_r.insert(0, r_newfirstarg) + self.args_s.insert(0, s_newfirstarg) + self.nb_args += 1 + + def has_implicit_exception(self, exc_cls): + for link in self.exceptionlinks: + if issubclass(exc_cls, link.exitcase): + return True + return False + # ____________________________________________________________ class LowLevelOpList(list): @@ -356,7 +473,7 @@ self.rtyper = rtyper def convertvar(self, v, r_from, r_to): - assert isinstance(v, Variable) + assert isinstance(v, (Variable, Constant)) if r_from != r_to: v = pair(r_from, r_to).convert_from_to(v, self) if v is NotImplemented: @@ -403,12 +520,12 @@ return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) - def gencapicall(self, cfnname, args_v, resulttype=None): + def gencapicall(self, cfnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) - f = functionptr(FUNCTYPE, cfnname, external="C") + f = functionptr(FUNCTYPE, cfnname, external="C", **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype) @@ -419,6 +536,6 @@ from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rslice -from pypy.rpython import rlist, rstr, rtuple +from pypy.rpython import rlist, rstr, rtuple, rdict from pypy.rpython import rclass, rbuiltin, rpbc from pypy.rpython import rptr Modified: pypy/branch/pycompiler/rpython/test/test_llann.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_llann.py (original) +++ pypy/branch/pycompiler/rpython/test/test_llann.py Fri Jul 1 18:30:34 2005 @@ -258,3 +258,25 @@ assert a.binding(vp).ll_ptrtype == T assert a.binding(rv) == annmodel.lltype_to_annotation(T.TO.OF) return a, vTs + + def test_getRuntimeTypeInfo(self): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def llf(): + return getRuntimeTypeInfo(S) + a = self.RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llf, []) + assert isinstance(s, annmodel.SomePtr) + assert s.ll_ptrtype == Ptr(RuntimeTypeInfo) + assert s.const == getRuntimeTypeInfo(S) + + def test_runtime_type_info(self): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def llf(p): + return runtime_type_info(p) + a = self.RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(Ptr(S))]) + assert isinstance(s, annmodel.SomePtr) + assert s.ll_ptrtype == Ptr(RuntimeTypeInfo) + Modified: pypy/branch/pycompiler/rpython/test/test_lltype.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_lltype.py (original) +++ pypy/branch/pycompiler/rpython/test/test_lltype.py Fri Jul 1 18:30:34 2005 @@ -338,3 +338,50 @@ del p p = cast_pointer(Ptr(S), p1) assert p.s1.x == 5 + +def test_getRuntimeTypeInfo(): + S = GcStruct('s', ('x', Signed)) + py.test.raises(ValueError, "getRuntimeTypeInfo(S)") + pinf0 = attachRuntimeTypeInfo(S) + assert pinf0._obj.about == S + pinf = getRuntimeTypeInfo(S) + assert pinf == pinf0 + pinf1 = getRuntimeTypeInfo(S) + assert pinf == pinf1 + Z = GcStruct('z', ('x', Unsigned)) + attachRuntimeTypeInfo(Z) + assert getRuntimeTypeInfo(Z) != pinf0 + Sbis = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(Sbis) + assert getRuntimeTypeInfo(Sbis) != pinf0 + assert Sbis != S # the attached runtime type info distinguishes them + +def test_runtime_type_info(): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + s = malloc(S) + assert runtime_type_info(s) == getRuntimeTypeInfo(S) + S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + attachRuntimeTypeInfo(S1) + s1 = malloc(S1) + assert runtime_type_info(s1) == getRuntimeTypeInfo(S1) + assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) + assert runtime_type_info(cast_pointer(Ptr(S), s1)) == getRuntimeTypeInfo(S1) + def dynamic_type_info_S(p): + if p.x == 0: + return getRuntimeTypeInfo(S) + else: + return getRuntimeTypeInfo(S1) + fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)), + "dynamic_type_info_S", + _callable=dynamic_type_info_S) + attachRuntimeTypeInfo(S, fp) + assert s.x == 0 + assert runtime_type_info(s) == getRuntimeTypeInfo(S) + s.x = 1 + py.test.raises(RuntimeError, "runtime_type_info(s)") + assert s1.sub.x == 0 + py.test.raises(RuntimeError, "runtime_type_info(s1.sub)") + s1.sub.x = 1 + assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) + Modified: pypy/branch/pycompiler/rpython/test/test_normalizecalls.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_normalizecalls.py (original) +++ pypy/branch/pycompiler/rpython/test/test_normalizecalls.py Fri Jul 1 18:30:34 2005 @@ -36,3 +36,22 @@ assert s_l1.__class__ == annmodel.SomeString # and not SomeChar assert s_l2.__class__ == annmodel.SomeString # and not SomeChar #translator.view() + +def test_normalize_keyword_call(): + def f1(a, b): + return (a, b, 0, 0) + def f2(b, c=123, a=456, d=789): + return (a, b, c, d) + def g(n): + if n > 0: + f = f1 + else: + f = f2 + f(a=5, b=6) + + translator = rtype(g, [int]) + f1graph = translator.getflowgraph(f1) + f2graph = translator.getflowgraph(f2) + assert len(f1graph.getargs()) == 2 + assert len(f2graph.getargs()) == 2 # normalized to the common call pattern + #translator.view() Modified: pypy/branch/pycompiler/rpython/test/test_rbool.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rbool.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rbool.py Fri Jul 1 18:30:34 2005 @@ -1,7 +1,9 @@ from pypy.translator.translator import Translator +from pypy.rpython.lltype import pyobjectptr from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import interpret class TestSnippet(object): @@ -36,3 +38,13 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + + def test_bool2int(self): + def f(n): + if n: + n = 2 + return n + res = interpret(f, [False]) + assert res == 0 and res is not False # forced to int by static typing + res = interpret(f, [True]) + assert res == 2 Modified: pypy/branch/pycompiler/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rclass.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rclass.py Fri Jul 1 18:30:34 2005 @@ -1,16 +1,6 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * -from pypy.rpython.rtyper import RPythonTyper - - -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - return t +from pypy.rpython.test.test_llinterp import interpret class EmptyBase(object): @@ -21,7 +11,9 @@ def dummyfn(): x = EmptyBase() return x - rtype(dummyfn) + res = interpret(dummyfn, []) + T = typeOf(res) + assert isinstance(T, Ptr) and isinstance(T.TO, GcStruct) def test_instanceattr(): def dummyfn(): @@ -29,8 +21,8 @@ x.a = 5 x.a += 1 return x.a - rtype(dummyfn) - + res = interpret(dummyfn, []) + assert res == 6 class Random: xyzzy = 12 @@ -40,11 +32,105 @@ def dummyfn(): x = Random() return x.xyzzy - rtype(dummyfn) + res = interpret(dummyfn, []) + assert res == 12 def test_classattr_as_defaults(): def dummyfn(): x = Random() x.xyzzy += 1 return x.xyzzy - rtype(dummyfn) + res = interpret(dummyfn, []) + assert res == 13 + +def test_prebuilt_instance(): + a = EmptyBase() + a.x = 5 + def dummyfn(): + a.x += 1 + return a.x + interpret(dummyfn, []) + +def test_recursive_prebuilt_instance(): + a = EmptyBase() + b = EmptyBase() + a.x = 5 + b.x = 6 + a.peer = b + b.peer = a + def dummyfn(): + return a.peer.peer.peer.x + res = interpret(dummyfn, []) + assert res == 6 + +# method calls +class A: + def f(self): + return self.g() + + def g(self): + return 42 + +class B(A): + def g(self): + return 1 + +class C(B): + pass + +def test_simple_method_call(): + def f(i): + if i: + a = A() + else: + a = B() + return a.f() + res = interpret(f, [True]) + assert res == 42 + res = interpret(f, [False]) + assert res == 1 + +def test_isinstance(): + def a(): + b = B() + return isinstance(b, A) + def b(): + b = B() + return isinstance(b, B) + def c(): + b = B() + return isinstance(b, C) + + res = interpret(a, []) + assert res is True + + res = interpret(b, []) + assert res is True + + res = interpret(c, []) + assert res is False + +def test_method_used_in_subclasses_only(): + class A: + def meth(self): + return 123 + class B(A): + pass + def f(): + x = B() + return x.meth() + res = interpret(f, []) + assert res == 123 + +def test_method_both_A_and_B(): + class A: + def meth(self): + return 123 + class B(A): + pass + def f(): + a = A() + b = B() + return a.meth() + b.meth() + res = interpret(f, []) + assert res == 246 Modified: pypy/branch/pycompiler/rpython/test/test_rfloat.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rfloat.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rfloat.py Fri Jul 1 18:30:34 2005 @@ -2,6 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import interpret class TestSnippet(object): @@ -36,3 +37,13 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + +def test_int_conversion(): + def fn(f): + return int(f) + + res = interpret(fn, [1.0]) + assert res == 1 + assert type(res) is int + res = interpret(fn, [2.34]) + assert res == fn(2.34) Modified: pypy/branch/pycompiler/rpython/test/test_rint.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rint.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rint.py Fri Jul 1 18:30:34 2005 @@ -2,6 +2,8 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.rarithmetic import r_uint class TestSnippet(object): @@ -36,3 +38,53 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + + +def test_char_constant(): + def dummyfn(i): + return chr(i) + res = interpret(dummyfn, [ord(' ')]) + assert res == ' ' + res = interpret(dummyfn, [0]) + assert res == '\0' + res = interpret(dummyfn, [ord('a')]) + assert res == 'a' + +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' + +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_unsigned(): + def dummy(i): + i = r_uint(i) + j = r_uint(12) + return i < j + + res = interpret(dummy,[0]) + assert res is True + + res = interpret(dummy, [-1]) + assert res is False # -1 ==> 0xffffffff + Modified: pypy/branch/pycompiler/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rlist.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rlist.py Fri Jul 1 18:30:34 2005 @@ -4,6 +4,8 @@ from pypy.rpython.rlist import * from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr +from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import find_exception def sample_list(): @@ -94,7 +96,7 @@ def test_simple(): def dummyfn(): - l = [10,20,30] + l = [10, 20, 30] return l[2] rtype(dummyfn) @@ -108,14 +110,14 @@ def test_len(): def dummyfn(): - l = [5,10] + l = [5, 10] return len(l) rtype(dummyfn) def test_iterate(): def dummyfn(): total = 0 - for x in [1,3,5,7,9]: + for x in [1, 3, 5, 7, 9]: total += x return total rtype(dummyfn) @@ -151,3 +153,165 @@ del l[-1] del l[:] rtype(dummyfn) + +def test_insert_pop(): + def dummyfn(): + l = [6, 7, 8] + l.insert(0, 5) + l.insert(1, 42) + l.pop(2) + l.pop(0) + l.pop(-1) + l.pop() + return l[-1] + res = interpret(dummyfn, ())#, view=True) + assert res == 42 + +def test_reverse(): + def dummyfn(): + l = [5, 3, 2] + l.reverse() + return l[0]*100 + l[1]*10 + l[2] + res = interpret(dummyfn, ()) + assert res == 235 + +def test_prebuilt_list(): + klist = ['a', 'd', 'z', 'k'] + def dummyfn(n): + return klist[n] + res = interpret(dummyfn, [0]) + assert res == 'a' + res = interpret(dummyfn, [3]) + assert res == 'k' + res = interpret(dummyfn, [-2]) + assert res == 'z' + +def test_bound_list_method(): + klist = [1, 2, 3] + # for testing constant methods without actually mutating the constant + def dummyfn(n): + klist.extend([]) + interpret(dummyfn, [7]) + +def test_list_is(): + def dummyfn(): + l1 = [] + return l1 is l1 + res = interpret(dummyfn, []) + assert res is True + def dummyfn(): + l2 = [1, 2] + return l2 is l2 + res = interpret(dummyfn, []) + assert res is True + def dummyfn(): + l1 = [2] + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False + def dummyfn(): + l1 = [1, 2] + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False + + def dummyfn(): + l1 = None + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False + +def test_list_compare(): + def fn(i, j, neg=False): + s1 = [[1, 2, 3], [4, 5, 1]] + s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], [7, 1, 1, 8, 9, 10]] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + for i in range(2): + for j in range(6): + for case in False, True: + res = interpret(fn, [i,j,case]) + assert res is fn(i, j, case) + +def test_list_comparestr(): + def fn(i, j, neg=False): + s1 = [["hell"], ["hello", "world"]] + s1[0][0] += "o" # ensure no interning + s2 = [["hello"], ["world"]] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + for i in range(2): + for j in range(2): + for case in False, True: + res = interpret(fn, [i,j,case]) + assert res is fn(i, j, case) + +class Foo: pass + +class Bar(Foo): pass + +def test_list_compareinst(): + def fn(i, j, neg=False): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + s1 = [[foo1], [foo2], [bar1]] + s2 = s1[:] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + for i in range(3): + for j in range(3): + for case in False, True: + res = interpret(fn, [i, j, case]) + assert res is fn(i, j, case) + +def test_list_contains(): + def fn(i, neg=False): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + bar2 = Bar() + lis = [foo1, foo2, bar1] + args = lis + [bar2] + if neg : return args[i] not in lis + return args[i] in lis + for i in range(4): + for case in False, True: + res = interpret(fn, [i, case]) + assert res is fn(i, case) + +def test_list_index(): + def fn(i): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + bar2 = Bar() + lis = [foo1, foo2, bar1] + args = lis + [bar2] + return lis.index(args[i]) + for i in range(4): + try: + res = interpret(fn, [i]) + except Exception, e: + res = find_exception(e) + try: + res2 = fn(i) + except Exception, e: + res2 = e.__class__ + assert res == res2 + +def test_list_str(): + def fn(): + return str([1,2,3]) + + res = interpret(fn, []) + assert ''.join(res.chars) == fn() + + def fn(): + return str([[1,2,3]]) + + res = interpret(fn, []) + assert ''.join(res.chars) == fn() Modified: pypy/branch/pycompiler/rpython/test/test_rpbc.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rpbc.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rpbc.py Fri Jul 1 18:30:34 2005 @@ -1,15 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper - - -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - t.checkgraphs() - return t +from pypy.rpython.test.test_llinterp import interpret def test_easy_call(): @@ -17,7 +9,8 @@ return x+1 def g(y): return f(y+2) - rtype(g, [int]) + res = interpret(g, [5]) + assert res == 8 def test_multiple_call(): def f1(x): @@ -30,7 +23,10 @@ else: f = f2 return f(y+3) - rtype(g, [int]) + res = interpret(g, [-1]) + assert res == 3 + res = interpret(g, [1]) + assert res == 6 class MyBase: @@ -46,7 +42,8 @@ obj = MyBase() obj.z = a return obj.m(b) - rtype(f, [int, int]) + res = interpret(f, [4, 5]) + assert res == 9 def test_virtual_method_call(): def f(a, b): @@ -56,4 +53,203 @@ obj = MySubclass() obj.z = a return obj.m(b) - rtype(f, [int, int]) + res = interpret(f, [1, 2.3]) + assert res == 3.3 + res = interpret(f, [-1, 2.3]) + assert res == -3.3 + + +class MyBaseWithInit: + def __init__(self, a): + self.a1 = a + +def test_class_init(): + def f(a): + instance = MyBaseWithInit(a) + return instance.a1 + assert interpret(f, [5]) == 5 + + +class Freezing: + def _freeze_(self): + return True + def mymethod(self, y): + return self.x + y + +def test_freezing(): + fr1 = Freezing() + fr2 = Freezing() + fr1.x = 5 + fr2.x = 6 + def g(fr): + return fr.x + def f(n): + if n > 0: + fr = fr1 + elif n < 0: + fr = fr2 + else: + fr = None + return g(fr) + res = interpret(f, [1]) + assert res == 5 + res = interpret(f, [-1]) + assert res == 6 + +def test_call_frozen_pbc_simple(): + fr1 = Freezing() + fr1.x = 5 + def f(n): + return fr1.mymethod(n) + res = interpret(f, [6]) + assert res == 11 + +def test_call_frozen_pbc_multiple(): + fr1 = Freezing() + fr2 = Freezing() + fr1.x = 5 + fr2.x = 6 + def f(n): + if n > 0: + fr = fr1 + else: + fr = fr2 + return fr.mymethod(n) + res = interpret(f, [1]) + assert res == 6 + res = interpret(f, [-1]) + assert res == 5 + +def test_unbound_method(): + def f(): + inst = MySubclass() + inst.z = 40 + return MyBase.m(inst, 2) + res = interpret(f, []) + assert res == 42 + +def test_call_defaults(): + def g(a, b=2, c=3): + return a+b+c + def f1(): + return g(1) + def f2(): + return g(1, 10) + def f3(): + return g(1, 10, 100) + res = interpret(f1, []) + assert res == 1+2+3 + res = interpret(f2, []) + assert res == 1+10+3 + res = interpret(f3, []) + assert res == 1+10+100 + +def test_call_memoized_function(): + fr1 = Freezing() + fr2 = Freezing() + def getorbuild(key): + a = 1 + if key is fr1: + result = eval("a+2") + else: + result = eval("a+6") + return result + getorbuild._annspecialcase_ = "specialize:memo" + + def f1(i): + if i > 0: + fr = fr1 + else: + fr = fr2 + return getorbuild(fr) + + res = interpret(f1, [0]) + assert res == 7 + res = interpret(f1, [1]) + assert res == 3 + +def test_call_memoized_cache(): + + # this test checks that we add a separate field + # per specialization and also it uses a subclass of + # the standard pypy.tool.cache.Cache + + from pypy.tool.cache import Cache + fr1 = Freezing() + fr2 = Freezing() + + class Cache1(Cache): + def _build(self, key): + "NOT_RPYTHON" + if key is fr1: + return fr2 + else: + return fr1 + + class Cache2(Cache): + def _build(self, key): + "NOT_RPYTHON" + a = 1 + if key is fr1: + result = eval("a+2") + else: + result = eval("a+6") + return result + + cache1 = Cache1() + cache2 = Cache2() + + def f1(i): + if i > 0: + fr = fr1 + else: + fr = fr2 + newfr = cache1.getorbuild(fr) + return cache2.getorbuild(newfr) + + res = interpret(f1, [0], view=0, viewbefore=0) + assert res == 3 + res = interpret(f1, [1]) + assert res == 7 + +def test_rpbc_bound_method_static_call(): + class R: + def meth(self): + return 0 + r = R() + m = r.meth + def fn(): + return m() + res = interpret(fn, []) + assert res == 0 + +def test_constant_return_disagreement(): + class R: + def meth(self): + return 0 + r = R() + def fn(): + return r.meth() + res = interpret(fn, []) + assert res == 0 + +def test_None_is_false(): + def fn(i): + return bool([None, fn][i]) + res = interpret(fn, [1]) + assert res is True + res = interpret(fn, [0]) + assert res is False + +def INPROGRESS_test_classpbc_getattr(): + class A: + myvalue = 123 + class B(A): + myvalue = 456 + def f(i): + B() # force B and A to have a ClassDef + return [A,B][i].myvalue + res = interpret(f, [0], view=True) + assert res == 123 + res = interpret(f, [1]) + assert res == 456 Modified: pypy/branch/pycompiler/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rptr.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rptr.py Fri Jul 1 18:30:34 2005 @@ -31,3 +31,15 @@ return cast_pointer(PS2, p) s, t = ll_rtype(llup, [annmodel.SomePtr(PS)]) assert s.ll_ptrtype == PS2 + +def test_runtime_type_info(): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def ll_example(p): + return (runtime_type_info(p), + runtime_type_info(p) == getRuntimeTypeInfo(S)) + + assert ll_example(malloc(S)) == (getRuntimeTypeInfo(S), True) + s, t = ll_rtype(ll_example, [annmodel.SomePtr(Ptr(S))]) + assert s == annmodel.SomeTuple([annmodel.SomePtr(Ptr(RuntimeTypeInfo)), + annmodel.SomeBool()]) Modified: pypy/branch/pycompiler/rpython/test/test_rrange.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rrange.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rrange.py Fri Jul 1 18:30:34 2005 @@ -1,6 +1,6 @@ from pypy.translator.translator import Translator -from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rrange import * +from pypy.rpython.test.test_llinterp import interpret def test_rlist_range(): def test1(start, stop, step): @@ -22,20 +22,40 @@ # ____________________________________________________________ -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - return t +def test_range(): + def dummyfn(N): + total = 0 + for i in range(N): + total += i + return total + res = interpret(dummyfn, [10]) + assert res == 45 +def test_range_is_lazy(): + def dummyfn(N, M): + total = 0 + for i in range(M): + if i == N: + break + total += i + return total + res = interpret(dummyfn, [10, 2147418112]) + assert res == 45 + +def test_range_item(): + def dummyfn(start, stop, i): + r = range(start, stop) + return r[i] + res = interpret(dummyfn, [10, 17, 4]) + assert res == 14 + res = interpret(dummyfn, [10, 17, -2]) + assert res == 15 def test_range(): def dummyfn(N): total = 0 - for i in range(N): + for i in xrange(N): total += i return total - rtype(dummyfn, [int]) + res = interpret(dummyfn, [10]) + assert res == 45 Modified: pypy/branch/pycompiler/rpython/test/test_rstr.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rstr.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rstr.py Fri Jul 1 18:30:34 2005 @@ -1,55 +1,332 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * -from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rstr import parse_fmt_string +from pypy.rpython.rtyper import RPythonTyper, TyperError +from pypy.rpython.test.test_llinterp import interpret def test_simple(): - def dummyfn(i): + def fn(i): s = 'hello' return s[i] - - t = Translator(dummyfn) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + for i in range(5): + res = interpret(fn, [i]) + assert res == 'hello'[i] def test_nonzero(): - def dummyfn(i, s): + def fn(i, j): + s = ['', 'xx'][j] if i < 0: s = None if i > -2: return bool(s) else: return False - - t = Translator(dummyfn) - t.annotate([int, str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + 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 dummyfn(s): + def fn(i): + if i == 0: + s = '' + else: + s = "xxx" return hash(s) - - t = Translator(dummyfn) - t.annotate([str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + res = interpret(fn, [0]) + assert res == -1 + res = interpret(fn, [1]) + assert typeOf(res) == Signed def test_concat(): - def dummyfn(s1, s2): - return s1 + s2 + 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_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_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_isspace(): + def fn(s): + return s.isspace() + res = interpret(fn, ['x']) + assert res == False + res = interpret(fn, [' ']) + assert res == True + +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_mul(): + def fn(c, mul): + s = c * mul + res = 0 + for i in range(len(s)): + res = res*10 + ord(s[i]) - ord('0') + c2 = c + c2 *= mul + res = 10 * res + (c2 == s) + return res + res = interpret(fn, ['3', 5]) + assert res == 333331 + res = interpret(fn, ['5', 3]) + assert res == 5551 + +def test_str_compare(): + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] == s2[j] + for i in range(2): + for j in range(6): + res = interpret(fn, [i,j]) + assert res is fn(i, j) + + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] != s2[j] + for i in range(2): + for j in range(6): + res = interpret(fn, [i, j]) + assert res is fn(i, j) + + 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_join(): + res = interpret(lambda: ''.join([]), []) + assert ''.join(res.chars) == "" + + def fn(i, j): + s1 = [ '', ',', ' and '] + s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] + return s1[i].join(s2[j]) + for i in range(3): + for j in range(3): + res = interpret(fn, [i,j]) + assert ''.join(res.chars) == fn(i, j) + +def test_parse_fmt(): + assert parse_fmt_string('a') == ['a'] + assert parse_fmt_string('%s') == [('s',)] + assert parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"] + +def test_strformat(): + def percentS(s): + return "before %s after" % (s,) + + res = interpret(percentS, ['1']) + assert ''.join(res.chars) == 'before 1 after' + + def percentD(i): + return "bing %d bang" % (i,) + + res = interpret(percentD, [23]) + assert ''.join(res.chars) == 'bing 23 bang' + + def percentX(i): + return "bing %x bang" % (i,) + + res = interpret(percentX, [23]) + assert ''.join(res.chars) == 'bing 17 bang' + + res = interpret(percentX, [-123]) + assert ''.join(res.chars) == 'bing -7b bang' + + def moreThanOne(s, d, x): + return "string: %s decimal: %d hex: %x" % (s, d, x) + + args = 'a', 2, 3 + 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_str_slice(): + def fn(): + s = 'hello' + s1 = s[:3] + s2 = s[3:] + return s1+s2 == s and s2+s1 == 'lohel' + res = interpret(fn, ()) + assert res + +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 = interpret(dummy, [0]) + assert ''.join(res.chars) == '' + +def test_percentformat_instance(): + class C: + pass + class D(C): + pass + + def dummy(i): + if i: + x = C() + y = D() + else: + x = D() + y = C() + return "what a nice %s, much nicer than %r"%(x, y) + + res = interpret(dummy, [1]) + assert ''.join(res.chars) == 'what a nice , much nicer than ' + + res = interpret(dummy, [0]) + assert ''.join(res.chars) == 'what a nice , much nicer than ' + +def test_split(): + def fn(i): + s = ['', '0.1.2.4.8', '.1.2', '1.2.', '.1.2.4.'][i] + l = s.split('.') + sum = 0 + for num in l: + if len(num): + sum += ord(num) - ord('0') + return sum + len(l) * 100 + for i in range(5): + res = interpret(fn, [i]) + assert res == fn(i) + +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) - t = Translator(dummyfn) - t.annotate([str, str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() +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, ()) Modified: pypy/branch/pycompiler/rpython/test/test_rtuple.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rtuple.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rtuple.py Fri Jul 1 18:30:34 2005 @@ -4,7 +4,8 @@ from pypy.rpython.rtuple import * from pypy.rpython.rint import signed_repr from pypy.rpython.rbool import bool_repr - +from pypy.rpython.test.test_llinterp import interpret +import py def test_rtuple(): rtuple = TupleRepr([signed_repr, bool_repr]) @@ -44,3 +45,35 @@ ## total += x ## return total ## rtype(dummyfn) + +def test_return_tuple(): + def dummyfn(x, y): + return (xy) + rtype(dummyfn, [int, int]) + +def test_tuple_concatenation(): + def f(): + tup = (1,2) + tup1 = (3,) + res = tup + tup1 + () + return res[0]*100 + res[1]*10 + res[2] + res = interpret(f, []) + assert res == 123 + +def test_tuple_concatenation_mix(): + def f(): + tup = (1,2) + tup1 = ('3',) + res = tup + tup1 + return res[0]*100 + res[1]*10 + ord(res[2]) - ord('0') + res = interpret(f, []) + assert res == 123 + +def test_constant_tuple_contains(): + def f(i): + t1 = (1, 2, 3, 4) + return i in t1 + res = interpret(f, [3], view=False, viewbefore=False) + assert res is True + res = interpret(f, [0]) + assert res is False Modified: pypy/branch/pycompiler/rpython/test/test_rtyper.py ============================================================================== --- pypy/branch/pycompiler/rpython/test/test_rtyper.py (original) +++ pypy/branch/pycompiler/rpython/test/test_rtyper.py Fri Jul 1 18:30:34 2005 @@ -1,20 +1,24 @@ from pypy.annotation import model as annmodel from pypy.translator.translator import Translator from pypy.rpython.lltype import * +from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rtyper import RPythonTyper +import py +def setup_module(mod): + mod.logstate = py.log._getstate() + py.log.setconsumer("rtyper", py.log.STDOUT) + py.log.setconsumer("annrpython", None) + +def teardown_module(mod): + py.log._setstate(mod.logstate) def test_simple(): def dummyfn(x): return x+1 - t = Translator(dummyfn) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - + res = interpret(dummyfn, [7]) + assert res == 8 def test_function_call(): def g(x, y): @@ -22,13 +26,8 @@ def f(x): return g(1, x) - t = Translator(f) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - + res = interpret(f, [4]) + assert res == -3 def test_retval(): def f(x): Modified: pypy/branch/pycompiler/tool/_enum_exceptions.py ============================================================================== --- pypy/branch/pycompiler/tool/_enum_exceptions.py (original) +++ pypy/branch/pycompiler/tool/_enum_exceptions.py Fri Jul 1 18:30:34 2005 @@ -177,7 +177,7 @@ return tuple(res) def findAllArgs(exc, maxprobe): - minargs, maxargs = probeArgCount(exc, maxprobe=20) + minargs, maxargs = probeArgCount(exc, maxprobe) res = [] # for minargs args, we need to try combinations arglist = tuple([genArgsToTry(i) for i in range(minargs)]) @@ -231,11 +231,11 @@ txt = br[0] + ", ".join(stuff) + br[-1] names[obj] = txt else: - names[obj] = "%r # default, hopefully" % obj + names[obj] = "%r" % obj return names[obj] res = [] for i,(name, obj) in enumerate(assigned): - if isinstance(obj,ProbeObject) or name == 'args': + if isinstance(obj,ProbeObject) or name == 'args' or obj==None: res.append("self.%s = %s" % (name, nameof(obj))) else: res.append("if type(%s) == %s:"%(nameof(obj),repr(type(obj))[7:-2])) @@ -284,8 +284,10 @@ dense = tuple(range(argcounts[0], argcounts[-1]+1)) == argcounts if len(argcounts) == 1: yield " if argc == %d:" % argcounts - trailer = [" else:"] - trailer += [" raise TypeError('function takes exactly 5 arguments (%d given)'%argc)"] + if maxargs == minargs: + trailer = [" else:"] + err_msg = "" + trailer += [" raise TypeError('function takes exactly "+str(argcounts[0])+" arguments (%d given)'%argc)"] elif dense and argcounts[0] == 0: yield " if argc <= %d:" % argcounts[-1] elif dense and argcounts[-1] == maxprobe-1: @@ -294,8 +296,11 @@ yield " if %d <= argc <= %d:" % (argcounts[0], argcounts[-1]) else: yield " if argc in %r:" % (argcounts, ) - for order, line in ordered_statements: - yield indent * " " + line + if len(ordered_statements)>0: + for order, line in ordered_statements: + yield indent * " " + line + else: + yield indent * " " + "pass" if trailer: for line in trailer : yield line Modified: pypy/branch/pycompiler/tool/ansi_print.py ============================================================================== --- pypy/branch/pycompiler/tool/ansi_print.py (original) +++ pypy/branch/pycompiler/tool/ansi_print.py Fri Jul 1 18:30:34 2005 @@ -7,8 +7,21 @@ def ansi_print(text, esc, file=None): if file is None: file = sys.stderr text = text.rstrip() - if sys.platform != "win32" and file.isatty(): + if esc and sys.platform != "win32" and file.isatty(): text = ('\x1b[%sm' % esc + text + '\x1b[0m') # ANSI color code "reset" file.write(text + '\n') + +def ansi_log(msg): + keywords = list(msg.keywords) + if 'bold' in keywords: + keywords.remove('bold') + esc = "1" + elif 'red' in keywords: + keywords.remove('red') + esc = "31" + else: + esc = None + ansi_print("[%s] %s" %(":".join(keywords), msg.content()), esc) + Modified: pypy/branch/pycompiler/tool/cache.py ============================================================================== --- pypy/branch/pycompiler/tool/cache.py (original) +++ pypy/branch/pycompiler/tool/cache.py Fri Jul 1 18:30:34 2005 @@ -13,7 +13,7 @@ # Cache class: # a cache meant to map a finite number of keys to values. # It is normally extended lazily, until it contains all possible -# keys. The _specialize_ attribute of the getorbuild() method +# keys. The _annspecialcase_ attribute of the getorbuild() method # forces the annotator to decode the argument's annotations, # which must be constants or SomePBCs, actually call the # method with all possible combinations, and gather the results. Modified: pypy/branch/pycompiler/tool/unionfind.py ============================================================================== --- pypy/branch/pycompiler/tool/unionfind.py (original) +++ pypy/branch/pycompiler/tool/unionfind.py Fri Jul 1 18:30:34 2005 @@ -4,7 +4,7 @@ class UnionFind(object): - def __init__(self, info_factory): + def __init__(self, info_factory=None): self.link_to_parent = {} self.weight = {} self.info_factory = info_factory @@ -15,9 +15,9 @@ if obj not in self.link_to_parent: raise KeyError, obj - ignore, rep, access = self.find(obj) + ignore, rep, info = self.find(obj) - return access + return info def __contains__(self, obj): return obj in self.link_to_parent @@ -31,9 +31,17 @@ def infos(self): return self.root_info.values() + def find_rep(self, obj): + ignore, rep, info = self.find(obj) + return rep + def find(self, obj): # -> new_root, obj, info if obj not in self.link_to_parent: - info = self.root_info[obj] = self.info_factory(obj) + if self.info_factory: + info = self.info_factory(obj) + else: + info = None + self.root_info[obj] = info self.weight[obj] = 1 self.link_to_parent[obj] = obj return True, obj, info @@ -66,7 +74,8 @@ if w1 < w2: rep1, rep2, info1, info2, = rep2, rep1, info2, info1 - info1.update(info2) + if info1 is not None: + info1.update(info2) self.link_to_parent[rep2] = rep1 From cfbolz at codespeak.net Fri Jul 1 18:32:01 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Jul 2005 18:32:01 +0200 (CEST) Subject: [pypy-svn] r14043 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050701163201.2305727B51@code1.codespeak.net> Author: cfbolz Date: Fri Jul 1 18:32:00 2005 New Revision: 14043 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/genllvm.py Log: added comment and setup_all Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 1 18:32:00 2005 @@ -24,6 +24,9 @@ self._pendingsetup.append(node) def prepare_repr_arg(self, const_or_var): + """if const_or_var is not already in a dictionary self.obj2node, + the appropriate node gets constructed and gets added to + self._pendingsetup and to self.obj2node""" if const_or_var in self.obj2node: return if isinstance(const_or_var, Constant): @@ -51,11 +54,10 @@ log.prepare(const_or_var) self.prepare_repr_arg(const_or_var) self.prepare_repr_arg_type(const_or_var.concretetype) - - def process(self): - if self._pendingsetup: + + def setup_all(self): + while self._pendingsetup: self._pendingsetup.pop().setup() - return bool(self._pendingsetup) def getobjects(self): return self.obj2node.values() @@ -92,4 +94,4 @@ self._tmpcount += 1 return "%tmp." + str(count) - \ No newline at end of file + Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 1 18:32:00 2005 @@ -17,8 +17,7 @@ c = inputconst(lltype.typeOf(ptr), ptr) db.prepare_repr_arg(c) assert c in db.obj2node - while db.process(): - pass + db.setup_all() entrynode = db.obj2node[c] codewriter = CodeWriter() dbobjects = db.getobjects() From cfbolz at codespeak.net Fri Jul 1 18:53:05 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Jul 2005 18:53:05 +0200 (CEST) Subject: [pypy-svn] r14046 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050701165305.8E9C327B55@code1.codespeak.net> Author: cfbolz Date: Fri Jul 1 18:53:05 2005 New Revision: 14046 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: simple string test Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 18:53:05 2005 @@ -86,9 +86,16 @@ f = compile_function(tuple_getitem, [int]) assert f(1) == 2 -def test_nested_tuple(): +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_string_getitem(): + def string_test(i): + l = "Hello, World" + return l[i] + f = compile_function(string_test, [int]) + assert f(0) == ord("H") From tismer at codespeak.net Fri Jul 1 19:09:10 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 1 Jul 2005 19:09:10 +0200 (CEST) Subject: [pypy-svn] r14047 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050701170910.AB2D327B51@code1.codespeak.net> Author: tismer Date: Fri Jul 1 19:09:09 2005 New Revision: 14047 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: (Jacob, chris) long division half-way done; tests on helpers are working Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Fri Jul 1 19:09:09 2005 @@ -648,9 +648,32 @@ z._normalize() return z + def _inplace_divrem1(pout, pin, n): - rem = r_uint(0, space) + """ + Divide long pin by non-zero digit n, storing quotient + in pout, and returning the remainder. It's OK for pin == pout on entry. + """ + rem = r_uint(0) assert n > 0 and n <= SHORT_MASK size = len(pin.digits) * 2 - 1 while size >= 0: rem = (rem << SHORT_BIT) + pin._getshort(size) + hi = rem // n + pout._setshort(size, hi) + rem -= hi * n + size -= 1 + return rem + +def _divrem1(space, a, n): + """ + Divide a long integer by a digit, returning both the quotient + and the remainder as a tuple. + The sign of a is ignored; n should not be zero. + """ + assert n > 0 and n <= SHORT_MASK + size = len(a.digits) + z = W_LongObject(space, [r_uint(0)] * size, 1) + rem = _inplace_divrem1(z, a, n) + z._normalize() + return z, rem 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 Fri Jul 1 19:09:09 2005 @@ -50,6 +50,24 @@ result = lobj.mul__Long_Long(self.space, f1, f2) assert result.longval() == x * y + def test__inplace_divrem1(self): + # signs are not handled in the helpers! + x = 1238585838347L + y = 3 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + remainder = lobj._inplace_divrem1(f1, f1, f2) + assert (f1.longval(), remainder) == divmod(x, y) + + def test__divrem1(self): + # signs are not handled in the helpers! + x = 1238585838347L + y = 3 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + div, rem = lobj._divrem1(self.space, f1, f2) + assert (div.longval(), rem) == divmod(x, y) + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L From cfbolz at codespeak.net Fri Jul 1 19:35:37 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Jul 2005 19:35:37 +0200 (CEST) Subject: [pypy-svn] r14048 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050701173537.D6E9B27B59@code1.codespeak.net> Author: cfbolz Date: Fri Jul 1 19:35:37 2005 New Revision: 14048 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, ludal) implementation of unsigned ints. refactoring of OpWriter. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 1 19:35:37 2005 @@ -7,6 +7,7 @@ log = log.database PRIMITIVES_TO_LLVM = {lltype.Signed: "int", + lltype.Unsigned: "uint", lltype.Bool: "bool"} class Database(object): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 1 19:35:37 2005 @@ -100,10 +100,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: - meth = getattr(opwriter, op.opname, None) - assert meth is not None, "operation %r not found" %(op.opname,) - meth(op) - + opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) @@ -117,51 +114,52 @@ codewriter.ret(inputargtype, inputarg) class OpWriter(object): + binary_operations = {'int_mul': 'mul', + 'int_add': 'add', + 'int_sub': 'sub', + 'int_floordiv': 'div', + 'int_mod': 'rem', + 'int_lt': 'setlt', + 'int_le': 'setle', + 'int_eq': 'seteq', + 'int_ne': 'setne', + 'int_ge': 'setge', + 'int_gt': 'setgt', + + 'uint_mul': 'mul', + 'uint_add': 'add', + 'uint_sub': 'sub', + 'uint_floordiv': 'div', + 'uint_mod': 'rem', + 'uint_lt': 'setlt', + 'uint_le': 'setle', + 'uint_eq': 'seteq', + 'uint_ne': 'setne', + 'uint_ge': 'setge', + 'uint_gt': 'setgt'} + def __init__(self, db, codewriter): self.db = db self.codewriter = codewriter - def binaryop(self, name, op): + def write_operation(self, op): + if op.opname in self.binary_operations: + self.binaryop(op) + else: + meth = getattr(self, op.opname, None) + assert meth is not None, "operation %r not found" %(op.opname,) + meth(op) + + def binaryop(self, op): + name = self.binary_operations[op.opname] assert len(op.args) == 2 self.codewriter.binaryop(name, self.db.repr_arg(op.result), self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), self.db.repr_arg(op.args[1])) - def int_mul(self, op): - self.binaryop('mul', op) - - def int_floordiv(self, op): - self.binaryop('div', op) - - def int_add(self, op): - self.binaryop('add', op) - - def int_sub(self, op): - self.binaryop('sub', op) - - def int_mod(self, op): - self.binaryop('rem', op) - - def int_eq(self, op): - self.binaryop('seteq', op) - - def int_ne(self, op): - self.binaryop('setne', op) - - def int_lt(self, op): - self.binaryop('setlt', op) - - def int_le(self, op): - self.binaryop('setle', op) - - def int_gt(self, op): - self.binaryop('setgt', op) - - def int_ge(self, op): - self.binaryop('setge', op) - def cast_bool_to_int(self, op): + def cast_primitive(self, op): #works for all primitives assert len(op.args) == 1 targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) @@ -169,7 +167,8 @@ fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) - int_is_true = cast_bool_to_int + int_is_true = cast_bool_to_int = cast_primitive + cast_bool_to_uint = uint_is_true = cast_primitive def direct_call(self, op): assert len(op.args) >= 1 Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Fri Jul 1 19:35:37 2005 @@ -3,6 +3,7 @@ log = log.pyrex PRIMITIVES_TO_C = {lltype.Signed: "int", + lltype.Unsigned: "unsigned int", lltype.Bool: "char"} def write_pyx_wrapper(funcgen, targetpath): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 19:35:37 2005 @@ -9,6 +9,7 @@ from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rarithmetic import r_uint py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) @@ -59,6 +60,24 @@ assert f(1) == 1 assert f(2) == 2 +def test_uint_ops(): + def ops(i): + x = r_uint(0) + x += i < i + x += i <= i + x += i == i + x += i != i + x += i >= i + x += i > i + x += x % i + #x += i is not None + #x += i is None + return i + 1 * i // i - 1 + f = compile_function(ops, [r_uint]) + assert f(1) == 1 + assert f(2) == 2 + + def test_function_call(): def callee(): return 1 @@ -99,3 +118,20 @@ return l[i] f = compile_function(string_test, [int]) assert f(0) == ord("H") + +class TestException(Exception): + pass + +def DONOTtest_exception(): + def raise_(i): + if i: + raise TestException() + else: + return 1 + def catch(i): + try: + return raise_(i) + except TestException: + return 0 + f = compile_function(catch, [int]) + From arigo at codespeak.net Fri Jul 1 19:44:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 19:44:40 +0200 (CEST) Subject: [pypy-svn] r14049 - pypy/branch/dist-2.4.1/lib-python Message-ID: <20050701174440.17BDA27B59@code1.codespeak.net> Author: arigo Date: Fri Jul 1 19:44:37 2005 New Revision: 14049 Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py Log: Sanity check. (Should be better handled, I suppose; for now let's try to avoid long and tedious debugging caused by this.) Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/conftest.py (original) +++ pypy/branch/dist-2.4.1/lib-python/conftest.py Fri Jul 1 19:44:37 2005 @@ -919,3 +919,14 @@ result['exit status'] = exit_status result['outcome'] = outcome return result + + +# +# Sanity check (could be done more nicely too) +# +import os +if os.path.samefile(os.getcwd(), str(regrtestdir.dirpath())): + raise NotImplementedError( + "Cannot run py.test with this current directory:\n" + "the app-level sys.path will contain %s before %s)." % ( + regrtestdir.dirpath(), modregrtestdir.dirpath())) From ac at codespeak.net Fri Jul 1 19:45:42 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 1 Jul 2005 19:45:42 +0200 (CEST) Subject: [pypy-svn] r14050 - pypy/branch/dist-2.4.1/pypy/module/__builtin__ Message-ID: <20050701174542.DB3D627B59@code1.codespeak.net> Author: ac Date: Fri Jul 1 19:45:42 2005 New Revision: 14050 Added: pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py (contents, props changed) Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py Log: A hackish way to support builtin set/frozenset. Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py Fri Jul 1 19:45:42 2005 @@ -64,6 +64,8 @@ 'file' : '(space.wrap(file))', 'open' : '(space.wrap(file))', 'unicode' : '(space.w_unicode)', + 'set' : '(settype.mk_set(space))', + 'frozenset' : '(settype.mk_frozenset(space))', # old-style classes dummy support '_classobj' : 'space.w_classobj', Added: pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py ============================================================================== --- (empty file) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py Fri Jul 1 19:45:42 2005 @@ -0,0 +1,13 @@ +from pypy.interpreter import gateway + +applevel = gateway.applevel(''' +def mk_set(): + import sets + return sets.Set + +def mk_frozenset(): + import sets + return sets.ImmutableSet +''') +mk_set = applevel.interphook('mk_set') +mk_frozenset = applevel.interphook('mk_frozenset') From arigo at codespeak.net Fri Jul 1 19:45:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Jul 2005 19:45:58 +0200 (CEST) Subject: [pypy-svn] r14051 - pypy/dist/lib-python Message-ID: <20050701174558.3A43F27B59@code1.codespeak.net> Author: arigo Date: Fri Jul 1 19:45:58 2005 New Revision: 14051 Modified: pypy/dist/lib-python/conftest.py Log: Sanity check. (Should be better handled, I suppose; for now let's try to avoid long and tedious debugging caused by this.) Modified: pypy/dist/lib-python/conftest.py ============================================================================== --- pypy/dist/lib-python/conftest.py (original) +++ pypy/dist/lib-python/conftest.py Fri Jul 1 19:45:58 2005 @@ -919,3 +919,14 @@ result['exit status'] = exit_status result['outcome'] = outcome return result + + +# +# Sanity check (could be done more nicely too) +# +import os +if os.path.samefile(os.getcwd(), str(regrtestdir.dirpath())): + raise NotImplementedError( + "Cannot run py.test with this current directory:\n" + "the app-level sys.path will contain %s before %s)." % ( + regrtestdir.dirpath(), modregrtestdir.dirpath())) From nik at codespeak.net Fri Jul 1 19:52:16 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Fri, 1 Jul 2005 19:52:16 +0200 (CEST) Subject: [pypy-svn] r14052 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1 Message-ID: <20050701175216.853F427B5B@code1.codespeak.net> Author: nik Date: Fri Jul 1 19:52:15 2005 New Revision: 14052 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/warnings.py - copied, changed from r14047, pypy/branch/dist-2.4.1/lib-python/2.4.1/warnings.py Log: Modified warnings module according to previous modifications from 2.3.4 Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/warnings.py (from r14047, pypy/branch/dist-2.4.1/lib-python/2.4.1/warnings.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/warnings.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/warnings.py Fri Jul 1 19:52:15 2005 @@ -141,7 +141,7 @@ assert action in ("error", "ignore", "always", "default", "module", "once"), "invalid action: %r" % (action,) assert isinstance(message, basestring), "message must be a string" - assert isinstance(category, types.ClassType), "category must be a class" + #assert isinstance(category, types.ClassType), "category must be a class" assert issubclass(category, Warning), "category must be a Warning subclass" assert isinstance(module, basestring), "module must be a string" assert isinstance(lineno, int) and lineno >= 0, \ @@ -243,8 +243,7 @@ cat = getattr(m, klass) except AttributeError: raise _OptionError("unknown warning category: %r" % (category,)) - if (not isinstance(cat, types.ClassType) or - not issubclass(cat, Warning)): + if not issubclass(cat, Warning): # or not isinstance(cat, types.ClassType): raise _OptionError("invalid warning category: %r" % (category,)) return cat From nik at codespeak.net Fri Jul 1 19:54:35 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Fri, 1 Jul 2005 19:54:35 +0200 (CEST) Subject: [pypy-svn] r14053 - in pypy/branch/dist-2.4.1: lib-python/modified-2.4.1/test pypy/module/__builtin__ Message-ID: <20050701175435.D325F27B5B@code1.codespeak.net> Author: nik Date: Fri Jul 1 19:54:34 2005 New Revision: 14053 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/__init__.py - copied, changed from r14039, pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/test/__init__.py Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_buffer.py Log: * Added test/__init__.py * Fixed buffer semantics to comply with CPython 2.4.1 (negative size argument) Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/__init__.py (from r14039, pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/test/__init__.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/test/__init__.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/__init__.py Fri Jul 1 19:54:34 2005 @@ -4,7 +4,7 @@ 'test' package from CPython. This assumes that sys.path is configured to contain -'lib-python/modified-2.3.4' before 'lib-python/2.3.4'. +'lib-python/modified-2.4.1' before 'lib-python/2.4.1'. """ from pkgutil import extend_path Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_buffer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_buffer.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_buffer.py Fri Jul 1 19:54:34 2005 @@ -19,8 +19,11 @@ raise TypeError, "buffer object expected" if offset < 0: raise ValueError, "offset must be zero or positive" + # XXX according to CPython 2.4.1. Broken? + if size is not None and size < -1: + raise ValueError, "size must be zero or positive" - if size is None: + if size is None or size == -1: self.buf = object[offset:] else: self.buf = object[offset:offset+size] From ludal at codespeak.net Fri Jul 1 20:07:50 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 1 Jul 2005 20:07:50 +0200 (CEST) Subject: [pypy-svn] r14054 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050701180750.B28AA27B5B@code1.codespeak.net> Author: ludal Date: Fri Jul 1 20:07:50 2005 New Revision: 14054 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, ludal): implementation of floats + test Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 1 20:07:50 2005 @@ -8,7 +8,8 @@ PRIMITIVES_TO_LLVM = {lltype.Signed: "int", lltype.Unsigned: "uint", - lltype.Bool: "bool"} + lltype.Bool: "bool", + lltype.Float: "double" } class Database(object): def __init__(self, translator): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 1 20:07:50 2005 @@ -125,7 +125,7 @@ 'int_ne': 'setne', 'int_ge': 'setge', 'int_gt': 'setgt', - + 'uint_mul': 'mul', 'uint_add': 'add', 'uint_sub': 'sub', @@ -136,7 +136,20 @@ 'uint_eq': 'seteq', 'uint_ne': 'setne', 'uint_ge': 'setge', - 'uint_gt': 'setgt'} + 'uint_gt': 'setgt', + + 'float_mul': 'mul', + 'float_add': 'add', + 'float_sub': 'sub', + 'float_truediv': 'div', + 'float_mod': 'rem', + 'float_lt': 'setlt', + 'float_le': 'setle', + 'float_eq': 'seteq', + 'float_ne': 'setne', + 'float_ge': 'setge', + 'float_gt': 'setgt', + } def __init__(self, db, codewriter): self.db = db @@ -148,7 +161,7 @@ else: meth = getattr(self, op.opname, None) assert meth is not None, "operation %r not found" %(op.opname,) - meth(op) + meth(op) def binaryop(self, op): name = self.binary_operations[op.opname] Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Fri Jul 1 20:07:50 2005 @@ -4,7 +4,9 @@ PRIMITIVES_TO_C = {lltype.Signed: "int", lltype.Unsigned: "unsigned int", - lltype.Bool: "char"} + lltype.Bool: "char", + lltype.Float: "double", + } def write_pyx_wrapper(funcgen, targetpath): def c_declaration(): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 20:07:50 2005 @@ -77,6 +77,22 @@ assert f(1) == 1 assert f(2) == 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 += flt fs not None + #x += flt is None + return flt + 1 * flt / flt - 1 + f = compile_function(ops, [float]) + assert f(1) == 1 + assert f(2) == 2 + def test_function_call(): def callee(): @@ -112,7 +128,7 @@ f = compile_function(nested_tuple, [int]) assert f(4) == 4 -def test_string_getitem(): +def DONOTtest_string_getitem(): def string_test(i): l = "Hello, World" return l[i] From gintas at codespeak.net Fri Jul 1 20:30:33 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 20:30:33 +0200 (CEST) Subject: [pypy-svn] r14055 - pypy/branch/dist-2.4.1/pypy/lib Message-ID: <20050701183033.2C80D27B59@code1.codespeak.net> Author: gintas Date: Fri Jul 1 20:30:32 2005 New Revision: 14055 Modified: pypy/branch/dist-2.4.1/pypy/lib/operator.py Log: Implementeg attrgetter and itemgetter; added type checking to delslice and getslice. Modified: pypy/branch/dist-2.4.1/pypy/lib/operator.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/operator.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/operator.py Fri Jul 1 20:30:32 2005 @@ -17,6 +17,10 @@ 'and_(a, b) -- Same as a & b.' return obj1 & obj2 __and__ = and_ +def attrgetter(attr): + def f(obj): + return getattr(obj, attr) + return f def concat(obj1, obj2): 'concat(a, b) -- Same as a + b, for a and b sequences.' return obj1 + obj2 # XXX cPython only works on types with sequence api @@ -40,6 +44,8 @@ __delitem__ = delitem def delslice(obj, start, end): 'delslice(a, b, c) -- Same as del a[b:c].' + if not isinstance(start, int) or not isinstance(end, int): + raise TypeError("an integer is expected") del obj[start:end] __delslice__ = delslice def div(a,b): @@ -64,6 +70,8 @@ __getitem__ = getitem def getslice(a, start, end): 'getslice(a, b, c) -- Same as a[b:c].' + if not isinstance(start, int) or not isinstance(end, int): + raise TypeError("an integer is expected") return a[start:end] __getslice__ = getslice def gt(a,b): @@ -107,6 +115,10 @@ def is_not(a, b): 'is_not(a, b) -- Same as a is not b.' return a is not b +def itemgetter(idx): + def f(obj): + return obj[idx] + return f def le(a, b): 'le(a, b) -- Same as a<=b.' return a <= b From cfbolz at codespeak.net Fri Jul 1 20:34:45 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Jul 2005 20:34:45 +0200 (CEST) Subject: [pypy-svn] r14056 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050701183445.B73B627B59@code1.codespeak.net> Author: cfbolz Date: Fri Jul 1 20:34:45 2005 New Revision: 14056 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (ludal, cfbolz): fixed is_true for ints, uints and floats Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 1 20:34:45 2005 @@ -180,8 +180,24 @@ fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) - int_is_true = cast_bool_to_int = cast_primitive + cast_bool_to_int = cast_primitive cast_bool_to_uint = uint_is_true = cast_primitive + + def int_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0") + + uint_is_true = int_is_true + + def float_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0.0") def direct_call(self, op): assert len(op.args) >= 1 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 20:34:45 2005 @@ -18,7 +18,7 @@ ## def setup_module(mod): ## mod.llvm_found = is_on_path("llvm-as") -def compile_function(function, annotate): +def compile_function(function, annotate, view=False): t = Translator(function) a = t.annotate(annotate) t.specialize() @@ -60,6 +60,20 @@ assert f(1) == 1 assert f(2) == 2 +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_uint_ops(): def ops(i): x = r_uint(0) From adim at codespeak.net Fri Jul 1 20:40:38 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:40:38 +0200 (CEST) Subject: [pypy-svn] r14057 - pypy/branch/pycompiler/module/recparser Message-ID: <20050701184038.5E23B27B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:40:37 2005 New Revision: 14057 Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py Log: refactored to make tuplebuilder.match and expand_nodes annotable Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/tuplebuilder.py (original) +++ pypy/branch/pycompiler/module/recparser/tuplebuilder.py Fri Jul 1 20:40:37 2005 @@ -2,54 +2,105 @@ from grammar import BaseGrammarBuilder from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET -def _expand_nodes(nodes): - expanded = [] - for n in nodes: - if n[0] == -2: - # expanded.extend(expand_nodes(n[1:])) - expanded.extend(n[1:]) +## +## def _expand_nodes(nodes): +## expanded = [] +## for n in nodes: +## if n[0] == -2: +## # expanded.extend(expand_nodes(n[1:])) +## expanded.extend(n[1:]) +## else: +## expanded.append(n) +## return tuple(expanded) +## +## def expand_nodes(nodes): +## r = _expand_nodes(nodes) +## for n in nodes: +## assert type(n[0]) == int +## return r +## + +class StackElement: + """wraps TupleBuilder's tuples""" + +class Terminal(StackElement): + def __init__(self, num, value, lineno=-1): + self.nodes = [(num, value, lineno)] + self.num = num + + def as_tuple(self, lineno=None): + if lineno is not None: + return self.nodes[0] else: - expanded.append(n) - return tuple(expanded) + return self.nodes[0][:-1] -def expand_nodes(nodes): - r = _expand_nodes(nodes) - for n in nodes: - assert type(n[0]) == int - return r +class NonTerminal(StackElement): + def __init__(self, num, nodes, rulename=None): + """rulename should always be None with regular Python grammar""" + self.nodes = nodes + self.num = num + + def as_tuple(self, lineno=None): + l = [self.num] + [node.as_tuple(lineno) for node in self.nodes] + return tuple(l) + + +def expand_nodes(stack_elements): + """generate a nested tuples from a list of stack elements""" + expanded = [] + for element in stack_elements: + if isinstance(element, NonTerminal) and element.num == -2: + expanded.extend(element.nodes) + else: + expanded.append(element) + return expanded class TupleBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" def __init__(self, rules=None, debug=0, lineno=True): - BaseGrammarBuilder.__init__(self, rules, debug ) + BaseGrammarBuilder.__init__(self, rules, debug) + # This attribute is here for convenience + self.source_encoding = None self.lineno = lineno self._unknown = -10 + def _add_rule(self, rulename): + SYMBOLS[rulename] = self._unknown + self._unknown -= 1 + def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] - node += expand_nodes( [self.stack[-1]] ) - self.stack[-1] = tuple(node) + nodes = expand_nodes( [self.stack[-1]] ) + if rule.name in SYMBOLS: + self.stack[-1] = NonTerminal(SYMBOLS[rule.name], nodes) + else: + # Using regular CPython's Grammar should not lead here + # XXX find how self._unknown is meant to be used + self.stack[-1] = NonTerminal(self._unknown, nodes, rule.name) + self._add_rule(rule.name) return True - + def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - if SYMBOLS.has_key(rule.name): - node = [SYMBOLS[rule.name]] + if rule.name in SYMBOLS: + num = SYMBOLS[rule.name] + node = [num] else: - node = [self._unknown] - SYMBOLS[rule.name] = self._unknown - self._unknown -= 1 + num = self._unknown + node = [num] + self._add_rule(rule.name) else: - node = [-2] + num = -2 + node = [num] if elts_number > 0: - node += expand_nodes( self.stack[-elts_number:] ) - self.stack[-elts_number:] = [tuple(node)] + sequence_elements = self.stack[-elts_number:] + nodes = expand_nodes( sequence_elements ) + self.stack[-elts_number:] = [NonTerminal(num, nodes)] else: - self.stack.append( tuple(node) ) + self.stack.append( NonTerminal(num, []) ) return True def token(self, name, value, source): @@ -61,7 +112,7 @@ else: value = '' if self.lineno: - self.stack.append( (num, value, lineno) ) + self.stack.append( Terminal(num, value, lineno) ) else: - self.stack.append( (num, value) ) + self.stack.append( Terminal(num, value, -1) ) return True From adim at codespeak.net Fri Jul 1 20:42:52 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:42:52 +0200 (CEST) Subject: [pypy-svn] r14058 - pypy/branch/pycompiler/module/recparser Message-ID: <20050701184252.81FCC27B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:42:51 2005 New Revision: 14058 Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py pypy/branch/pycompiler/module/recparser/grammar.py Log: made return values a bit more homogeneous Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/ebnfparse.py (original) +++ pypy/branch/pycompiler/module/recparser/ebnfparse.py Fri Jul 1 20:42:51 2005 @@ -50,7 +50,7 @@ ret = builder.token( tk.name, tk.value, source ) return self.debug_return( ret, tk.name, tk.value ) source.restore( ctx ) - return None + return 0 def match_token(self, other): """convenience '==' implementation, this is *not* a *real* equality test Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Fri Jul 1 20:42:51 2005 @@ -79,6 +79,8 @@ """Base/default class for a builder""" def __init__(self, rules=None, debug=0): self.rules = rules or {} # a dictionary of grammar rules for debug/reference + # XXX This attribute is here for convenience + self.source_encoding = None self.debug = debug self.stack = [] @@ -178,7 +180,7 @@ return self.debug_return( ret, 0 ) if self._trace: self._debug_display(token, level, 'rrr') - return None + return 0 elif self._trace: self._debug_display(token, level, '>>>') @@ -208,7 +210,7 @@ """Try to match a grammar rule If next set of tokens matches this grammar element, use - to build an appropriate object, otherwise returns None. + to build an appropriate object, otherwise returns 0. /!\ If the sets of element didn't match the current grammar element, then the is restored as it was before the @@ -216,7 +218,7 @@ returns None if no match or an object build by builder """ - return None + return 0 def parse(self, source): """Returns a simplified grammar if the rule matched at the source @@ -299,7 +301,7 @@ if m: ret = builder.alternative( self, source ) return self.debug_return( ret ) - return False + return 0 def display(self, level=0): if level==0: @@ -374,7 +376,7 @@ # before the one that failed source.restore(ctx) builder.restore(bctx) - return None + return 0 ret = builder.sequence(self, source, len(self.args)) return self.debug_return( ret ) @@ -444,7 +446,7 @@ if rules1: print "tried tok:", self.display() source.restore( ctx ) - return None + return 0 def display(self, level=0): if self.value is None: From adim at codespeak.net Fri Jul 1 20:43:52 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:43:52 +0200 (CEST) Subject: [pypy-svn] r14059 - pypy/branch/pycompiler/module/recparser Message-ID: <20050701184352.082C227B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:43:51 2005 New Revision: 14059 Modified: pypy/branch/pycompiler/module/recparser/automata.py Log: use 'item in dict' instead of dict.has_key(item) Modified: pypy/branch/pycompiler/module/recparser/automata.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/automata.py (original) +++ pypy/branch/pycompiler/module/recparser/automata.py Fri Jul 1 20:43:51 2005 @@ -72,9 +72,9 @@ accept = self.accepts[crntState] if accept: return i - elif arcMap.has_key(item): + elif item in arcMap: crntState = arcMap[item] - elif arcMap.has_key(DEFAULT): + elif DEFAULT in arcMap: crntState = arcMap[DEFAULT] else: return -1 From adim at codespeak.net Fri Jul 1 20:46:15 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:46:15 +0200 (CEST) Subject: [pypy-svn] r14060 - pypy/branch/pycompiler/module/recparser Message-ID: <20050701184615.C0F6927B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:46:14 2005 New Revision: 14060 Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py pypy/branch/pycompiler/module/recparser/pythonutil.py Log: The parser is now annotable !!! (Thanks Samuele) Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Fri Jul 1 20:46:14 2005 @@ -298,7 +298,7 @@ """This source uses Jonathan's tokenizer""" def __init__(self, strings): # TokenSource.__init__(self) - tokens, encoding = generate_tokens(strings) # inpstring.splitlines(True)) + tokens, encoding = generate_tokens(strings) self.token_stack = tokens self.encoding = encoding self._current_line = '' # the current line (as a string) Modified: pypy/branch/pycompiler/module/recparser/pythonutil.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonutil.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonutil.py Fri Jul 1 20:46:14 2005 @@ -18,29 +18,37 @@ import symbol def pypy_parse(filename): - """parse using PyPy's parser module and return nested tuples + """parse using PyPy's parser module and return + a tuple of three elements : + - The encoding declaration symbol or None if there were no encoding + statement + - The TupleBuilder's stack top element (instance of + tuplebuilder.StackElement which is a wrapper of some nested tuples + like those returned by the CPython's parser) + - The encoding string or None if there were no encoding statement + nested tuples """ pyf = file(filename) text = pyf.read() pyf.close() builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder) + # make the annotator life easier + strings = [line+'\n' for line in text.split('\n')] + pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) nested_tuples = builder.stack[-1] - if hasattr(builder, '_source_encoding'): - # XXX: maybe the parser could fix that instead ? - return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) - return nested_tuples + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) -def annotateme(text): - strings = text.split('\n') +def annotateme(strings): builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - pythonparse.parse_python_source(text, PYTHON_PARSER, 'file_input', builder) -## nested_tuples = builder.stack[-1] -## if hasattr(builder, '_source_encoding'): -## # XXX: maybe the parser could fix that instead ? -## return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) -## return nested_tuples - return 0 + pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + nested_tuples = builder.stack[-1] + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) def ast_single_input( text ): builder = TupleBuilder( PYTHON_PARSER.rules ) From adim at codespeak.net Fri Jul 1 20:46:54 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:46:54 +0200 (CEST) Subject: [pypy-svn] r14061 - pypy/branch/pycompiler/module/recparser Message-ID: <20050701184654.E96A127B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:46:53 2005 New Revision: 14061 Modified: pypy/branch/pycompiler/module/recparser/pythonparse.py Log: temp fix: return None instead of raising a SyntaxError Modified: pypy/branch/pycompiler/module/recparser/pythonparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonparse.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonparse.py Fri Jul 1 20:46:53 2005 @@ -31,11 +31,11 @@ builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) result = target.match(src, builder) # XXX find a clean way to process encoding declarations - if src.encoding: - builder._source_encoding = src.encoding + builder.source_encoding = src.encoding # if not result: - raise SyntaxError("at %s" % src.debug() ) + return None + # raise SyntaxError("at %s" % src.debug() ) return builder def parse_file_input(pyf, gram, builder=None): From adim at codespeak.net Fri Jul 1 20:47:14 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:47:14 +0200 (CEST) Subject: [pypy-svn] r14062 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050701184714.1C6A127B5B@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:47:12 2005 New Revision: 14062 Modified: pypy/branch/pycompiler/module/recparser/test/test_samples.py Log: fixed tests to match the new API Modified: pypy/branch/pycompiler/module/recparser/test/test_samples.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_samples.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_samples.py Fri Jul 1 20:47:12 2005 @@ -50,13 +50,19 @@ grammar.USE_LOOKAHEAD = use_lookahead for fname in os.listdir(samples_dir): if not fname.endswith('.py'): + # if fname != 'snippet_simple_assignment.py': continue abspath = osp.join(samples_dir, fname) yield check_parse, abspath def check_parse(filepath): - print "Testing:", filepath - pypy_tuples = pypy_parse(filepath) + # pypy_tuples = pypy_parse(filepath) + encoding_decl, stack_element, encoding = pypy_parse(filepath) + nested_tuples = stack_element.as_tuple() + if encoding is None: + pypy_tuples = nested_tuples + else: + pypy_tuples = (encoding_decl, nested_tuples, encoding) python_tuples = python_parse(filepath) try: assert_tuples_equal(pypy_tuples, python_tuples) From ac at codespeak.net Fri Jul 1 20:47:56 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 1 Jul 2005 20:47:56 +0200 (CEST) Subject: [pypy-svn] r14063 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1 Message-ID: <20050701184756.43C7C27B59@code1.codespeak.net> Author: ac Date: Fri Jul 1 20:47:56 2005 New Revision: 14063 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/traceback.py - copied, changed from r14055, pypy/branch/dist-2.4.1/lib-python/2.4.1/traceback.py Log: Fix tracaback module. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/traceback.py (from r14055, pypy/branch/dist-2.4.1/lib-python/2.4.1/traceback.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/traceback.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/traceback.py Fri Jul 1 20:47:56 2005 @@ -157,7 +157,7 @@ which exception occurred is the always last string in the list. """ list = [] - if type(etype) == types.ClassType: + if isinstance(etype, (type, types.ClassType)): stype = etype.__name__ else: stype = etype From ignas at codespeak.net Fri Jul 1 20:49:02 2005 From: ignas at codespeak.net (ignas at codespeak.net) Date: Fri, 1 Jul 2005 20:49:02 +0200 (CEST) Subject: [pypy-svn] r14064 - in pypy/branch/dist-2.4.1/pypy/objspace/std: . test Message-ID: <20050701184902.D83D427B59@code1.codespeak.net> Author: ignas Date: Fri Jul 1 20:49:00 2005 New Revision: 14064 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/stringtype.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py Log: Add rsplit method to a string type as in python 2.4.1 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py Fri Jul 1 20:49:00 2005 @@ -291,6 +291,70 @@ return W_ListObject(w_self.space, res_w) +def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1): + res = [] + inword = 0 + value = w_self._value + maxsplit = space.int_w(w_maxsplit) + + for i in range(len(value)-1, -1, -1): + ch = value[i] + if _isspace(ch): + if inword: + inword = 0 + else: + if inword: + ch = ch + res[-1] + res[-1] = ch + else: + if maxsplit > -1: + if maxsplit == 0: + res.append(value[:i+1]) + break + maxsplit = maxsplit - 1 + res.append(ch) + inword = 1 + + res_w = [None] * len(res) + for i in range(len(res)): + res_w[i] = W_StringObject(space, res[i]) + res_w.reverse() + return W_ListObject(space, res_w) + +def str_rsplit__String_String_ANY(space, w_self, w_by, w_maxsplit=-1): + res_w = [] + value = w_self._value + end = len(value) + by = w_by._value + bylen = len(by) + if bylen == 0: + raise OperationError(space.w_ValueError, space.wrap("empty separator")) + maxsplit = space.int_w(w_maxsplit) + + #if maxsplit is default, then you have no limit + #of the length of the resulting array + if maxsplit == -1: + splitcount = 1 + else: + splitcount = maxsplit + + while splitcount: + next = _find(value, by, 0, end, -1) + #next = value.rfind(by, end) #of course we cannot use + #the find method, + if next < 0: + break + res_w.append(W_StringObject(space, value[next+bylen:end])) + end = next + #decrese the counter only then, when + #we don't have default maxsplit + if maxsplit > -1: + splitcount = splitcount - 1 + + res_w.append(W_StringObject(space, value[:end])) + res_w.reverse() + return W_ListObject(w_self.space, res_w) + def str_join__String_ANY(space, w_self, w_list): list = space.unpackiterable(w_list) str_w = space.str_w Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/stringtype.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/stringtype.py Fri Jul 1 20:49:00 2005 @@ -5,6 +5,7 @@ str_join = MultiMethod('join', 2) str_split = MultiMethod('split', 3, defaults=(None,-1)) +str_rsplit = MultiMethod('rsplit', 3, defaults=(None,-1)) str_isdigit = MultiMethod('isdigit', 1) str_isalpha = MultiMethod('isalpha', 1) str_isspace = MultiMethod('isspace', 1) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py Fri Jul 1 20:49:00 2005 @@ -142,6 +142,29 @@ assert 'endcase test'.split('test') == ['endcase ', ''] raises(ValueError, 'abc'.split, '') + def test_rsplit(self): + assert "".rsplit() == [] + assert " ".rsplit() == [] + assert "a".rsplit() == ['a'] + assert "a".rsplit("a", 1) == ['', ''] + assert " ".rsplit(" ", 1) == ['', ''] + assert "aa".rsplit("a", 2) == ['', '', ''] + assert " a ".rsplit() == ['a'] + assert "a b c".rsplit() == ['a','b','c'] + assert 'this is the rsplit function'.rsplit() == ['this', 'is', 'the', 'rsplit', 'function'] + assert 'a|b|c|d'.rsplit('|') == ['a', 'b', 'c', 'd'] + assert 'a|b|c|d'.rsplit('|', 2) == ['a|b', 'c', 'd'] + assert 'a b c d'.rsplit(None, 1) == ['a b c', 'd'] + assert 'a b c d'.rsplit(None, 2) == ['a b', 'c', 'd'] + assert 'a b c d'.rsplit(None, 3) == ['a', 'b', 'c', 'd'] + assert 'a b c d'.rsplit(None, 4) == ['a', 'b', 'c', 'd'] + assert 'a b c d'.rsplit(None, 0) == ['a b c d'] + assert 'a b c d'.rsplit(None, 2) == ['a b', 'c', 'd'] + assert 'a b c d '.rsplit() == ['a', 'b', 'c', 'd'] + assert 'a//b//c//d'.rsplit('//') == ['a', 'b', 'c', 'd'] + assert 'endcase test'.rsplit('test') == ['endcase ', ''] + raises(ValueError, 'abc'.rsplit, '') + def test_split_splitchar(self): assert "/a/b/c".split('/') == ['','a','b','c'] From ludal at codespeak.net Fri Jul 1 20:50:26 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 1 Jul 2005 20:50:26 +0200 (CEST) Subject: [pypy-svn] r14065 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050701185026.3AA0F27B59@code1.codespeak.net> Author: ludal Date: Fri Jul 1 20:50:26 2005 New Revision: 14065 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: added unit test for while loops Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 20:50:26 2005 @@ -60,6 +60,34 @@ assert f(1) == 1 assert f(2) == 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_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) From adim at codespeak.net Fri Jul 1 20:57:48 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 20:57:48 +0200 (CEST) Subject: [pypy-svn] r14066 - pypy/branch/pycompiler/translator/goal Message-ID: <20050701185748.A460A27B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 20:57:44 2005 New Revision: 14066 Added: pypy/branch/pycompiler/translator/goal/targetparser.py Log: added a target for the parser's main parse function Added: pypy/branch/pycompiler/translator/goal/targetparser.py ============================================================================== --- (empty file) +++ pypy/branch/pycompiler/translator/goal/targetparser.py Fri Jul 1 20:57:44 2005 @@ -0,0 +1,22 @@ +import os, sys +from pypy.annotation.model import * +from pypy.annotation.listdef import ListDef + +# 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. + +this_dir = os.path.dirname(sys.argv[0]) + +from pypy.module.recparser.pythonutil import annotateme +# __________ Entry point __________ +entry_point = annotateme + +# _____ Define and setup target ___ +def target(): + s_list_of_strings = SomeList(ListDef(None, SomeString())) + return entry_point, [s_list_of_strings] + +# _____ Run translated _____ +def run(c_entry_point): + pass From rxe at codespeak.net Fri Jul 1 20:58:56 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 1 Jul 2005 20:58:56 +0200 (CEST) Subject: [pypy-svn] r14067 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050701185856.2963B27B59@code1.codespeak.net> Author: rxe Date: Fri Jul 1 20:58:54 2005 New Revision: 14067 Added: pypy/dist/pypy/translator/llvm2/arraynode.py Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: A WIP progress of variable length sturcts. Including globals and function pointers. Sorry for big checkin. :-( Added: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Fri Jul 1 20:58:54 2005 @@ -0,0 +1,25 @@ +import py +from pypy.translator.llvm2.log import log +log = log.structnode + +class ArrayNode(object): + _issetup = False + array_counter = 0 + + def __init__(self, db, array): + self.db = db + self.array = array + self.ref = "%%array.%s.%s" % (array.OF, ArrayNode.array_counter) + ArrayNode.array_counter += 1 + + def __str__(self): + return "" % self.ref + + def setup(self): + self._issetup = True + + # ______________________________________________________________________ + # entry points from genllvm + # + def writedatatypedecl(self, codewriter): + codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Fri Jul 1 20:58:54 2005 @@ -11,6 +11,9 @@ self._lines.append(line) log(line) + def comment(self, line): + self.append(";; " + line) + def indent(self, line): self.append(" " + line) @@ -20,6 +23,9 @@ def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) + def arraydef(self, name, typerepr): + self.append("%s = type { int, [0 x %s] }" % (name, typerepr)) + def declare(self, decl): self.append("declare %s" %(decl,)) @@ -64,12 +70,17 @@ self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) - def malloc(self, targetvar, type): - self.indent("%(targetvar)s = malloc %(type)s" % locals()) - - def getelementptr(self, targetvar, type, typevar, index): - self.indent("%(targetvar)s = getelementptr " - "%(type)s %(typevar)s, int 0, uint %(index)s" % locals()) + def malloc(self, targetvar, type, sizetype=None, size=None): + if size is None: + assert sizetype is None + self.indent("%(targetvar)s = malloc %(type)s" % locals()) + else: + self.indent("%(targetvar)s = malloc %(type)s, %(sizetype)s %(size)s" % locals()) + + def getelementptr(self, targetvar, type, typevar, *indices): + res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals() + res += ", ".join(["%s %s" % (t, i) for t, i in indices]) + self.indent(res) def load(self, targetvar, targettype, ptr): self.indent("%(targetvar)s = load %(targettype)s* %(ptr)s" % locals()) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 1 20:58:54 2005 @@ -1,12 +1,15 @@ from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.funcnode import FuncNode -from pypy.translator.llvm2.structnode import StructNode +from pypy.translator.llvm2.funcnode import FuncNode, FuncSig +from pypy.translator.llvm2.structnode import StructNode, StructInstance +from pypy.translator.llvm2.arraynode import ArrayNode +ArrayNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable log = log.database PRIMITIVES_TO_LLVM = {lltype.Signed: "int", + lltype.Char: "sbyte", lltype.Unsigned: "uint", lltype.Bool: "bool", lltype.Float: "double" } @@ -17,7 +20,7 @@ self.obj2node = {} self._pendingsetup = [] self._tmpcount = 1 - + def addpending(self, key, node): assert key not in self.obj2node, ( "node with key %r already known!" %(key,)) @@ -32,11 +35,25 @@ if const_or_var in self.obj2node: return if isinstance(const_or_var, Constant): - if isinstance(const_or_var.concretetype, lltype.Primitive): - pass - #log.prepare(const_or_var, "(is primitive)") + + ct = const_or_var.concretetype + while isinstance(ct, lltype.Ptr): + ct = ct.TO + + if isinstance(ct, lltype.FuncType): + self.addpending(const_or_var, FuncNode(self, const_or_var)) else: - self.addpending(const_or_var, FuncNode(self, const_or_var)) + #value = const_or_var.value + #while hasattr(value, "_obj"): + # value = value._obj + + if isinstance(ct, lltype.Struct): + self.addpending(const_or_var, StructInstance(self, value)) + + elif isinstance(ct, lltype.Primitive): + log.prepare(const_or_var, "(is primitive)") + else: + log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var)) else: log.prepare.ignore(const_or_var) @@ -47,23 +64,80 @@ pass elif isinstance(type_, lltype.Ptr): self.prepare_repr_arg_type(type_.TO) + elif isinstance(type_, lltype.Struct): self.addpending(type_, StructNode(self, type_)) + + elif isinstance(type_, lltype.FuncType): + self.addpending(type_, FuncSig(self, type_)) + + elif isinstance(type_, lltype.Array): + self.addpending(type_, ArrayNode(self, type_)) + else: log.XXX("need to prepare typerepr", type_) def prepare_arg(self, const_or_var): log.prepare(const_or_var) - self.prepare_repr_arg(const_or_var) self.prepare_repr_arg_type(const_or_var.concretetype) - + self.prepare_repr_arg(const_or_var) + def setup_all(self): while self._pendingsetup: self._pendingsetup.pop().setup() - def getobjects(self): - return self.obj2node.values() - + def getobjects(self, subset_types=None): + res = [] + for v in self.obj2node.values(): + if subset_types is None or isinstance(v, subset_types): + res.append(v) + res.reverse() + return res + + def get_typedecls(self): + return self.getobjects((StructNode, ArrayNode)) + + def get_globaldata(self): + return self.getobjects((StructInstance)) + + def get_functions(self): + struct_nodes = [n for n in self.getobjects(StructNode) if n.inline_struct] + return struct_nodes + self.getobjects(FuncNode) + + def dump(self): + + # get and reverse the order in which seen objs + all_objs = self.obj2node.items() + all_objs.reverse() + + log.dump_db("*** type declarations ***") + for k,v in all_objs: + if isinstance(v, (StructNode, ArrayNode)): + log.dump_db("%s ---> %s" % (k, v)) + + log.dump_db("*** global data ***") + for k,v in all_objs: + if isinstance(v, (StructInstance)): + log.dump_db("%s ---> %s" % (k, v)) + + log.dump_db("*** function protos ***") + for k,v in all_objs: + if isinstance(v, (FuncNode)): + log.dump_db("%s ---> %s" % (k, v)) + + log.dump_db("*** function implementations ***") + for k,v in all_objs: + if isinstance(v, (FuncNode)): + log.dump_db("%s ---> %s" % (k, v)) + + log.dump_db("*** unknown ***") + for k,v in all_objs: + if isinstance(v, (FuncSig)): + log.dump_db("%s ---> %s" % (k, v)) + + # __________________________________________________________ + # Getters + def repr_arg(self, arg): if (isinstance(arg, Constant) and isinstance(arg.concretetype, lltype.Primitive)): @@ -95,5 +169,3 @@ count = self._tmpcount self._tmpcount += 1 return "%tmp." + str(count) - - Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 1 20:58:54 2005 @@ -6,6 +6,24 @@ from pypy.translator.llvm2.log import log log = log.funcnode +class FuncSig(object): + """ XXX Not sure about this - should be combined with FuncNode? + Abstract function signature. """ + def __init__(self, db, typ): + self.db = db + self.typ = typ + # Hack around some debug statements + self.ref = "pending setup!" + + def __str__(self): + return "" % self.ref + + def setup(self): + returntype = self.db.repr_arg_type(self.typ.RESULT) + inputargtypes = self.db.repr_arg_type_multi(self.typ.ARGS) + self.ref = "%s (%s)" % (returntype, ", ".join(inputargtypes)) + + class FuncNode(object): _issetup = False @@ -14,7 +32,6 @@ self.ref = "%" + const_ptr_func.value._obj._name self.graph = prepare_graph(const_ptr_func.value._obj.graph, db._translator) - def __str__(self): return "" %(self.ref,) @@ -30,19 +47,6 @@ self.db.prepare_arg(op.result) traverse(visit, self.graph) self._issetup = True - - def getdecl(self): - assert self._issetup - startblock = self.graph.startblock - returnblock = self.graph.returnblock - inputargs = self.db.repr_arg_multi(startblock.inputargs) - inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) - returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) - result = "%s %s" % (returntype, self.ref) - args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] - result += "(%s)" % ", ".join(args) - return result - # ______________________________________________________________________ # main entry points from genllvm def writedecl(self, codewriter): @@ -72,6 +76,18 @@ # ______________________________________________________________________ # writing helpers for entry points + def getdecl(self): + assert self._issetup + startblock = self.graph.startblock + returnblock = self.graph.returnblock + inputargs = self.db.repr_arg_multi(startblock.inputargs) + inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) + returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) + result = "%s %s" % (returntype, self.ref) + args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] + result += "(%s)" % ", ".join(args) + return result + def write_block(self, codewriter, block): self.write_block_phi_nodes(codewriter, block) self.write_block_operations(codewriter, block) @@ -101,7 +117,6 @@ opwriter = OpWriter(self.db, codewriter) for op in block.operations: opwriter.write_operation(op) - def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) self.write_block_branches(codewriter, block) @@ -218,17 +233,36 @@ type = self.db.obj2node[arg.value].ref self.codewriter.malloc(targetvar, type) + def malloc_varsize(self, op): + targetvar = self.db.repr_arg(op.result) + arg_type = op.args[0] + assert (isinstance(arg_type, Constant) and + isinstance(arg_type.value, lltype.Struct)) + struct_type = self.db.obj2node[arg_type.value].ref + struct_cons = self.db.obj2node[arg_type.value].new_var_name + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) + self.codewriter.call(targetvar, struct_type + " *", + struct_cons, argrefs, argtypes) + def getfield(self, op): tmpvar = self.db.repr_tmpvar() - type = self.db.repr_arg_type(op.args[0]) - typevar = self.db.repr_arg(op.args[0]) + typ = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, type, typevar, index) - + self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) + targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - self.codewriter.load(targetvar, targettype, tmpvar) + #XXX This doesnt work - yet + #if isinstance(op.result.concretetype, lltype.Ptr): + # self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + #else: + # Moving to correct result variable + #self.codewriter.load(targetvar, targettype, tmpvar) + self.codewriter.load(targetvar, targettype, tmpvar) + getsubstruct = getfield def setfield(self, op): tmpvar = self.db.repr_tmpvar() @@ -236,8 +270,51 @@ typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, type, typevar, index) + self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index)) + + valuevar = self.db.repr_arg(op.args[2]) + valuetype = self.db.repr_arg_type(op.args[2]) + self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarrayitem(self, op): + var = self.db.repr_arg(op.args[0]) + vartype = self.db.repr_arg_type(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, vartype, var, + ("uint", 1), (indextype, index)) + + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + + # Ditto see getfield + if not isinstance(op.result.concretetype, lltype.Ptr): + self.codewriter.load(targetvar, targettype, tmpvar) + else: + # XXX noop + self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + + def setarrayitem(self, op): + array = self.db.repr_arg(op.args[0]) + arraytype = self.db.repr_arg_type(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarraysize(self, op): + var = self.db.repr_arg(op.args[0]) + vartype = self.db.repr_arg_type(op.args[0]) + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 0)) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + self.codewriter.load(targetvar, targettype, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 1 20:58:54 2005 @@ -20,14 +20,27 @@ db.setup_all() entrynode = db.obj2node[c] codewriter = CodeWriter() - dbobjects = db.getobjects() - log.debug(dbobjects) - log.debug(db.obj2node) - for node in dbobjects: - node.writedecl(codewriter) - codewriter.startimpl() - for node in dbobjects: - node.writeimpl(codewriter) + comment = codewriter.comment + nl = lambda: codewriter.append("") + + nl(); comment("Type Declarations"); nl() + for typ_decl in db.get_typedecls(): + typ_decl.writedatatypedecl(codewriter) + + nl(); comment("Global Data") ; nl() + for typ_decl in db.get_globaldata(): + typ_decl.writedata(codewriter) + + nl(); comment("Function Prototypes") ; nl() + for typ_decl in db.get_functions(): + typ_decl.writedecl(codewriter) + + nl(); comment("Function Implementation") + codewriter.startimpl() + for typ_decl in db.get_functions(): + typ_decl.writeimpl(codewriter) + + comment("End of file") ; nl() targetdir = udir llvmsource = targetdir.join(func.func_name).new(ext='.ll') Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Fri Jul 1 20:58:54 2005 @@ -6,6 +6,7 @@ lltype.Unsigned: "unsigned int", lltype.Bool: "char", lltype.Float: "double", + lltype.Char: "char", } def write_pyx_wrapper(funcgen, targetpath): Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Fri Jul 1 20:58:54 2005 @@ -1,6 +1,7 @@ import py from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.translator.llvm2.log import log +from pypy.rpython import lltype log = log.structnode class StructNode(object): @@ -8,22 +9,39 @@ struct_counter = 0 def __init__(self, db, struct): + assert isinstance(struct, lltype.Struct) + self.db = db - self.struct = struct - self.ref = "%%st.%s.%s" % (struct._name, StructNode.struct_counter) + self.struct = struct + + self.name = "%s.%s" % (self.struct._name, StructNode.struct_counter) + self.ref = "%%st.%s" % self.name + self.inline_struct = self.struct._arrayfld + StructNode.struct_counter += 1 def __str__(self): return "" %(self.ref,) def setup(self): - log.XXX("setup", self) + # Recurse + for fieldname in self.struct._names: + field_type = getattr(self.struct, fieldname) + self.db.prepare_repr_arg_type(field_type) + + if self.inline_struct: + log.XXX("Register me", self) + self._issetup = True + def get_decl_for_varsize(self): + self.new_var_name = "%%new.st.%s" % self.name + return "%s * %s(int %%len)" % (self.ref, self.new_var_name) + # ______________________________________________________________________ - # entry points from genllvm - # - def writedecl(self, codewriter): + # main entry points from genllvm + + def writedatatypedecl(self, codewriter): assert self._issetup struct = self.struct l = [] @@ -32,5 +50,81 @@ l.append(self.db.repr_arg_type(type_)) codewriter.structdef(self.ref, l) + def writedecl(self, codewriter): + # declaration for constructor + if self.inline_struct: + # XXX Not well thought out - hack / better to modify the graph + codewriter.declare(self.get_decl_for_varsize()) + def writeimpl(self, codewriter): - assert self._issetup + + if self.inline_struct: + log.writeimpl(self.ref) + codewriter.openfunc(self.get_decl_for_varsize()) + codewriter.label("block0") + + # XXX TODO + arraytype = "sbyte" + indices_to_array = [("uint", 1)] + + # Into array and length + indices = indices_to_array + [("uint", 1), ("int", "%len")] + codewriter.getelementptr("%size", self.ref + "*", + "null", *indices) + + #XXX is this ok for 64bit? + codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") + codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") + codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") + + # remember the allocated length for later use. + indices = indices_to_array + [("uint", 0)] + codewriter.getelementptr("%size_ptr", self.ref + "*", + "%result", *indices) + + codewriter.cast("%signedsize", "uint", "%sizeu", "int") + codewriter.store("int", "%signedsize", "%size_ptr") + + codewriter.ret(self.ref + "*", "%result") + codewriter.closefunc() + + +class StructInstance(object): + _issetup = False + struct_counter = 0 + + def __init__(self, db, value): + self.db = db + self.name = "%s.%s" % (value._TYPE._name, StructInstance.struct_counter) + self.ref = "%%stinstance.%s" % self.name + self.value = value + StructInstance.struct_counter += 1 + + def __str__(self): + return "" %(self.ref,) + + def setup(self): + # Recurse fields (XXX Messy!) + for name in self.value._TYPE._names: + T = self.value._TYPE._flds[name] + self.db.prepare_repr_arg_type(T) + if not isinstance(T, lltype.Primitive): + value = getattr(self.value, name) + self.db.prepare_repr_arg(value) + + self._issetup = True + +# def struct_repr(self): +# typ = repr_arg_type(self.value) +# self.value._TYPE._names +# typevaluepairs = ["%s %s" % for t, v in +# typevaluepairsstr = ", ".join(typevaluepairs) +# return "%s { %s }" % (typ, typevaluepairsstr) + + def writedata(self, codewriter): + log.XXXXXXXXXX("ooops TODO should write - ", self.ref) + for name in self.value._TYPE._names: + log.XXXXXXXXXX("ooops ", getattr(self.value, name)) + typ = self.db.repr_arg_type(self.value._TYPE) + # XXX constant you say? + codewriter.append("%s = internal constant %s* null" % (self.ref, typ)) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 1 20:58:54 2005 @@ -168,7 +168,31 @@ l = (1,(1,2,i),i) return l[1][2] f = compile_function(nested_tuple, [int]) - assert f(4) == 4 + assert f(4) == 4 + +def test_pbc_fns(): + 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 DONOT_test_simple_chars(): + 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 DONOTtest_string_getitem(): def string_test(i): @@ -192,4 +216,3 @@ except TestException: return 0 f = compile_function(catch, [int]) - From adim at codespeak.net Fri Jul 1 21:00:19 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 1 Jul 2005 21:00:19 +0200 (CEST) Subject: [pypy-svn] r14068 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050701190019.39AC527B59@code1.codespeak.net> Author: adim Date: Fri Jul 1 21:00:18 2005 New Revision: 14068 Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Log: source now takes a list of strings instead of one big string Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Fri Jul 1 21:00:18 2005 @@ -4,7 +4,7 @@ def parse_source(source): """returns list of parsed tokens""" - lexer = Source(source) + lexer = Source(source.splitlines(True)) tokens = [] last_token = Token(None, None) while last_token.name != 'ENDMARKER': From gintas at codespeak.net Fri Jul 1 21:13:48 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 21:13:48 +0200 (CEST) Subject: [pypy-svn] r14069 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings Message-ID: <20050701191348.855E627B59@code1.codespeak.net> Author: gintas Date: Fri Jul 1 21:13:47 2005 New Revision: 14069 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ - copied from r14063, pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/ Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ascii.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/charmap.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/latin_1.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mbcs.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/raw_unicode_escape.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/string_escape.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_escape.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_internal.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_7.py Log: Added staticmethod to encode/decode method assignments in the encodings package. The tests seem to fail for other reasons, so I'm not sure if these changes are complete or even correct. Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ascii.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/ascii.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ascii.py Fri Jul 1 21:13:47 2005 @@ -14,8 +14,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.ascii_encode - decode = codecs.ascii_decode + encode = staticmethod(codecs.ascii_encode) + decode = staticmethod(codecs.ascii_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/charmap.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/charmap.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/charmap.py Fri Jul 1 21:13:47 2005 @@ -18,8 +18,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.charmap_encode - decode = codecs.charmap_decode + encode = staticmethod(codecs.charmap_encode) + decode = staticmethod(codecs.charmap_decode) class StreamWriter(Codec,codecs.StreamWriter): Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/latin_1.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/latin_1.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/latin_1.py Fri Jul 1 21:13:47 2005 @@ -14,8 +14,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.latin_1_encode - decode = codecs.latin_1_decode + encode = staticmethod(codecs.latin_1_encode) + decode = staticmethod(codecs.latin_1_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mbcs.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mbcs.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mbcs.py Fri Jul 1 21:13:47 2005 @@ -15,8 +15,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.mbcs_encode - decode = codecs.mbcs_decode + encode = staticmethod(codecs.mbcs_encode) + decode = staticmethod(codecs.mbcs_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/raw_unicode_escape.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/raw_unicode_escape.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/raw_unicode_escape.py Fri Jul 1 21:13:47 2005 @@ -14,8 +14,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.raw_unicode_escape_encode - decode = codecs.raw_unicode_escape_decode + encode = staticmethod(codecs.raw_unicode_escape_encode) + decode = staticmethod(codecs.raw_unicode_escape_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/string_escape.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/string_escape.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/string_escape.py Fri Jul 1 21:13:47 2005 @@ -9,8 +9,8 @@ class Codec(codecs.Codec): - encode = codecs.escape_encode - decode = codecs.escape_decode + encode = staticmethod(codecs.escape_encode) + decode = staticmethod(codecs.escape_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_escape.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/unicode_escape.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_escape.py Fri Jul 1 21:13:47 2005 @@ -14,8 +14,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.unicode_escape_encode - decode = codecs.unicode_escape_decode + encode = staticmethod(codecs.unicode_escape_encode) + decode = staticmethod(codecs.unicode_escape_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_internal.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/unicode_internal.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_internal.py Fri Jul 1 21:13:47 2005 @@ -14,8 +14,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.unicode_internal_encode - decode = codecs.unicode_internal_decode + encode = staticmethod(codecs.unicode_internal_encode) + decode = staticmethod(codecs.unicode_internal_decode) class StreamWriter(Codec,codecs.StreamWriter): pass Modified: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_7.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_7.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_7.py Fri Jul 1 21:13:47 2005 @@ -10,8 +10,8 @@ # Note: Binding these as C functions will result in the class not # converting them to methods. This is intended. - encode = codecs.utf_7_encode - decode = codecs.utf_7_decode + encode = staticmethod(codecs.utf_7_encode) + decode = staticmethod(codecs.utf_7_decode) class StreamWriter(Codec,codecs.StreamWriter): pass From nik at codespeak.net Fri Jul 1 21:19:47 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Fri, 1 Jul 2005 21:19:47 +0200 (CEST) Subject: [pypy-svn] r14070 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050701191947.9F43D27B59@code1.codespeak.net> Author: nik Date: Fri Jul 1 21:19:46 2005 New Revision: 14070 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_struct.py - copied, changed from r14047, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_struct.py Log: Applied modifications from 2.3.4 to 2.4.1 version of test_struct.py Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_struct.py (from r14047, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_struct.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_struct.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_struct.py Fri Jul 1 21:19:46 2005 @@ -329,16 +329,25 @@ from random import randrange # Create all interesting powers of 2. - values = [] + allvalues = [] for exp in range(self.bitsize + 3): - values.append(1L << exp) + allvalues.append(1L << exp) - # Add some random values. - for i in range(self.bitsize): - val = 0L - for j in range(self.bytesize): - val = (val << 8) | randrange(256) - values.append(val) + # reduce the number of values again + values = [] + i = 1 + while i <= len(allvalues): + values.append(allvalues[i-1]) + i *= 2 + + # + # XXX doesn't seem like good practice to run with random values + # + #for i in range(self.bitsize): + # val = 0L + # for j in range(self.bytesize): + # val = (val << 8) | randrange(256) + # values.append(val) # Try all those, and their negations, and +-1 from them. Note # that this tests all power-of-2 boundaries in range, and a few out From ericvrp at codespeak.net Fri Jul 1 21:28:32 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 1 Jul 2005 21:28:32 +0200 (CEST) Subject: [pypy-svn] r14071 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050701192832.1B23127B59@code1.codespeak.net> Author: ericvrp Date: Fri Jul 1 21:28:31 2005 New Revision: 14071 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py Log: Added linenumbers to llvm codewriter for easier debugging Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Fri Jul 1 21:28:31 2005 @@ -2,12 +2,20 @@ from pypy.translator.llvm2.log import log log = log.codewriter +show_line_numbers = True class CodeWriter(object): def __init__(self): self._lines = [] def append(self, line): + if show_line_numbers: + global line_number + try: + line_number += 1 + except: + line_number = 1 + line = "%-80s; %d" % (line, line_number) self._lines.append(line) log(line) From gintas at codespeak.net Fri Jul 1 21:40:20 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Fri, 1 Jul 2005 21:40:20 +0200 (CEST) Subject: [pypy-svn] r14072 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050701194020.14B6627B59@code1.codespeak.net> Author: gintas Date: Fri Jul 1 21:40:19 2005 New Revision: 14072 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_class.py - copied, changed from r14069, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_class.py Log: Fixed test_class. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_class.py (from r14069, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_class.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_class.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_class.py Fri Jul 1 21:40:19 2005 @@ -353,7 +353,7 @@ try: A().a # Raised AttributeError: A instance has no attribute 'a' except AttributeError, x: - if str(x) is not "booh": + if str(x) != "booh": print "attribute error for A().a got masked:", str(x) class E: From adim at codespeak.net Sat Jul 2 11:31:07 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sat, 2 Jul 2005 11:31:07 +0200 (CEST) Subject: [pypy-svn] r14073 - in pypy/dist/pypy/module/recparser: . compiler data test Message-ID: <20050702093107.0ACEE27B5D@code1.codespeak.net> Author: adim Date: Sat Jul 2 11:31:02 2005 New Revision: 14073 Added: pypy/dist/pypy/module/recparser/compiler/ - copied from r14072, pypy/branch/pycompiler/module/recparser/compiler/ Modified: pypy/dist/pypy/module/recparser/__init__.py pypy/dist/pypy/module/recparser/compat.py pypy/dist/pypy/module/recparser/data/Grammar2.4 pypy/dist/pypy/module/recparser/ebnflexer.py pypy/dist/pypy/module/recparser/ebnfparse.py pypy/dist/pypy/module/recparser/grammar.py pypy/dist/pypy/module/recparser/pyparser.py pypy/dist/pypy/module/recparser/pythonlexer.py pypy/dist/pypy/module/recparser/pythonparse.py pypy/dist/pypy/module/recparser/pythonutil.py pypy/dist/pypy/module/recparser/syntaxtree.py pypy/dist/pypy/module/recparser/test/test_pytokenizer.py pypy/dist/pypy/module/recparser/test/test_samples.py pypy/dist/pypy/module/recparser/test/unittest_samples.py pypy/dist/pypy/module/recparser/tuplebuilder.py Log: merged pycompiler branch to the trunk Modified: pypy/dist/pypy/module/recparser/__init__.py ============================================================================== --- pypy/dist/pypy/module/recparser/__init__.py (original) +++ pypy/dist/pypy/module/recparser/__init__.py Sat Jul 2 11:31:02 2005 @@ -1,44 +1,49 @@ from pypy.interpreter.error import OperationError, debug_print from pypy.interpreter import module -from pypy.interpreter.mixedmodule import MixedModule -import pythonutil -debug_print( "Loading grammar %s" % pythonutil.PYTHON_GRAMMAR ) -PYTHON_PARSER = pythonutil.python_grammar() -class Module(MixedModule): - """The builtin parser module. - """ +import pythonparse +debug_print( "Loading grammar %s" % pythonparse.PYTHON_GRAMMAR ) +from pypy.interpreter.mixedmodule import MixedModule +class Module(MixedModule): + interpleveldefs = {} + appleveldefs = {} - appleveldefs = { - # 'ParserError' : 'app_class.ParserError', - } - interpleveldefs = { - '__name__' : '(space.wrap("parser"))', - '__doc__' : '(space.wrap("parser (recparser version) module"))', - - 'suite' : 'pyparser.suite', - 'expr' : 'pyparser.expr', - 'STType' : 'pyparser.STType', - 'ast2tuple' : 'pyparser.ast2tuple', -# 'ASTType' : 'pyparser.STType', - # 'sequence2st' : 'pyparser.sequence2st', - #'eval_input' : 'pyparser.eval_input', - #'file_input' : 'pyparser.file_input', - #'compileast' : 'pyparser.compileast', - #'st2tuple' : 'pyparser.st2tuple', - #'st2list' : 'pyparser.st2list', - #'issuite' : 'pyparser.issuite', - #'ast2tuple' : 'pyparser.ast2tuple', - #'tuple2st' : 'pyparser.tuple2st', - #'isexpr' : 'pyparser.isexpr', - #'ast2list' : 'pyparser.ast2list', - #'sequence2ast' : 'pyparser.sequence2ast', - #'tuple2ast' : 'pyparser.tuple2ast', - #'_pickler' : 'pyparser._pickler', - #'compilest' : 'pyparser.compilest', - } +## from pypy.interpreter.mixedmodule import MixedModule +## class Module(MixedModule): +## """The builtin parser module. +## """ + + +## appleveldefs = { +## # 'ParserError' : 'app_class.ParserError', +## } +## interpleveldefs = { +## '__name__' : '(space.wrap("parser"))', +## '__doc__' : '(space.wrap("parser (recparser version) module"))', + +## 'suite' : 'pyparser.suite', +## 'expr' : 'pyparser.expr', +## 'STType' : 'pyparser.STType', +## 'ast2tuple' : 'pyparser.ast2tuple', +## # 'ASTType' : 'pyparser.STType', +## # 'sequence2st' : 'pyparser.sequence2st', +## #'eval_input' : 'pyparser.eval_input', +## #'file_input' : 'pyparser.file_input', +## #'compileast' : 'pyparser.compileast', +## #'st2tuple' : 'pyparser.st2tuple', +## #'st2list' : 'pyparser.st2list', +## #'issuite' : 'pyparser.issuite', +## #'ast2tuple' : 'pyparser.ast2tuple', +## #'tuple2st' : 'pyparser.tuple2st', +## #'isexpr' : 'pyparser.isexpr', +## #'ast2list' : 'pyparser.ast2list', +## #'sequence2ast' : 'pyparser.sequence2ast', +## #'tuple2ast' : 'pyparser.tuple2ast', +## #'_pickler' : 'pyparser._pickler', +## #'compilest' : 'pyparser.compilest', +## } Modified: pypy/dist/pypy/module/recparser/compat.py ============================================================================== --- pypy/dist/pypy/module/recparser/compat.py (original) +++ pypy/dist/pypy/module/recparser/compat.py Sat Jul 2 11:31:02 2005 @@ -1,7 +1,7 @@ """Compatibility layer for CPython's parser module""" from pythonparse import parse_python_source -from pypy.module.recparser import PYTHON_PARSER +from pythonutil import PYTHON_PARSER from compiler import transformer, compile as pycompile def suite( source ): Modified: pypy/dist/pypy/module/recparser/data/Grammar2.4 ============================================================================== --- pypy/dist/pypy/module/recparser/data/Grammar2.4 (original) +++ pypy/dist/pypy/module/recparser/data/Grammar2.4 Sat Jul 2 11:31:02 2005 @@ -90,7 +90,8 @@ listmaker: test ( list_for | (',' test)* [','] ) testlist_gexp: test ( gen_for | (',' test)* [','] ) lambdef: 'lambda' [varargslist] ':' test -trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | [test] ':' [test] [sliceop] | test sliceop: ':' [test] @@ -101,7 +102,8 @@ classdef: 'class' NAME ['(' testlist ')'] ':' suite -arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +arglist: (argument ',')* ( '*' test [',' '**' test] | '**' test | argument | [argument ','] ) argument: [test '='] test [gen_for] # Really [keyword '='] test list_iter: list_for | list_if Modified: pypy/dist/pypy/module/recparser/ebnflexer.py ============================================================================== --- pypy/dist/pypy/module/recparser/ebnflexer.py (original) +++ pypy/dist/pypy/module/recparser/ebnflexer.py Sat Jul 2 11:31:02 2005 @@ -4,7 +4,7 @@ """ import re -from grammar import TokenSource +from grammar import TokenSource, Token DEBUG = False @@ -21,9 +21,10 @@ TokenSource.__init__(self) self.input = inpstring self.pos = 0 + self._peeked = None def context(self): - return self.pos + return self.pos, self._peeked def offset(self, ctx=None): if ctx is None: @@ -32,10 +33,15 @@ assert type(ctx)==int return ctx - def restore(self, ctx ): - self.pos = ctx + def restore(self, ctx): + self.pos, self._peeked = ctx def next(self): + if self._peeked is not None: + peeked = self._peeked + self._peeked = None + return peeked + pos = self.pos inp = self.input m = g_skip.match(inp, pos) @@ -43,29 +49,35 @@ pos = m.end() if pos==len(inp): self.pos = pos - return None, None + return Token("EOF", None) m = g_skip.match(inp, pos) m = g_symdef.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return 'SYMDEF',tk[:-1] + return Token('SYMDEF',tk[:-1]) m = g_tok.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return tk,tk + return Token(tk,tk) m = g_string.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return 'STRING',tk[1:-1] + return Token('STRING',tk[1:-1]) m = g_symbol.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return 'SYMBOL',tk + return Token('SYMBOL',tk) raise ValueError("Unknown token at pos=%d context='%s'" % (pos,inp[pos:pos+20]) ) + def peek(self): + if self._peeked is not None: + return self._peeked + self._peeked = self.next() + return self._peeked + def debug(self): return self.input[self.pos:self.pos+20] Modified: pypy/dist/pypy/module/recparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/module/recparser/ebnfparse.py (original) +++ pypy/dist/pypy/module/recparser/ebnfparse.py Sat Jul 2 11:31:02 2005 @@ -1,6 +1,6 @@ #!/usr/bin/env python from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ - KleenStar, GrammarElement + KleenStar, GrammarElement, build_first_sets, EmptyToken from ebnflexer import GrammarSource import re @@ -32,7 +32,7 @@ Token.__init__(self, "NAME") self.keywords = keywords - def match(self, source, builder): + def match(self, source, builder, level=0): """Matches a token. the default implementation is to match any token whose type corresponds to the object's name. You can extend Token @@ -44,16 +44,38 @@ # error unknown or negative integer """ ctx = source.context() - tk_type, tk_value = source.next() - if tk_type==self.name: - if tk_value not in self.keywords: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type, tk_value ) + tk = source.next() + if tk.name==self.name: + if tk.value not in self.keywords: + ret = builder.token( tk.name, tk.value, source ) + return self.debug_return( ret, tk.name, tk.value ) source.restore( ctx ) - return None + return 0 + def match_token(self, other): + """convenience '==' implementation, this is *not* a *real* equality test + a Token instance can be compared to: + - another Token instance in which case all fields (name and value) + must be equal + - a tuple, such as those yielded by the Python lexer, in which case + the comparison algorithm is similar to the one in match() + XXX: + 1/ refactor match and __eq__ ? + 2/ make source.next and source.peek return a Token() instance + """ + if not isinstance(other, Token): + raise RuntimeError("Unexpected token type %r" % other) + if other is EmptyToken: + return False + if other.name != self.name: + return False + if other.value in self.keywords: + return False + return True + class EBNFVisitor(object): + def __init__(self): self.rules = {} self.terminals = {} @@ -101,10 +123,10 @@ def visit_alternative( self, node ): items = [ node.nodes[0].visit(self) ] - items+= node.nodes[1].visit(self) - if len(items)==1 and items[0].name.startswith(':'): + items += node.nodes[1].visit(self) + if len(items) == 1 and items[0].name.startswith(':'): return items[0] - alt = Alternative( self.new_name(), *items ) + alt = Alternative( self.new_name(), items ) return self.new_item( alt ) def visit_sequence( self, node ): @@ -115,16 +137,12 @@ if len(items)==1: return items[0] elif len(items)>1: - return self.new_item( Sequence( self.new_name(), *items) ) + return self.new_item( Sequence( self.new_name(), items) ) raise SyntaxError("Found empty sequence") def visit_sequence_cont( self, node ): """Returns a list of sequences (possibly empty)""" return [n.visit(self) for n in node.nodes] -## L = [] -## for n in node.nodes: -## L.append( n.visit(self) ) -## return L def visit_seq_cont_list(self, node): return node.nodes[1].visit(self) @@ -178,6 +196,7 @@ raise SyntaxError("Got symbol star_opt with value='%s'" % tok.value ) return myrule +rules = None def grammar_grammar(): """Builds the grammar for the grammar file @@ -193,37 +212,42 @@ option: '[' alternative ']' group: '(' alternative ')' star? """ + global rules # star: '*' | '+' - star = Alternative( "star", Token('*'), Token('+') ) + star = Alternative( "star", [Token('*'), Token('+')] ) star_opt = KleenStar ( "star_opt", 0, 1, rule=star ) # rule: SYMBOL ':' alternative - symbol = Sequence( "symbol", Token('SYMBOL'), star_opt ) + symbol = Sequence( "symbol", [Token('SYMBOL'), star_opt] ) symboldef = Token( "SYMDEF" ) - alternative = Sequence( "alternative" ) - rule = Sequence( "rule", symboldef, alternative ) + alternative = Sequence( "alternative", []) + rule = Sequence( "rule", [symboldef, alternative] ) # grammar: rule+ grammar = KleenStar( "grammar", _min=1, rule=rule ) # alternative: sequence ( '|' sequence )* sequence = KleenStar( "sequence", 1 ) - seq_cont_list = Sequence( "seq_cont_list", Token('|'), sequence ) + seq_cont_list = Sequence( "seq_cont_list", [Token('|'), sequence] ) sequence_cont = KleenStar( "sequence_cont",0, rule=seq_cont_list ) alternative.args = [ sequence, sequence_cont ] # option: '[' alternative ']' - option = Sequence( "option", Token('['), alternative, Token(']') ) + option = Sequence( "option", [Token('['), alternative, Token(']')] ) # group: '(' alternative ')' - group = Sequence( "group", Token('('), alternative, Token(')'), star_opt ) + group = Sequence( "group", [Token('('), alternative, Token(')'), star_opt] ) # sequence: (SYMBOL | STRING | option | group )+ string = Token('STRING') - alt = Alternative( "sequence_alt", symbol, string, option, group ) + alt = Alternative( "sequence_alt", [symbol, string, option, group] ) sequence.args = [ alt ] - + + + rules = [ star, star_opt, symbol, alternative, rule, grammar, sequence, + seq_cont_list, sequence_cont, option, group, alt ] + build_first_sets( rules ) return grammar @@ -244,7 +268,7 @@ from pprint import pprint if __name__ == "__main__": - grambuild = parse_grammar(file('../python/Grammar')) + grambuild = parse_grammar(file('data/Grammar2.3')) for i,r in enumerate(grambuild.items): print "% 3d : %s" % (i, r) pprint(grambuild.terminals.keys()) Modified: pypy/dist/pypy/module/recparser/grammar.py ============================================================================== --- pypy/dist/pypy/module/recparser/grammar.py (original) +++ pypy/dist/pypy/module/recparser/grammar.py Sat Jul 2 11:31:02 2005 @@ -9,6 +9,7 @@ """ DEBUG = 0 +USE_LOOKAHEAD = True #### Abstract interface for a lexer/tokenizer class TokenSource(object): @@ -35,15 +36,51 @@ """Returns the current line number""" return 0 + def get_pos(self): + """Returns the current source position of the scanner""" + return 0 + + def get_source_text(self, pos1, pos2 ): + """Returns the source text between two scanner positions""" + return "" + ###################################################################### + +def build_first_sets(rules): + """builds the real first tokens set for each rule in + + Because a rule can be recursive (directly or indirectly), the + *simplest* algorithm to build each first set is to recompute them + until Computation(N) = Computation(N-1), N being the number of rounds. + As an example, on Python2.3's grammar, we need 19 cycles to compute + full first sets. + """ + changed = True + while changed: + # loop while one first set is changed + changed = False + for rule in rules: + # For each rule, recompute first set + size = len(rule.first_set) + rule.calc_first_set() + new_size = len(rule.first_set) + if new_size != size: + changed = True + for r in rules: + assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r + r.reorder_rule() + + from syntaxtree import SyntaxNode, TempSyntaxNode, TokenNode class BaseGrammarBuilder(object): """Base/default class for a builder""" - def __init__( self, rules=None, debug=0): + def __init__(self, rules=None, debug=0): self.rules = rules or {} # a dictionary of grammar rules for debug/reference + # XXX This attribute is here for convenience + self.source_encoding = None self.debug = debug self.stack = [] @@ -60,7 +97,7 @@ # Do nothing, keep rule on top of the stack if rule.is_root(): elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.name, source, *elems) + self.stack[-1] = SyntaxNode(rule.name, source, elems) if self.debug: self.stack[-1].dumpstr() return True @@ -76,11 +113,11 @@ node_type = TempSyntaxNode # replace N elements with 1 element regrouping them if elts_number >= 1: - elem = node_type(rule.name, source, *items) + elem = node_type(rule.name, source, items) del self.stack[-elts_number:] self.stack.append(elem) elif elts_number == 0: - self.stack.append(node_type(rule.name, source)) + self.stack.append(node_type(rule.name, source, [])) if self.debug: self.stack[-1].dumpstr() return True @@ -102,15 +139,20 @@ self.name = name self.args = [] self._is_root = False + self.first_set = [] + self.first_set_complete = False + # self._processing = False + self._trace = False def is_root(self): """This is a root node of the grammar, that is one that will be included in the syntax tree""" - if self.name!=":" and self.name.startswith(":"): + if self.name != ":" and self.name.startswith(":"): return False return True + - def match(self, source, builder): + def match(self, source, builder, level=0): """Try to match a grammar rule If next set of tokens matches this grammar element, use @@ -122,7 +164,61 @@ returns None if no match or an object build by builder """ - return None + if not USE_LOOKAHEAD: + return self._match(source, builder, level) + pos1 = -1 # XXX make the annotator happy + pos2 = -1 # XXX make the annotator happy + token = source.peek() + if self._trace: + pos1 = source.get_pos() + in_first_set = self.match_first_set(token) + if not in_first_set: # and not EmptyToken in self.first_set: + if EmptyToken in self.first_set: + ret = builder.sequence(self, source, 0 ) + if self._trace: + self._debug_display(token, level, 'eee') + return self.debug_return( ret, 0 ) + if self._trace: + self._debug_display(token, level, 'rrr') + return 0 + elif self._trace: + self._debug_display(token, level, '>>>') + + res = self._match(source, builder, level) + if self._trace: + pos2 = source.get_pos() + if res: + prefix = '+++' + else: + prefix = '---' + self._debug_display(token, level, prefix) + print ' '*level, prefix, " TEXT ='%s'" % ( + source.get_source_text(pos1,pos2)) + if res: + print "*" * 50 + return res + + def _debug_display(self, token, level, prefix): + """prints context debug informations""" + prefix = '%s%s' % (' ' * level, prefix) + print prefix, " RULE =", self + print prefix, " TOKEN =", token + print prefix, " FIRST SET =", self.first_set + + + def _match(self, source, builder, level=0): + """Try to match a grammar rule + + If next set of tokens matches this grammar element, use + to build an appropriate object, otherwise returns 0. + + /!\ If the sets of element didn't match the current grammar + element, then the is restored as it was before the + call to the match() method + + returns None if no match or an object build by builder + """ + return 0 def parse(self, source): """Returns a simplified grammar if the rule matched at the source @@ -131,14 +227,6 @@ # To consider if we need to improve speed in parsing pass - def first_set(self): - """Returns a list of possible tokens that can start this rule - None means the rule can be empty - """ - # **NOT USED** **NOT IMPLEMENTED** - # To consider if we need to improve speed in parsing - pass - def __str__(self): return self.display(0) @@ -159,29 +247,61 @@ print "matched %s (%s): %s" % (self.__class__.__name__, sargs, self.display() ) return ret + + def calc_first_set(self): + """returns the list of possible next tokens + *must* be implemented in subclasses + """ + # XXX: first_set could probably be implemented with sets + return [] + + def match_first_set(self, other): + """matching is not equality: + token('NAME','x') matches token('NAME',None) + """ + for tk in self.first_set: + if tk.match_token( other ): + return True + return False + + def in_first_set(self, other): + return other in self.first_set + + def reorder_rule(self): + """Called after the computation of first set to allow rules to be reordered + to avoid ambiguities""" + pass + class Alternative(GrammarElement): """Represents an alternative in a grammar rule (as in S -> A | B | C)""" - def __init__(self, name, *args): + def __init__(self, name, args): GrammarElement.__init__(self, name ) - self.args = list(args) + self.args = args + self._reordered = False for i in self.args: assert isinstance( i, GrammarElement ) - def match(self, source, builder): + def _match(self, source, builder, level=0): """If any of the rules in self.args matches returns the object built from the first rules that matches """ if DEBUG>1: print "try alt:", self.display() + tok = source.peek() # Here we stop at the first match we should # try instead to get the longest alternative # to see if this solve our problems with infinite recursion for rule in self.args: - m = rule.match( source, builder ) + if USE_LOOKAHEAD: + if not rule.match_first_set(tok) and EmptyToken not in rule.first_set: + if self._trace: + print "Skipping impossible rule: %s" % (rule,) + continue + m = rule.match(source, builder, level+1) if m: ret = builder.alternative( self, source ) return self.debug_return( ret ) - return False + return 0 def display(self, level=0): if level==0: @@ -192,30 +312,71 @@ name = "" items = [ a.display(1) for a in self.args ] return name+"(" + "|".join( items ) + ")" - + def calc_first_set(self): + """returns the list of possible next tokens + if S -> (A | B | C): + LAH(S) = Union( LAH(A), LAH(B), LAH(C) ) + """ + # do this to avoid problems on indirect recursive rules + for rule in self.args: + for t in rule.first_set: + if t not in self.first_set: + self.first_set.append(t) + # self.first_set[t] = 1 + + def reorder_rule(self): + # take the opportunity to reorder rules in alternatives + # so that rules with Empty in their first set come last + # warn if two rules have empty in their first set + empty_set = [] + not_empty_set = [] + # is only needed for warning / debugging purposes + tokens_set = [] + for rule in self.args: + if EmptyToken in rule.first_set: + empty_set.append(rule) + else: + not_empty_set.append(rule) + if DEBUG: + # This loop is only neede dfor warning / debugging purposes + # It will check if a token is part of several first sets of + # a same alternative + for token in rule.first_set: + if token is not EmptyToken and token in tokens_set: + print "Warning, token %s in\n\t%s's first set is part " \ + "of a previous rule's first set in alternative\n\t" \ + "%s" % (token, rule, self) + tokens_set.append(token) + if len(empty_set) > 1 and not self._reordered: + print "Warning: alternative %s has more than one rule matching Empty" % self + self._reordered = True + self.args[:] = not_empty_set + self.args.extend( empty_set ) + + class Sequence(GrammarElement): """Reprensents a Sequence in a grammar rule (as in S -> A B C)""" - def __init__(self, name, *args): + def __init__(self, name, args): GrammarElement.__init__(self, name ) - self.args = list(args) + self.args = args for i in self.args: assert isinstance( i, GrammarElement ) - def match(self, source, builder): + def _match(self, source, builder, level=0): """matches all of the symbols in order""" if DEBUG>1: print "try seq:", self.display() ctx = source.context() bctx = builder.context() for rule in self.args: - m = rule.match(source, builder) + m = rule.match(source, builder, level+1) if not m: # Restore needed because some rules may have been matched # before the one that failed source.restore(ctx) builder.restore(bctx) - return None + return 0 ret = builder.sequence(self, source, len(self.args)) return self.debug_return( ret ) @@ -229,6 +390,32 @@ items = [a.display(1) for a in self.args] return name + "(" + " ".join( items ) + ")" + def calc_first_set(self): + """returns the list of possible next tokens + if S -> A* B C: + LAH(S) = Union( LAH(A), LAH(B) ) + if S -> A+ B C: + LAH(S) = LAH(A) + if S -> A B C: + LAH(S) = LAH(A) + """ + for rule in self.args: + if not rule.first_set: + break + if EmptyToken in self.first_set: + self.first_set.remove( EmptyToken ) + + # del self.first_set[EmptyToken] + # while we're in this loop, keep agregating possible tokens + for t in rule.first_set: + if t not in self.first_set: + self.first_set.append(t) + # self.first_set[t] = 1 + if EmptyToken not in rule.first_set: + break + + + class KleenStar(GrammarElement): """Represents a KleenStar in a grammar rule as in (S -> A+) or (S -> A*)""" def __init__(self, name, _min = 0, _max = -1, rule=None): @@ -239,8 +426,11 @@ raise ValueError("KleenStar needs max==-1 or max>1") self.max = _max self.star = "x" + if self.min == 0: + self.first_set.append( EmptyToken ) + # self.first_set[EmptyToken] = 1 - def match(self, source, builder): + def _match(self, source, builder, level=0): """matches a number of times self.args[0]. the number must be comprised between self._min and self._max inclusive. -1 is used to represent infinity""" if DEBUG>1: @@ -250,13 +440,13 @@ rules = 0 rule = self.args[0] while True: - m = rule.match(source, builder) + m = rule.match(source, builder, level+1) if not m: # Rule should be matched at least 'min' times if rules A*: + LAH(S) = Union( LAH(A), EmptyToken ) + if S -> A+: + LAH(S) = LAH(A) + """ + rule = self.args[0] + self.first_set = rule.first_set[:] + # self.first_set = dict(rule.first_set) + if self.min == 0 and EmptyToken not in self.first_set: + self.first_set.append(EmptyToken) + # self.first_set[EmptyToken] = 1 + class Token(GrammarElement): """Represents a Token in a grammar rule (a lexer token)""" def __init__( self, name, value = None): GrammarElement.__init__( self, name ) self.value = value + self.first_set = [self] + # self.first_set = {self: 1} - def match(self, source, builder): + def match(self, source, builder, level=0): """Matches a token. the default implementation is to match any token whose type corresponds to the object's name. You can extend Token @@ -300,18 +506,19 @@ # error unknown or negative integer """ ctx = source.context() - tk_type, tk_value = source.next() - if tk_type==self.name: + tk = source.next() + # XXX: match_token + if tk.name == self.name: if self.value is None: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type ) - elif self.value == tk_value: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type, tk_value ) + ret = builder.token( tk.name, tk.value, source ) + return self.debug_return( ret, tk.name ) + elif self.value == tk.value: + ret = builder.token( tk.name, tk.value, source ) + return self.debug_return( ret, tk.name, tk.value ) if DEBUG>1: print "tried tok:", self.display() source.restore( ctx ) - return None + return 0 def display(self, level=0): if self.value is None: @@ -320,3 +527,33 @@ return "<%s>=='%s'" % (self.name, self.value) + def match_token(self, other): + """convenience '==' implementation, this is *not* a *real* equality test + a Token instance can be compared to: + - another Token instance in which case all fields (name and value) + must be equal + - a tuple, such as those yielded by the Python lexer, in which case + the comparison algorithm is similar to the one in match() + XXX: + 1/ refactor match and __eq__ ? + 2/ make source.next and source.peek return a Token() instance + """ + if not isinstance(other, Token): + raise RuntimeError("Unexpected token type %r" % other) + if other is EmptyToken: + return False + res = other.name == self.name and self.value in (None, other.value) + #print "matching", self, other, res + return res + + def __eq__(self, other): + return self.name == other.name and self.value == other.value + + + + def calc_first_set(self): + """computes the list of possible next tokens + """ + pass + +EmptyToken = Token(None) Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Sat Jul 2 11:31:02 2005 @@ -9,7 +9,7 @@ from pypy.interpreter.pycode import PyCode from syntaxtree import SyntaxNode from pythonparse import parse_python_source -from pypy.module.recparser import PYTHON_PARSER +from pythonutil import PYTHON_PARSER __all__ = [ "ASTType", "STType", "suite", "expr" ] Modified: pypy/dist/pypy/module/recparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/module/recparser/pythonlexer.py (original) +++ pypy/dist/pypy/module/recparser/pythonlexer.py Sat Jul 2 11:31:02 2005 @@ -3,49 +3,45 @@ analyser in grammar.py """ -from grammar import TokenSource - -DEBUG = False -import re - -KEYWORDS = [ - 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', - 'elif', 'if', 'import', 'in', 'is', 'finally', 'for', 'from', - 'global', 'else', 'except', 'exec', 'lambda', 'not', 'or', - 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield' - ] - -py_keywords = re.compile(r'(%s)$' % ('|'.join(KEYWORDS)), re.M | re.X) - -py_punct = re.compile(r""" -<>|!=|==|~| -<=|<<=|<<|<| ->=|>>=|>>|>| -\*=|\*\*=|\*\*|\*| -//=|/=|//|/| -%=|\^=|\|=|\+=|=|&=|-=| -,|\^|&|\+|-|\.|%|\|| -\)|\(|;|:|@|\[|\]|`|\{|\} -""", re.M | re.X) - -g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:", re.M) -g_string = re.compile(r"'[^']+'", re.M) -py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) -py_comment = re.compile(r"#.*$|[ \t\014]*$", re.M) -py_ws = re.compile(r" *", re.M) -py_skip = re.compile(r"[ \t\014]*(#.*$)?", re.M) -py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") -# py_number = re.compile(r"0x[0-9a-z]+|[0-9]+l|([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?j?||[0-9]+", re.I) - -# 0x[\da-f]+l matches hexadecimal numbers, possibly defined as long -# \d+l matches and only matches long integers -# (\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? matches simple integers, -# exponential notations and complex -py_number = re.compile(r"""0x[\da-f]+l?| -\d+l| -(\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? -""", re.I | re.X) - +from grammar import TokenSource, Token +# Don't import string for that ... +NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' +NUMCHARS = '0123456789' +ALNUMCHARS = NAMECHARS + NUMCHARS +EXTENDED_ALNUMCHARS = ALNUMCHARS + '-.' +WHITESPACES = ' \t\n\r\v\f' + +def match_encoding_declaration(comment): + """returns the declared encoding or None + + This function is a replacement for : + >>> py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") + >>> py_encoding.search(comment) + """ + index = comment.find('coding') + if index == -1: + return None + next_char = comment[index + 6] + if next_char not in ':=': + return None + end_of_decl = comment[index + 7:] + index = 0 + for char in end_of_decl: + if char not in WHITESPACES: + break + index += 1 + else: + return None + encoding = '' + for char in end_of_decl[index:]: + if char in EXTENDED_ALNUMCHARS: + encoding += char + else: + break + if encoding != '': + return encoding + return None + def _normalize_encoding(encoding): """returns normalized name for @@ -64,25 +60,258 @@ return 'iso-8859-1' return encoding +################################################################################ +import token as tokenmod +from pytokenize import tabsize, whiteSpaceDFA, triple_quoted, endDFAs, \ + single_quoted, pseudoDFA +import automata + +# adopt pytokenize notations / values +tokenmod.COMMENT = tokenmod.N_TOKENS +tokenmod.NL = tokenmod.N_TOKENS + 1 + +class TokenError(Exception): + """Raised when EOF is found prematuerly""" + def __init__(self, msg, strstart, token_stack): + # Exception.__init__(self, msg) + self.strstart = strstart + self.token_stack = token_stack + + +def generate_tokens(lines): + """ + This is a rewrite of pypy.module.parser.pytokenize.generate_tokens since + the original function is not RPYTHON (uses yield) + It was also slightly modified to generate Token instances instead + of the original 5-tuples + + Original docstring :: + + The generate_tokens() generator requires one argment, readline, which + must be a callable object which provides the same interface as the + readline() method of built-in file objects. Each call to the function + should return one line of input as a string. + + The generator produces 5-tuples with these members: the token type; the + token string; a 2-tuple (srow, scol) of ints specifying the row and + column where the token begins in the source; a 2-tuple (erow, ecol) of + ints specifying the row and column where the token ends in the source; + and the line on which the token was found. The line passed is the + logical line; continuation lines are included. + """ + token_list = [] + lnum = parenlev = continued = 0 + namechars = NAMECHARS + numchars = NUMCHARS + contstr, needcont = '', 0 + contline = None + indents = [0] + last_comment = '' + encoding = None + strstart = (0, 0) + + lines.append('') # XXX HACK probably not needed + endDFA = automata.DFA([], []) # XXX Make the translator happy + line = '' # XXX Make the translator happy + for line in lines: + lnum = lnum + 1 + pos, max = 0, len(line) + + if contstr: # continued string + if not line: + raise TokenError("EOF in multi-line string", strstart, token_list) + endmatch = endDFA.recognize(line) + if -1 != endmatch: + pos = end = endmatch + tok = token_from_values(tokenmod.STRING, contstr + line[:end]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, contstr + line[:end], + # strstart, (lnum, end), contline + line)) + contstr, needcont = '', 0 + contline = None + elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + tok = token_from_values(tokenmod.ERRORTOKEN, contstr + line) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((ERRORTOKEN, contstr + line, + # strstart, (lnum, len(line)), contline)) + contstr = '' + contline = None + continue + else: + contstr = contstr + line + contline = contline + line + continue + + elif parenlev == 0 and not continued: # new statement + if not line: break + column = 0 + while pos < max: # measure leading whitespace + if line[pos] == ' ': column = column + 1 + elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize + elif line[pos] == '\f': column = 0 + else: break + pos = pos + 1 + if pos == max: break + + if line[pos] in '#\r\n': # skip comments or blank lines + if line[pos] == '#': + tok = token_from_values(tokenmod.COMMENT, line[pos:]) + last_comment = line[pos:] + if lnum <= 2 and encoding is None: + encoding = match_encoding_declaration(last_comment) + if encoding is not None: + encoding = _normalize_encoding(encoding) + else: + tok = token_from_values(tokenmod.NL, line[pos:]) + last_comment = '' + # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line)) + # token_list.append(((NL, COMMENT)[line[pos] == '#'], line[pos:], + # (lnum, pos), (lnum, len(line)), line)) + continue + + if column > indents[-1]: # count indents or dedents + indents.append(column) + tok = token_from_values(tokenmod.INDENT, line[:pos]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((INDENT, line[:pos], (lnum, 0), (lnum, pos), line)) + while column < indents[-1]: + indents = indents[:-1] + tok = token_from_values(tokenmod.DEDENT, '') + token_list.append((tok, line)) + last_comment = '' + # token_list.append((DEDENT, '', (lnum, pos), (lnum, pos), line)) + + else: # continued statement + if not line: + raise TokenError("EOF in multi-line statement", (lnum, 0), token_list) + continued = 0 + + while pos < max: + pseudomatch = pseudoDFA.recognize(line, pos) + if -1 != pseudomatch: # scan for tokens + # JDR: Modified + start = whiteSpaceDFA.recognize(line, pos) + if -1 == start: + start = pos + end = pseudomatch + + spos, epos, pos = (lnum, start), (lnum, end), end + token, initial = line[start:end], line[start] + + if initial in numchars or \ + (initial == '.' and token != '.'): # ordinary number + tok = token_from_values(tokenmod.NUMBER, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((NUMBER, token, spos, epos, line)) + elif initial in '\r\n': + if parenlev > 0: + tok = token_from_values(tokenmod.NL, token) + last_comment = '' + # XXX Skip NL + else: + tok = token_from_values(tokenmod.NEWLINE, token) + # XXX YUCK ! + tok.value = last_comment + token_list.append((tok, line)) + last_comment = '' + # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) + elif initial == '#': + tok = token_from_values(tokenmod.COMMENT, token) + last_comment = token + if lnum <= 2 and encoding is None: + encoding = match_encoding_declaration(last_comment) + if encoding is not None: + encoding = _normalize_encoding(encoding) + # XXX Skip # token_list.append((tok, line)) + # token_list.append((COMMENT, token, spos, epos, line)) + elif token in triple_quoted: + endDFA = endDFAs[token] + endmatch = endDFA.recognize(line, pos) + if -1 != endmatch: # all on one line + pos = endmatch + token = line[start:pos] + tok = token_from_values(tokenmod.STRING, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, token, spos, (lnum, pos), line)) + else: + strstart = (lnum, start) # multiple lines + contstr = line[start:] + contline = line + break + elif initial in single_quoted or \ + token[:2] in single_quoted or \ + token[:3] in single_quoted: + if token[-1] == '\n': # continued string + strstart = (lnum, start) + endDFA = (endDFAs[initial] or endDFAs[token[1]] or + endDFAs[token[2]]) + contstr, needcont = line[start:], 1 + contline = line + break + else: # ordinary string + tok = token_from_values(tokenmod.STRING, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, token, spos, epos, line)) + elif initial in namechars: # ordinary name + tok = token_from_values(tokenmod.NAME, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((NAME, token, spos, epos, line)) + elif initial == '\\': # continued stmt + continued = 1 + else: + if initial in '([{': parenlev = parenlev + 1 + elif initial in ')]}': parenlev = parenlev - 1 + tok = token_from_values(tokenmod.OP, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((OP, token, spos, epos, line)) + else: + tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((ERRORTOKEN, line[pos], + # (lnum, pos), (lnum, pos+1), line)) + pos = pos + 1 + + last_comment = '' + for indent in indents[1:]: # pop remaining indent levels + tok = token_from_values(tokenmod.DEDENT, '') + token_list.append((tok, line)) + # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) + + ## adim + token_list.append((Token('NEWLINE', ''), line)) + ## + tok = token_from_values(tokenmod.ENDMARKER, '',) + token_list.append((tok, line)) + # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) + return token_list, encoding + class PythonSource(TokenSource): - """The Python tokenizer""" - def __init__(self, inpstring): - TokenSource.__init__(self) - self.input = inpstring - self.pos = 0 - self.indent = 0 - self.indentstack = [ 0 ] - self.atbol = True - self.line = 1 - self._current_line = 1 - self.pendin = 0 # indentation change waiting to be reported - self.level = 0 - self.linestart = 0 - self.stack = [] + """This source uses Jonathan's tokenizer""" + def __init__(self, strings): + # TokenSource.__init__(self) + tokens, encoding = generate_tokens(strings) + self.token_stack = tokens + self.encoding = encoding + self._current_line = '' # the current line (as a string) self.stack_pos = 0 - self.comment = '' - self.encoding = None - + + def next(self): + if self.stack_pos >= len(self.token_stack): + raise StopIteration("Remove me") + tok, line = self.token_stack[self.stack_pos] + self.stack_pos += 1 + self._current_line = line + return tok + def current_line(self): return self._current_line @@ -92,6 +321,14 @@ def restore(self, ctx): self.stack_pos = ctx + def peek(self): + """returns next token without consuming it""" + ctx = self.context() + token = self.next() + self.restore(ctx) + return token + + #### methods below have to be translated def offset(self, ctx=None): if ctx is None: return self.stack_pos @@ -99,310 +336,40 @@ assert type(ctx)==int return ctx - def _next(self): - """returns the next token from source""" - inp = self.input - pos = self.pos - input_length = len(inp) - if pos >= input_length: - return self.end_of_file() - # Beginning of line - if self.atbol: - self.linestart = pos - col = 0 - m = py_ws.match(inp, pos) - pos = m.end() - col = pos - self.linestart - self.atbol = False - # skip blanklines - m = py_comment.match(inp, pos) - if m: - if not self.comment: - self.comment = m.group(0) - # XXX FIXME: encoding management - if self.line <= 2: - # self.comment can be the previous comment, so don't use it - comment = m.group(0)[1:] - m_enc = py_encoding.search(comment) - if m_enc is not None: - self.encoding = _normalize_encoding(m_enc.group(1)) - # - self.pos = m.end() + 1 - self.line += 1 - self.atbol = True - return self._next() - # the current block is more indented than the previous one - if col > self.indentstack[-1]: - self.indentstack.append(col) - return "INDENT", None - # the current block is less indented than the previous one - while col < self.indentstack[-1]: - self.pendin += 1 - self.indentstack.pop(-1) - if col != self.indentstack[-1]: - raise SyntaxError("Indentation Error") - if self.pendin > 0: - self.pendin -= 1 - return "DEDENT", None - m = py_skip.match(inp, pos) - if m.group(0)[-1:] == '\n': - self.line += 1 - self.comment = m.group(1) or '' - pos = m.end() # always match - if pos >= input_length: - return self.end_of_file() - self.pos = pos - - # STRING - c = inp[pos] - if c in ('r','R'): - if pos < input_length-1 and inp[pos+1] in ("'",'"'): - return self.next_string(raw=1) - elif c in ('u','U'): - if pos < input_length-1: - if inp[pos+1] in ("r",'R'): - if pos 0: - return self._next() - else: - self.atbol = True - comment = self.comment - self.comment = '' - return "NEWLINE", comment - - if c == '\\': - if pos < input_length-1 and inp[pos+1] == '\n': - self.pos += 2 - return self._next() - - m = py_punct.match(inp, pos) - if m: - punct = m.group(0) - if punct in ( '(', '{', '[' ): - self.level += 1 - if punct in ( ')', '}', ']' ): - self.level -= 1 - self.pos = m.end() - return punct, None - raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) - - def next(self): + def get_pos(self): if self.stack_pos >= len(self.stack): - tok, val = self._next() - self.stack.append( (tok, val, self.line) ) - self._current_line = self.line + return self.pos else: - tok,val,line = self.stack[self.stack_pos] - self._current_line = line - self.stack_pos += 1 - if DEBUG: - print "%d/%d: %s, %s" % (self.stack_pos, len(self.stack), tok, val) - return (tok, val) - - def end_of_file(self): - """return DEDENT and ENDMARKER""" - if len(self.indentstack) == 1: - self.indentstack.pop(-1) - return "NEWLINE", '' #self.comment - elif len(self.indentstack) > 1: - self.indentstack.pop(-1) - return "DEDENT", None - return "ENDMARKER", None - - - def next_string(self, raw=0, uni=0): - pos = self.pos + raw + uni - inp = self.input - quote = inp[pos] - qsize = 1 - if inp[pos:pos+3] == 3*quote: - pos += 3 - quote = 3*quote - qsize = 3 - else: - pos += 1 - while True: - if inp[pos:pos+qsize] == quote: - s = inp[self.pos:pos+qsize] - self.pos = pos+qsize - return "STRING", s - # FIXME : shouldn't it be inp[pos] == os.linesep ? - if inp[pos:pos+2] == "\n" and qsize == 1: - return None, None - if inp[pos] == "\\": - pos += 1 - pos += 1 + token, line, pos = self.stack[self.stack_pos] + return pos + def get_source_text(self, pos0, pos1 ): + return self.input[pos0:pos1] + def debug(self): """return context for debug information""" - if not hasattr(self, '_lines'): - # split lines only once - self._lines = self.input.splitlines() - if self.line > len(self._lines): - lineno = len(self._lines) - else: - lineno = self.line - return 'line %s : %s' % (lineno, self._lines[lineno-1]) - - ## ONLY refactor ideas ########################################### -## def _mynext(self): -## """returns the next token from source""" -## inp = self.input -## pos = self.pos -## input_length = len(inp) -## if pos >= input_length: -## return self.end_of_file() -## # Beginning of line -## if self.atbol: -## self.linestart = pos -## col = 0 -## m = py_ws.match(inp, pos) -## pos = m.end() -## col = pos - self.linestart -## self.atbol = False -## # skip blanklines -## m = py_comment.match(inp, pos) -## if m: -## self.pos = m.end() + 1 -## self.line += 1 -## self.atbol = True -## return self._next() -## # the current block is more indented than the previous one -## if col > self.indentstack[-1]: -## self.indentstack.append(col) -## return "INDENT", None -## # the current block is less indented than the previous one -## while col < self.indentstack[-1]: -## self.pendin += 1 -## self.indentstack.pop(-1) -## if col != self.indentstack[-1]: -## raise SyntaxError("Indentation Error") -## if self.pendin > 0: -## self.pendin -= 1 -## return "DEDENT", None -## m = py_skip.match(inp, pos) -## if m.group(0)[-1:] == '\n': -## self.line += 1 -## pos = m.end() # always match -## if pos >= input_length: -## return self.end_of_file() -## self.pos = pos - -## c = inp[pos] -## chain = (self._check_string, self._check_name, self._check_number, -## self._check_newline, self._check_backslash, self._check_punct) -## for check_meth in chain: -## token_val_pair = check_meth(c, pos) -## if token_val_pair is not None: -## return token_val_pair - + return 'line %s : %s' % ('XXX', self._current_line) -## def _check_string(self, c, pos): -## inp = self.input -## input_length = len(inp) -## # STRING -## if c in ('r', 'R'): -## if pos < input_length-1 and inp[pos+1] in ("'",'"'): -## return self.next_string(raw=1) -## elif c in ('u','U'): -## if pos < input_length - 1: -## if inp[pos+1] in ("r", 'R'): -## if pos 0: -## return self._next() -## else: -## self.atbol = True -## return "NEWLINE", None -## return None - -## def _check_backslash(self, c, pos): -## inp = self.input -## input_length = len(inp) -## if c == '\\': -## if pos < input_length-1 and inp[pos+1] == '\n': -## self.pos += 2 -## return self._next() -## return None - -## def _check_punct(self, c, pos): -## inp = self.input -## input_length = len(inp) -## m = py_punct.match(inp, pos) -## if m: -## punct = m.group(0) -## if punct in ( '(', '{' ): -## self.level += 1 -## if punct in ( ')', '}' ): -## self.level -= 1 -## self.pos = m.end() -## return punct, None -## raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) +NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] +NAMED_LIST = [tokenmod.OP, ] +def token_from_values(tok_type, tok_string): + """XXX Compatibility layer between both parsers""" + if tok_type in NONE_LIST: + return Token(tokenmod.tok_name[tok_type], None) + if tok_type in NAMED_LIST: + return Token(tok_string, None) + if tok_type == tokenmod.NEWLINE: + return Token('NEWLINE', '') # XXX pending comment ? + return Token(tokenmod.tok_name[tok_type], tok_string) +Source = PythonSource def tokenize_file(filename): f = file(filename).read() - src = PythonSource(f) + src = Source(f) token = src.next() - while token!=("ENDMARKER",None) and token!=(None,None): + while token != ("ENDMARKER", None) and token != (None, None): print token token = src.next() Modified: pypy/dist/pypy/module/recparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/module/recparser/pythonparse.py (original) +++ pypy/dist/pypy/module/recparser/pythonparse.py Sat Jul 2 11:31:02 2005 @@ -1,65 +1,51 @@ #!/usr/bin/env python -from grammar import BaseGrammarBuilder -from pythonlexer import PythonSource +from pythonlexer import Source from ebnfparse import parse_grammar import sys -import pythonutil +import os import symbol +import grammar -def parse_python_source( textsrc, gram, goal ): +# parse the python grammar corresponding to our CPython version +_ver = ".".join([str(i) for i in sys.version_info[:2]]) +PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) + +def python_grammar(): + """returns a """ + level = grammar.DEBUG + grammar.DEBUG = 0 + gram = parse_grammar( file(PYTHON_GRAMMAR) ) + grammar.DEBUG = level + # Build first sets for each rule (including anonymous ones) + grammar.build_first_sets(gram.items) + return gram + +PYTHON_PARSER = python_grammar() + + +def parse_python_source( textsrc, gram, goal, builder=None ): """Parse a python source according to goal""" target = gram.rules[goal] - src = PythonSource(textsrc) - builder = BaseGrammarBuilder(debug=False, rules=gram.rules) + src = Source(textsrc) + if builder is None: + builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) result = target.match(src, builder) # XXX find a clean way to process encoding declarations - if src.encoding: - builder._source_encoding = src.encoding + builder.source_encoding = src.encoding # if not result: - raise SyntaxError("at %s" % src.debug() ) + return None + # raise SyntaxError("at %s" % src.debug() ) return builder -def parse_file_input(pyf, gram): +def parse_file_input(pyf, gram, builder=None): """Parse a python file""" - return parse_python_source( pyf.read(), gram, "file_input" ) + return parse_python_source( pyf.read(), gram, "file_input", builder ) -def parse_single_input(textsrc, gram): - """Parse a python file""" - return parse_python_source( textsrc, gram, "single_input" ) - -def parse_eval_input(textsrc, gram): - """Parse a python file""" - return parse_python_source( textsrc, gram, "eval_input" ) - -def pypy_parse(filename): - """parse using PyPy's parser module and return nested tuples - """ - pyf = file(filename) - builder = parse_file_input(pyf, pythonutil.python_grammar()) - pyf.close() - if builder.stack: - # print builder.stack[-1] - root_node = builder.stack[-1] - nested_tuples = root_node.totuple() - if hasattr(builder, '_source_encoding'): - # XXX: maybe the parser could fix that instead ? - return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) - else: - return nested_tuples - return None # XXX raise an exception instead - -if __name__ == "__main__": - if len(sys.argv) < 2: - print "python parse.py [-d N] test_file.py" - sys.exit(1) - if sys.argv[1] == "-d": - debug_level = int(sys.argv[2]) - test_file = sys.argv[3] - else: - test_file = sys.argv[1] - print "-"*20 - print - print "pyparse \n", pypy_parse(test_file) - print "parser \n", pythonutil.python_parse(test_file) - +def parse_single_input(textsrc, gram, builder=None): + """Parse a python single statement""" + return parse_python_source( textsrc, gram, "single_input", builder ) + +def parse_eval_input(textsrc, gram, builder=None): + """Parse a python expression""" + return parse_python_source( textsrc, gram, "eval_input", builder ) Modified: pypy/dist/pypy/module/recparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/module/recparser/pythonutil.py (original) +++ pypy/dist/pypy/module/recparser/pythonutil.py Sat Jul 2 11:31:02 2005 @@ -1,30 +1,12 @@ -__all__ = ["python_grammar", "PYTHON_GRAMMAR" ] +__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", + "ast_eval_input" ] -import os -import sys - -_ver = ".".join([str(i) for i in sys.version_info[:2]]) -PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) - -def python_grammar(): - """returns a """ - from ebnfparse import parse_grammar - level = get_debug() - set_debug( 0 ) - gram = parse_grammar( file(PYTHON_GRAMMAR) ) - set_debug( level ) - return gram - -def get_debug(): - """Return debug level""" - import grammar - return grammar.DEBUG - -def set_debug( level ): - """sets debug mode to """ - import grammar - grammar.DEBUG = level +import grammar +import pythonparse +from compiler.transformer import Transformer +from tuplebuilder import TupleBuilder +PYTHON_PARSER = pythonparse.PYTHON_PARSER def python_parse(filename): """parse using CPython's parser module and return nested tuples @@ -33,3 +15,84 @@ import parser tp2 = parser.suite(pyf.read()) return tp2.totuple() + +import symbol +def pypy_parse(filename): + """parse using PyPy's parser module and return + a tuple of three elements : + - The encoding declaration symbol or None if there were no encoding + statement + - The TupleBuilder's stack top element (instance of + tuplebuilder.StackElement which is a wrapper of some nested tuples + like those returned by the CPython's parser) + - The encoding string or None if there were no encoding statement + nested tuples + """ + pyf = file(filename) + text = pyf.read() + pyf.close() + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) + # make the annotator life easier + strings = [line+'\n' for line in text.split('\n')] + pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + nested_tuples = builder.stack[-1] + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + +def annotateme(strings): + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) + pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + nested_tuples = builder.stack[-1] + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + +def ast_single_input( text ): + builder = TupleBuilder( PYTHON_PARSER.rules ) + pythonparse.parse_python_source( text, PYTHON_PARSER, "single_input", builder ) + tree = builder.stack[-1] + trans = Transformer() + ast = trans.transform( tree ) + return ast + +def ast_file_input( filename ): + pyf = file(filename,"r") + text = pyf.read() + return ast_srcfile_input( text, filename ) + +def ast_srcfile_input( srctext, filename ): + # TODO do something with the filename + builder = TupleBuilder( PYTHON_PARSER.rules ) + pythonparse.parse_python_source( srctext, PYTHON_PARSER, "file_input", builder ) + tree = builder.stack[-1] + trans = Transformer() + ast = trans.transform( tree ) + return ast + +def ast_eval_input( textsrc ): + builder = TupleBuilder( PYTHON_PARSER.rules ) + pythonparse.parse_python_source( textsrc, PYTHON_PARSER, "eval_input", builder ) + tree = builder.stack[-1] + trans = Transformer() + ast = trans.transform( tree ) + return ast + + + +if __name__ == "__main__": + import sys + if len(sys.argv) < 2: + print "python parse.py [-d N] test_file.py" + sys.exit(1) + if sys.argv[1] == "-d": + debug_level = int(sys.argv[2]) + test_file = sys.argv[3] + else: + test_file = sys.argv[1] + print "-"*20 + print + print "pyparse \n", pypy_parse(test_file) + print "parser \n", python_parse(test_file) Modified: pypy/dist/pypy/module/recparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/module/recparser/syntaxtree.py (original) +++ pypy/dist/pypy/module/recparser/syntaxtree.py Sat Jul 2 11:31:02 2005 @@ -60,20 +60,21 @@ "|" : token.VBAR, "|=" : token.VBAREQUAL, } - +NT_OFFSET = token.NT_OFFSET + SYMBOLS = {} # copies the numerical mapping between symbol name and symbol value # into SYMBOLS -for k,v in symbol.__dict__.items(): - if type(v)==int: - SYMBOLS[k] = v +for k,v in symbol.sym_name.items(): + SYMBOLS[v] = k +SYMBOLS['UNKNOWN'] = -1 class SyntaxNode(object): """A syntax node""" - def __init__(self, name, source, *args): + def __init__(self, name, source, args): self.name = name - self.nodes = list(args) + self.nodes = args self.lineno = source.current_line() def dumptree(self, treenodes, indent): @@ -102,6 +103,7 @@ return "(%s)" % self.name def visit(self, visitor): + """NOT RPYTHON, used only at bootstrap time anyway""" visit_meth = getattr(visitor, "visit_%s" % self.name, None) if visit_meth: return visit_meth(self) @@ -114,7 +116,7 @@ return [ self ] def totuple(self, lineno=False ): - symvalue = SYMBOLS.get( self.name, (0,self.name) ) + symvalue = SYMBOLS.get( self.name, (0, self.name) ) l = [ symvalue ] l += [node.totuple(lineno) for node in self.nodes] return tuple(l) @@ -128,7 +130,7 @@ class TokenNode(SyntaxNode): """A token node""" def __init__(self, name, source, value): - SyntaxNode.__init__(self, name, source) + SyntaxNode.__init__(self, name, source, []) self.value = value def dumptree(self, treenodes, indent): Modified: pypy/dist/pypy/module/recparser/test/test_pytokenizer.py ============================================================================== --- pypy/dist/pypy/module/recparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/module/recparser/test/test_pytokenizer.py Sat Jul 2 11:31:02 2005 @@ -1,79 +1,93 @@ -from pypy.module.recparser.pythonlexer import PythonSource, py_number, \ - g_symdef, g_string, py_name, py_punct +from pypy.module.recparser.pythonlexer import Source, TokenError, \ + match_encoding_declaration +from pypy.module.recparser.grammar import Token def parse_source(source): """returns list of parsed tokens""" - lexer = PythonSource(source) + lexer = Source(source.splitlines(True)) tokens = [] - last_token = '' - while last_token != 'ENDMARKER': - last_token, value = lexer.next() - tokens.append((last_token, value)) + last_token = Token(None, None) + while last_token.name != 'ENDMARKER': + last_token = lexer.next() + # tokens.append((last_token, value)) + tokens.append(last_token) return tokens -class TestSuite: - """Tokenizer test suite""" - PUNCTS = [ - # Here should be listed each existing punctuation - '>=', '<>', '!=', '<', '>', '<=', '==', '*=', - '//=', '%=', '^=', '<<=', '**=', '|=', - '+=', '>>=', '=', '&=', '/=', '-=', ',', '^', - '>>', '&', '+', '*', '-', '/', '.', '**', - '%', '<<', '//', '|', ')', '(', ';', ':', - '@', '[', ']', '`', '{', '}', - ] - - NUMBERS = [ - # Here should be listed each different form of number - '1', '1.23', '1.', '0', - '1L', '1l', - '0x12L', '0x12l', '0X12', '0x12', - '1j', '1J', - '1e2', '1.2e4', - '0.1', '0.', '0.12', '.2', - ] - - BAD_NUMBERS = [ - 'j', '0xg', '0xj', '0xJ', - ] - - def test_empty_string(self): - """make sure defined regexps don't match empty string""" - rgxes = {'numbers' : py_number, - 'defsym' : g_symdef, - 'strings' : g_string, - 'names' : py_name, - 'punct' : py_punct, - } - for label, rgx in rgxes.items(): - assert rgx.match('') is None, '%s matches empty string' % label - - def test_several_lines_list(self): - """tests list definition on several lines""" - s = """['a' - ]""" - tokens = parse_source(s) - assert tokens == [('[', None), ('STRING', "'a'"), (']', None), - ('NEWLINE', ''), ('ENDMARKER', None)] - - def test_numbers(self): - """make sure all kind of numbers are correctly parsed""" - for number in self.NUMBERS: - assert parse_source(number)[0] == ('NUMBER', number) - neg = '-%s' % number - assert parse_source(neg)[:2] == [('-', None), ('NUMBER', number)] - for number in self.BAD_NUMBERS: - assert parse_source(number)[0] != ('NUMBER', number) - - def test_hex_number(self): - """basic pasrse""" - tokens = parse_source("a = 0x12L") - assert tokens == [('NAME', 'a'), ('=', None), ('NUMBER', '0x12L'), - ('NEWLINE', ''), ('ENDMARKER', None)] - - def test_punct(self): - """make sure each punctuation is correctly parsed""" - for pstr in self.PUNCTS: +## class TestSuite: +## """Tokenizer test suite""" +PUNCTS = [ + # Here should be listed each existing punctuation + '>=', '<>', '!=', '<', '>', '<=', '==', '*=', + '//=', '%=', '^=', '<<=', '**=', '|=', + '+=', '>>=', '=', '&=', '/=', '-=', ',', '^', + '>>', '&', '+', '*', '-', '/', '.', '**', + '%', '<<', '//', '|', ')', '(', ';', ':', + # '@', # XXX This one is skipped for now (?!) + '[', ']', '`', '{', '}', + ] + +NUMBERS = [ + # Here should be listed each different form of number + '1', '1.23', '1.', '0', + '1L', '1l', + '0x12L', '0x12l', '0X12', '0x12', + '1j', '1J', + '1e2', '1.2e4', + '0.1', '0.', '0.12', '.2', + ] + +BAD_NUMBERS = [ + 'j', '0xg', '0xj', '0xJ', + ] + +def test_several_lines_list(): + """tests list definition on several lines""" + s = """['a' + ]""" + tokens = parse_source(s) + assert tokens == [Token('[', None), Token('STRING', "'a'"), + Token(']', None), Token('NEWLINE', ''), + Token('ENDMARKER', None)] + +def test_numbers(): + """make sure all kind of numbers are correctly parsed""" + for number in NUMBERS: + assert parse_source(number)[0] == Token('NUMBER', number) + neg = '-%s' % number + assert parse_source(neg)[:2] == [Token('-', None), + Token('NUMBER', number)] + for number in BAD_NUMBERS: + assert parse_source(number)[0] != Token('NUMBER', number) + +def test_hex_number(): + """basic pasrse""" + tokens = parse_source("a = 0x12L") + assert tokens == [Token('NAME', 'a'), Token('=', None), + Token('NUMBER', '0x12L'), Token('NEWLINE', ''), + Token('ENDMARKER', None)] + +def test_punct(): + """make sure each punctuation is correctly parsed""" + for pstr in PUNCTS: + try: tokens = parse_source(pstr) - assert tokens[0][0] == pstr - + except TokenError, error: + tokens = [tok for tok, line in error.token_stack] + assert tokens[0].name == pstr + + +def test_encoding_declarations_match(): + checks = [ + ('# -*- coding: ISO-8859-1 -*-', 'ISO-8859-1'), + ('# -*- coding: ISO-8859-1 -*-\n', 'ISO-8859-1'), + ('# -*- coding: ISO-8859-1', 'ISO-8859-1'), + ('# -*- coding= UTF-8', 'UTF-8'), + ('# coding= UTF-8', 'UTF-8'), + ('# coding= UTF-8 hello', 'UTF-8'), + ('# -*- coding: ISO_8859-1', 'ISO_8859-1'), + ('# -*- coding ISO_8859-1', None), + ('# coding ISO_8859-1', None), + ] + for comment, encoding in checks: + res = match_encoding_declaration(comment) + assert res == encoding, "Failed on (%s), %s != %s" % (comment, res, encoding) Modified: pypy/dist/pypy/module/recparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/module/recparser/test/test_samples.py (original) +++ pypy/dist/pypy/module/recparser/test/test_samples.py Sat Jul 2 11:31:02 2005 @@ -1,7 +1,7 @@ """test module for CPython / PyPy nested tuples comparison""" import os, os.path as osp -from pypy.module.recparser.pythonutil import python_parse -from pypy.module.recparser.pythonparse import pypy_parse +from pypy.module.recparser.pythonutil import python_parse, pypy_parse +# from pypy.module.recparser.pythonparse import pypy_parse from pprint import pprint from pypy.module.recparser import grammar grammar.DEBUG = False @@ -39,21 +39,30 @@ def assert_tuples_equal(tup1, tup2, curpos = ()): for index, (elt1, elt2) in enumerate(zip(tup1, tup2)): if elt1 != elt2: - if type(elt1) is tuple and type(elt2) is tuple: + if isinstance(elt1, tuple) and isinstance(elt2, tuple): assert_tuples_equal(elt1, elt2, curpos + (index,)) raise AssertionError('Found difference at %s : %s != %s\n' % (curpos, name(elt1), name(elt2) ), curpos) def test_samples(): samples_dir = osp.join(osp.dirname(__file__), 'samples') - for fname in os.listdir(samples_dir): - if not fname.endswith('.py'): - continue - abspath = osp.join(samples_dir, fname) - yield check_parse, abspath - + for use_lookahead in (True, False): + grammar.USE_LOOKAHEAD = use_lookahead + for fname in os.listdir(samples_dir): + if not fname.endswith('.py'): + # if fname != 'snippet_simple_assignment.py': + continue + abspath = osp.join(samples_dir, fname) + yield check_parse, abspath + def check_parse(filepath): - pypy_tuples = pypy_parse(filepath) + # pypy_tuples = pypy_parse(filepath) + encoding_decl, stack_element, encoding = pypy_parse(filepath) + nested_tuples = stack_element.as_tuple() + if encoding is None: + pypy_tuples = nested_tuples + else: + pypy_tuples = (encoding_decl, nested_tuples, encoding) python_tuples = python_parse(filepath) try: assert_tuples_equal(pypy_tuples, python_tuples) Modified: pypy/dist/pypy/module/recparser/test/unittest_samples.py ============================================================================== --- pypy/dist/pypy/module/recparser/test/unittest_samples.py (original) +++ pypy/dist/pypy/module/recparser/test/unittest_samples.py Sat Jul 2 11:31:02 2005 @@ -2,7 +2,7 @@ import os, os.path as osp import sys -from pypy.module.recparser.pythonutil import python_parse, pypy_parse, set_debug +from pypy.module.recparser.pythonutil import python_parse, pypy_parse from pprint import pprint from pypy.module.recparser import grammar grammar.DEBUG = False @@ -85,7 +85,8 @@ opts, args = getopt.getopt( sys.argv[1:], "d:", [] ) for opt, val in opts: if opt == "-d": - set_debug(int(val)) + pass +# set_debug(int(val)) if args: samples = args else: Modified: pypy/dist/pypy/module/recparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/module/recparser/tuplebuilder.py (original) +++ pypy/dist/pypy/module/recparser/tuplebuilder.py Sat Jul 2 11:31:02 2005 @@ -1,53 +1,110 @@ from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP, SYMBOLS, NT_OFFSET +from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET +## +## def _expand_nodes(nodes): +## expanded = [] +## for n in nodes: +## if n[0] == -2: +## # expanded.extend(expand_nodes(n[1:])) +## expanded.extend(n[1:]) +## else: +## expanded.append(n) +## return tuple(expanded) +## +## def expand_nodes(nodes): +## r = _expand_nodes(nodes) +## for n in nodes: +## assert type(n[0]) == int +## return r +## + +class StackElement: + """wraps TupleBuilder's tuples""" + +class Terminal(StackElement): + def __init__(self, num, value, lineno=-1): + self.nodes = [(num, value, lineno)] + self.num = num + + def as_tuple(self, lineno=None): + if lineno is not None: + return self.nodes[0] + else: + return self.nodes[0][:-1] -def _expand_nodes( nodes ): +class NonTerminal(StackElement): + def __init__(self, num, nodes, rulename=None): + """rulename should always be None with regular Python grammar""" + self.nodes = nodes + self.num = num + + def as_tuple(self, lineno=None): + l = [self.num] + [node.as_tuple(lineno) for node in self.nodes] + return tuple(l) + + +def expand_nodes(stack_elements): + """generate a nested tuples from a list of stack elements""" expanded = [] - for n in nodes: - if n[0]==-2: - expanded.extend( expand_nodes(n[1:]) ) + for element in stack_elements: + if isinstance(element, NonTerminal) and element.num == -2: + expanded.extend(element.nodes) else: - expanded.append(n) - return tuple(expanded) + expanded.append(element) + return expanded -def expand_nodes( nodes ): - r = _expand_nodes( nodes ) - for n in nodes: - assert type(n[0])==int - return r - class TupleBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" - def __init__( self, rules=None, debug=0, lineno=False ): - BaseGrammarBuilder.__init__(self, rules, debug ) - self.lineno = True - - def alternative( self, rule, source ): + def __init__(self, rules=None, debug=0, lineno=True): + BaseGrammarBuilder.__init__(self, rules, debug) + # This attribute is here for convenience + self.source_encoding = None + self.lineno = lineno + self._unknown = -10 + + def _add_rule(self, rulename): + SYMBOLS[rulename] = self._unknown + self._unknown -= 1 + + def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] - node += expand_nodes( [self.stack[-1]] ) - self.stack[-1] = tuple(node) + nodes = expand_nodes( [self.stack[-1]] ) + if rule.name in SYMBOLS: + self.stack[-1] = NonTerminal(SYMBOLS[rule.name], nodes) + else: + # Using regular CPython's Grammar should not lead here + # XXX find how self._unknown is meant to be used + self.stack[-1] = NonTerminal(self._unknown, nodes, rule.name) + self._add_rule(rule.name) return True - + def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] + if rule.name in SYMBOLS: + num = SYMBOLS[rule.name] + node = [num] + else: + num = self._unknown + node = [num] + self._add_rule(rule.name) else: - node = [ -2 ] - if elts_number>0: - node += expand_nodes( self.stack[-elts_number:] ) - self.stack[-elts_number:] = [tuple(node)] + num = -2 + node = [num] + if elts_number > 0: + sequence_elements = self.stack[-elts_number:] + nodes = expand_nodes( sequence_elements ) + self.stack[-elts_number:] = [NonTerminal(num, nodes)] else: - self.stack.append( tuple(node) ) + self.stack.append( NonTerminal(num, []) ) return True def token(self, name, value, source): - num = TOKEN_MAP.get( name, -1) + num = TOKEN_MAP.get(name, -1) lineno = source.current_line() if value is None: if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): @@ -55,7 +112,7 @@ else: value = '' if self.lineno: - self.stack.append( (num, value, lineno) ) + self.stack.append( Terminal(num, value, lineno) ) else: - self.stack.append( (num, value) ) + self.stack.append( Terminal(num, value, -1) ) return True From adim at codespeak.net Sat Jul 2 11:33:55 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sat, 2 Jul 2005 11:33:55 +0200 (CEST) Subject: [pypy-svn] r14074 - pypy/dist/pypy/bin Message-ID: <20050702093355.A34F627B5E@code1.codespeak.net> Author: adim Date: Sat Jul 2 11:33:54 2005 New Revision: 14074 Modified: pypy/dist/pypy/bin/translator.py Log: catch ImportError if readline or rlcompleter is not installed Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Sat Jul 2 11:33:54 2005 @@ -226,8 +226,11 @@ import atexit atexit.register(readline.write_history_file, histfile) - if __name__ == '__main__': + try: + setup_readline() + except ImportError, err: + print "Disabling readline support (%s)" % err from pypy.translator.test import snippet as test from pypy.translator.llvm.test import llvmsnippet as test2 from pypy.rpython.rtyper import RPythonTyper From adim at codespeak.net Sat Jul 2 12:30:40 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sat, 2 Jul 2005 12:30:40 +0200 (CEST) Subject: [pypy-svn] r14076 - pypy/dist/pypy/module/recparser Message-ID: <20050702103040.1D96227B61@code1.codespeak.net> Author: adim Date: Sat Jul 2 12:30:38 2005 New Revision: 14076 Added: pypy/dist/pypy/module/recparser/automata.py - copied unchanged from r14075, pypy/branch/pycompiler/module/recparser/automata.py pypy/dist/pypy/module/recparser/pytokenize.py - copied unchanged from r14075, pypy/branch/pycompiler/module/recparser/pytokenize.py pypy/dist/pypy/module/recparser/test_lookahead.py - copied unchanged from r14075, pypy/branch/pycompiler/module/recparser/test/test_lookahead.py Log: added missing modules from pycompiler branch From gintas at codespeak.net Sat Jul 2 12:37:16 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 12:37:16 +0200 (CEST) Subject: [pypy-svn] r14077 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050702103716.DEE4927B62@code1.codespeak.net> Author: gintas Date: Sat Jul 2 12:37:15 2005 New Revision: 14077 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_itertools.py - copied, changed from r14074, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_itertools.py Log: Disabled weakref checks in test_itertools, reduced some ranges to make the test faster. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_itertools.py (from r14074, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_itertools.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_itertools.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_itertools.py Sat Jul 2 12:37:15 2005 @@ -1,7 +1,6 @@ import unittest from test import test_support from itertools import * -from weakref import proxy import sys import operator import random @@ -190,8 +189,11 @@ zip('abc', 'def')) self.assertEqual([pair for pair in izip('abc', 'def')], zip('abc', 'def')) - ids = map(id, izip('abc', 'def')) - self.assertEqual(min(ids), max(ids)) + # the following test deals with a specific implementation detail, + # that izip "reuses" the SAME tuple object each time when it can; + # it does not apply correctly to pypy, so I'm commenting it -- AM + # ids = map(id, izip('abc', 'def')) + # self.assertEqual(min(ids), max(ids)) ids = map(id, list(izip('abc', 'def'))) self.assertEqual(len(dict.fromkeys(ids)), len(ids)) @@ -275,7 +277,9 @@ self.assertRaises(ValueError, islice, xrange(10), 1, 'a') self.assertRaises(ValueError, islice, xrange(10), 'a', 1, 1) self.assertRaises(ValueError, islice, xrange(10), 1, 'a', 1) - self.assertEqual(len(list(islice(count(), 1, 10, sys.maxint))), 1) + # too slow to test on pypy, weakened...: + # self.assertEqual(len(list(islice(count(), 1, 10, sys.maxint))), 1) + self.assertEqual(len(list(islice(count(), 1, 10, 99))), 1) def test_takewhile(self): data = [1, 3, 5, 20, 2, 4, 6, 8] @@ -303,7 +307,7 @@ self.assertRaises(ValueError, dropwhile(errfunc, [(4,5)]).next) def test_tee(self): - n = 200 + n = 20 def irange(n): for i in xrange(n): yield i @@ -320,16 +324,16 @@ self.assertEqual(list(b), range(n)) a, b = tee(irange(n)) # test dealloc of leading iterator - for i in xrange(100): + for i in xrange(n // 2): self.assertEqual(a.next(), i) del a self.assertEqual(list(b), range(n)) a, b = tee(irange(n)) # test dealloc of trailing iterator - for i in xrange(100): + for i in xrange(n // 2): self.assertEqual(a.next(), i) del b - self.assertEqual(list(a), range(100, n)) + self.assertEqual(list(a), range(n // 2, n)) for j in xrange(5): # test randomly interleaved order = [0]*n + [1]*n @@ -354,13 +358,13 @@ self.assertEqual(list(c), list('def')) # test long-lagged and multi-way split - a, b, c = tee(xrange(2000), 3) - for i in xrange(100): + a, b, c = tee(xrange(n), 3) + for i in xrange(n // 2): self.assertEqual(a.next(), i) - self.assertEqual(list(b), range(2000)) + self.assertEqual(list(b), range(n)) self.assertEqual([c.next(), c.next()], range(2)) - self.assertEqual(list(a), range(100,2000)) - self.assertEqual(list(c), range(2,2000)) + self.assertEqual(list(a), range(n // 2, n)) + self.assertEqual(list(c), range(2, n)) # test values of n self.assertRaises(TypeError, tee, 'abc', 'invalid') @@ -383,12 +387,16 @@ t3 = tnew(t1) self.assert_(list(t1) == list(t2) == list(t3) == list('abc')) - # test that tee objects are weak referencable - a, b = tee(xrange(10)) - p = proxy(a) - self.assertEqual(getattr(p, '__class__'), type(b)) - del a - self.assertRaises(ReferenceError, getattr, p, '__class__') +# Commented out until weakref support is implemented. +# +# def test_tee_weakref(self): +# # test that tee objects are weak referencable +# from weakref import proxy +# a, b = tee(xrange(10)) +# p = proxy(a) +# self.assertEqual(getattr(p, '__class__'), type(b)) +# del a +# self.assertRaises(ReferenceError, getattr, p, '__class__') def test_StopIteration(self): self.assertRaises(StopIteration, izip().next) @@ -548,7 +556,7 @@ class TestVariousIteratorArgs(unittest.TestCase): def test_chain(self): - for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("123", "", range(10), ('do', 1.2), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(list(chain(g(s))), list(g(s))) self.assertEqual(list(chain(g(s), g(s))), list(g(s))+list(g(s))) @@ -557,7 +565,7 @@ self.assertRaises(ZeroDivisionError, list, chain(E(s))) def test_cycle(self): - for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("123", "", range(10), ('do', 1.2), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): tgtlen = len(s) * 3 expected = list(g(s))*3 @@ -568,7 +576,7 @@ self.assertRaises(ZeroDivisionError, list, cycle(E(s))) def test_groupby(self): - for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for s in (range(10), range(0), range(10), (7,11), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual([k for k, sb in groupby(g(s))], list(g(s))) self.assertRaises(TypeError, groupby, X(s)) @@ -576,7 +584,7 @@ self.assertRaises(ZeroDivisionError, list, groupby(E(s))) def test_ifilter(self): - for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for s in (range(10), range(0), range(10), (7,11), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(list(ifilter(isEven, g(s))), filter(isEven, g(s))) self.assertRaises(TypeError, ifilter, isEven, X(s)) @@ -584,7 +592,7 @@ self.assertRaises(ZeroDivisionError, list, ifilter(isEven, E(s))) def test_ifilterfalse(self): - for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for s in (range(10), range(0), range(10), (7,11), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(list(ifilterfalse(isEven, g(s))), filter(isOdd, g(s))) self.assertRaises(TypeError, ifilterfalse, isEven, X(s)) @@ -592,7 +600,7 @@ self.assertRaises(ZeroDivisionError, list, ifilterfalse(isEven, E(s))) def test_izip(self): - for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("123", "", range(10), ('do', 1.2), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(list(izip(g(s))), zip(g(s))) self.assertEqual(list(izip(g(s), g(s))), zip(g(s), g(s))) @@ -610,7 +618,7 @@ self.assertRaises(ZeroDivisionError, list, imap(onearg, E(s))) def test_islice(self): - for s in ("12345", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("12345", "", range(10), ('do', 1.2), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(list(islice(g(s),1,None,2)), list(g(s))[1::2]) self.assertRaises(TypeError, islice, X(s), 10) @@ -627,7 +635,7 @@ self.assertRaises(ZeroDivisionError, list, starmap(operator.pow, E(ss))) def test_takewhile(self): - for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for s in (range(10), range(0), range(10), (7,11), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): tgt = [] for elem in g(s): @@ -639,7 +647,7 @@ self.assertRaises(ZeroDivisionError, list, takewhile(isEven, E(s))) def test_dropwhile(self): - for s in (range(10), range(0), range(1000), (7,11), xrange(2000,2200,5)): + for s in (range(10), range(0), range(10), (7,11), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): tgt = [] for elem in g(s): @@ -651,7 +659,7 @@ self.assertRaises(ZeroDivisionError, list, dropwhile(isOdd, E(s))) def test_tee(self): - for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("123", "", range(10), ('do', 1.2), xrange(2000,2030,5)): for g in (G, I, Ig, S, L, R): it1, it2 = tee(g(s)) self.assertEqual(list(it1), list(g(s))) From ignas at codespeak.net Sat Jul 2 13:07:36 2005 From: ignas at codespeak.net (ignas at codespeak.net) Date: Sat, 2 Jul 2005 13:07:36 +0200 (CEST) Subject: [pypy-svn] r14078 - in pypy/branch/dist-2.4.1/pypy/objspace/std: . test Message-ID: <20050702110736.BEC6827B68@code1.codespeak.net> Author: ignas Date: Sat Jul 2 13:07:35 2005 New Revision: 14078 Added: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py - copied, changed from r14047, pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py Removed: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Log: Added rsplit to unicode string as in python 2.4.1 Copied: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py (from r14047, pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py) ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py Sat Jul 2 13:07:35 2005 @@ -59,11 +59,59 @@ assert u'+123'.zfill(6) == u'+00123' def test_split(self): - assert (u'this is the split function'.split() == - [u'this', u'is', u'the', u'split', u'function']) - assert (u'this!is!the!split!function'.split('!') == - [u'this', u'is', u'the', u'split', u'function']) - + assert u"".split() == [] + assert u" ".split() == [] + assert u"a".split() == [u'a'] + assert u"a".split(u"a", 1) == [u'', u''] + assert u" ".split(u" ", 1) == [u'', u''] + assert u"aa".split(u"a", 2) == [u'', u'', u''] + assert u" a ".split() == [u'a'] + assert u"a b c".split() == [u'a',u'b',u'c'] + assert u'this is the split function'.split() == [u'this', u'is', u'the', u'split', u'function'] + assert u'a|b|c|d'.split(u'|') == [u'a', u'b', u'c', u'd'] + assert 'a|b|c|d'.split(u'|') == [u'a', u'b', u'c', u'd'] + assert u'a|b|c|d'.split('|') == [u'a', u'b', u'c', u'd'] + assert u'a|b|c|d'.split(u'|', 2) == [u'a', u'b', u'c|d'] + assert u'a b c d'.split(None, 1) == [u'a', u'b c d'] + assert u'a b c d'.split(None, 2) == [u'a', u'b', u'c d'] + assert u'a b c d'.split(None, 3) == [u'a', u'b', u'c', u'd'] + assert u'a b c d'.split(None, 4) == [u'a', u'b', u'c', u'd'] + assert u'a b c d'.split(None, 0) == [u'a b c d'] + assert u'a b c d'.split(None, 2) == [u'a', u'b', u'c d'] + assert u'a b c d '.split() == [u'a', u'b', u'c', u'd'] + assert u'a//b//c//d'.split(u'//') == [u'a', u'b', u'c', u'd'] + assert u'endcase test'.split(u'test') == [u'endcase ', u''] + raises(ValueError, u'abc'.split, '') + raises(ValueError, u'abc'.split, u'') + raises(ValueError, 'abc'.split, u'') + + def test_rsplit(self): + assert u"".rsplit() == [] + assert u" ".rsplit() == [] + assert u"a".rsplit() == [u'a'] + assert u"a".rsplit(u"a", 1) == [u'', u''] + assert u" ".rsplit(u" ", 1) == [u'', u''] + assert u"aa".rsplit(u"a", 2) == [u'', u'', u''] + assert u" a ".rsplit() == [u'a'] + assert u"a b c".rsplit() == [u'a',u'b',u'c'] + assert u'this is the rsplit function'.rsplit() == [u'this', u'is', u'the', u'rsplit', u'function'] + assert u'a|b|c|d'.rsplit(u'|') == [u'a', u'b', u'c', u'd'] + assert u'a|b|c|d'.rsplit('|') == [u'a', u'b', u'c', u'd'] + assert 'a|b|c|d'.rsplit(u'|') == [u'a', u'b', u'c', u'd'] + assert u'a|b|c|d'.rsplit(u'|', 2) == [u'a|b', u'c', u'd'] + assert u'a b c d'.rsplit(None, 1) == [u'a b c', u'd'] + assert u'a b c d'.rsplit(None, 2) == [u'a b', u'c', u'd'] + assert u'a b c d'.rsplit(None, 3) == [u'a', u'b', u'c', u'd'] + assert u'a b c d'.rsplit(None, 4) == [u'a', u'b', u'c', u'd'] + assert u'a b c d'.rsplit(None, 0) == [u'a b c d'] + assert u'a b c d'.rsplit(None, 2) == [u'a b', u'c', u'd'] + assert u'a b c d '.rsplit() == [u'a', u'b', u'c', u'd'] + assert u'a//b//c//d'.rsplit(u'//') == [u'a', u'b', u'c', u'd'] + assert u'endcase test'.rsplit(u'test') == [u'endcase ', u''] + raises(ValueError, u'abc'.rsplit, u'') + raises(ValueError, u'abc'.rsplit, '') + raises(ValueError, 'abc'.rsplit, u'') + def test_long_from_unicode(self): assert long(u'12345678901234567890') == 12345678901234567890 assert int(u'12345678901234567890') == 12345678901234567890 Deleted: /pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodestring.py Sat Jul 2 13:07:35 2005 +++ (empty file) @@ -1,75 +0,0 @@ -# test the integration of unicode and strings (even though we don't -# really implement unicode yet). - -import autopath, sys - - -objspacename = 'std' - -class AppTestUnicodeStringStdOnly: - def test_compares(self): - assert u'a' == 'a' - assert 'a' == u'a' - assert not u'a' == 'b' # xxx u'a' != 'b' fails - assert not 'a' == u'b'# xxx 'a' != u'b' fails - -class AppTestUnicodeString: - def test_addition(self): - def check(a, b): - assert a == b - assert type(a) == type(b) - check(u'a' + 'b', u'ab') - check('a' + u'b', u'ab') - - def test_join(self): - def check(a, b): - assert a == b - assert type(a) == type(b) - check(', '.join([u'a']), u'a') - check(', '.join(['a', u'b']), u'a, b') - check(u', '.join(['a', 'b']), u'a, b') - - if sys.version_info >= (2,3): - def test_contains_ex(self): - assert u'' in 'abc' - assert u'bc' in 'abc' - assert 'bc' in 'abc' - - def test_contains(self): - assert u'a' in 'abc' - assert 'a' in u'abc' - - def test_splitlines(self): - assert u''.splitlines() == [] - assert u''.splitlines(1) == [] - assert u'\n'.splitlines() == [u''] - assert u'a'.splitlines() == [u'a'] - assert u'one\ntwo'.splitlines() == [u'one', u'two'] - assert u'\ntwo\nthree'.splitlines() == [u'', u'two', u'three'] - assert u'\n\n'.splitlines() == [u'', u''] - assert u'a\nb\nc'.splitlines(1) == [u'a\n', u'b\n', u'c'] - 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(6) == u'000123' - assert u'+123'.zfill(2) == u'+123' - assert u'+123'.zfill(4) == u'+123' - assert u'+123'.zfill(6) == u'+00123' - - def test_split(self): - assert (u'this is the split function'.split() == - [u'this', u'is', u'the', u'split', u'function']) - assert (u'this!is!the!split!function'.split('!') == - [u'this', u'is', u'the', u'split', u'function']) - - def test_long_from_unicode(self): - assert long(u'12345678901234567890') == 12345678901234567890 - assert int(u'12345678901234567890') == 12345678901234567890 - - def test_int_from_unicode(self): - assert int(u'12345') == 12345 - - def test_float_from_unicode(self): - assert float(u'123.456e89') == float('123.456e89') Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py Sat Jul 2 13:07:35 2005 @@ -647,25 +647,30 @@ return space.newlist([]) start = 0 end = len(self) + inword = 0 + while maxsplit != 0 and start < end: index = start for index in range(start, end): if _isspace(self[index]): break + else: + inword = 1 else: break - parts.append(W_UnicodeObject(space, self[start:index])) - maxsplit -= 1 + if inword == 1: + parts.append(W_UnicodeObject(space, self[start:index])) + maxsplit -= 1 # Eat whitespace for start in range(index + 1, end): if not _isspace(self[start]): break else: return space.newlist(parts) + parts.append(W_UnicodeObject(space, self[start:])) return space.newlist(parts) - def unicode_split__Unicode_Unicode_ANY(space, w_self, w_delim, w_maxsplit): self = w_self._value delim = w_delim._value @@ -689,6 +694,64 @@ parts.append(W_UnicodeObject(space, self[start:])) return space.newlist(parts) + +def unicode_rsplit__Unicode_None_ANY(space, w_self, w_none, w_maxsplit): + self = w_self._value + maxsplit = space.int_w(w_maxsplit) + parts = [] + if len(self) == 0: + return space.newlist([]) + start = 0 + end = len(self) + inword = 0 + + while maxsplit != 0 and start < end: + index = end + for index in range(end-1, start-1, -1): + if _isspace(self[index]): + break + else: + inword = 1 + else: + break + if inword == 1: + parts.append(W_UnicodeObject(space, self[index+1:end])) + maxsplit -= 1 + # Eat whitespace + for end in range(index, start-1, -1): + if not _isspace(self[end-1]): + break + else: + return space.newlist(parts) + + parts.append(W_UnicodeObject(space, self[:end])) + parts.reverse() + return space.newlist(parts) + +def unicode_rsplit__Unicode_Unicode_ANY(space, w_self, w_delim, w_maxsplit): + self = w_self._value + delim = w_delim._value + maxsplit = space.int_w(w_maxsplit) + delim_len = len(delim) + if delim_len == 0: + raise OperationError(space.w_ValueError, + space.wrap('empty separator')) + parts = [] + if len(self) == 0: + return space.newlist([]) + start = 0 + end = len(self) + while maxsplit != 0: + index = _rfind(self, delim, 0, end) + if index < 0: + break + parts.append(W_UnicodeObject(space, self[index+delim_len:end])) + end = index + maxsplit -= 1 + parts.append(W_UnicodeObject(space, self[:end])) + parts.reverse() + return space.newlist(parts) + def _split(space, self, maxsplit): if len(self) == 0: return [] @@ -706,7 +769,7 @@ maxsplit -= 1 parts.append(W_UnicodeObject(space, self[index:])) return parts - + def unicode_replace__Unicode_Unicode_Unicode_ANY(space, w_self, w_old, w_new, w_maxsplit): if len(w_old._value): @@ -834,5 +897,9 @@ def str_split__String_Unicode_ANY(space, w_self, w_delim, w_maxsplit): return space.call_method(space.call_function(space.w_unicode, w_self), 'split', w_delim, w_maxsplit) - + + def str_rsplit__String_Unicode_ANY(space, w_self, w_delim, w_maxsplit): + return space.call_method(space.call_function(space.w_unicode, w_self), + 'rsplit', w_delim, w_maxsplit) + register_all(vars(), stringtype) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Sat Jul 2 13:07:35 2005 @@ -30,6 +30,7 @@ unicode_rindex = MultiMethod('rindex', 4, defaults=(0, maxint)) unicode_rjust = MultiMethod('rjust', 2) unicode_rstrip = MultiMethod('rstrip', 2, defaults=(None,)) +unicode_rsplit = MultiMethod('rsplit', 3, defaults=(None,-1)) unicode_split = MultiMethod('split', 3, defaults=(None,-1)) unicode_splitlines = MultiMethod('splitlines', 2, defaults=(0,)) unicode_startswith = MultiMethod('startswith', 4, defaults=(0,maxint)) From ac at codespeak.net Sat Jul 2 13:12:05 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 2 Jul 2005 13:12:05 +0200 (CEST) Subject: [pypy-svn] r14079 - in pypy/branch/dist-2.4.1/pypy: module/__builtin__/test objspace objspace/std Message-ID: <20050702111205.9E19527B6A@code1.codespeak.net> Author: ac Date: Sat Jul 2 13:12:05 2005 New Revision: 14079 Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_builtin.py pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py pypy/branch/dist-2.4.1/pypy/objspace/std/objspace.py Log: Remove icky-ness from the implementation of cmp. Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_builtin.py Sat Jul 2 13:12:05 2005 @@ -261,10 +261,10 @@ b = []; b.append(b) from UserList import UserList c = UserList(); c.append(c) - assert cmp(a, b) == 0 - assert cmp(b, c) == 0 - assert cmp(c, a) == 0 - assert cmp(a, c) == 0 + raises(RuntimeError, cmp, a, b) + raises(RuntimeError, cmp, b, c) + raises(RuntimeError, cmp, c, a) + raises(RuntimeError, cmp, a, c) # okay, now break the cycles a.pop(); b.pop(); c.pop() Modified: pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py Sat Jul 2 13:12:05 2005 @@ -64,10 +64,6 @@ class DescrOperation: _mixin_ = True - def setup_ec(space, ec): - ec._compare_nesting = 0 - ec._cmp_state = {} - def is_data_descr(space, w_obj): return space.lookup(w_obj, '__set__') is not None @@ -289,64 +285,23 @@ _NESTING_LIMIT = 20 def cmp(space, w_v, w_w): - # Icky implementation trying to mimic python 2.3 semantics. if space.is_w(w_v, w_w): return space.wrap(0) - w_vt = space.type(w_v) - token = None - _inprogress_dict = None - - ec = space.getexecutioncontext() - ec._compare_nesting += 1 - _compare_nesting = ec._compare_nesting - - try: - # Try to do some magic to compare cyclic constructs. - if (_compare_nesting > space._NESTING_LIMIT and - # dont't be subtle the corresponding condition in CPython is always true for heaptypes - # (space.lookup(w_v, '__getitem__') is not None) and - not (space.is_w(w_vt, space.w_str) or - space.is_w(w_vt, space.w_tuple))): - try: - iv = space.int_w(space.id(w_v)) - iw = space.int_w(space.id(w_w)) - if iv <= iw: - t = (iv, iw, -1) - else: - t = (iw, iv, -1) - _inprogress_dict = ec._cmp_state - if t in _inprogress_dict: - # If we are allready trying to compare the arguments - # presume they are equal - return space.wrap(0) - else: - token = _inprogress_dict[t] = t - except: - return space.wrap(-1) - try: - # The real comparison - if space.is_w(space.type(w_v), space.type(w_w)): - # for object of the same type, prefer __cmp__ over rich comparison. - w_cmp = space.lookup(w_v, '__cmp__') - w_res = _invoke_binop(space, w_cmp, w_v, w_w) - if w_res is not None: - return w_res - # fall back to rich comparison. - if space.eq_w(w_v, w_w): - return space.wrap(0) - elif space.is_true(space.lt(w_v, w_w)): - return space.wrap(-1) - return space.wrap(1) - finally: - if token is not None: - try: - del _inprogress_dict[token] - except: - pass - finally: - ec._compare_nesting -= 1 + # The real comparison + if space.is_w(space.type(w_v), space.type(w_w)): + # for object of the same type, prefer __cmp__ over rich comparison. + w_cmp = space.lookup(w_v, '__cmp__') + w_res = _invoke_binop(space, w_cmp, w_v, w_w) + if w_res is not None: + return w_res + # fall back to rich comparison. + if space.eq_w(w_v, w_w): + return space.wrap(0) + elif space.is_true(space.lt(w_v, w_w)): + return space.wrap(-1) + return space.wrap(1) def coerce(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) @@ -478,65 +433,25 @@ w_first = w_obj1 w_second = w_obj2 - token = None - _inprogress_dict = None - - ec = space.getexecutioncontext() - ec._compare_nesting += 1 - _compare_nesting = ec._compare_nesting - try: - # Try to do some magic to compare cyclic constructs. - if (_compare_nesting > space._NESTING_LIMIT and - # dont't be subtle the corresponding condition in CPython is always true for heaptypes - # (space.lookup(w_obj1, '__getitem__') is not None) and - not (space.is_w(w_typ1, space.w_str) or - space.is_w(w_typ1, space.w_tuple))): - i1 = space.int_w(space.id(w_obj1)) - i2 = space.int_w(space.id(w_obj2)) - if i1 <= i2: - t = (i1, i2, left) - else: - t = (i2, i1, right) - _inprogress_dict = ec._cmp_state - if t in _inprogress_dict: - # If we are allready trying to compare the arguments - # presume they are equal - if symbol == '==': - return space.w_True - elif symbol == '!=': - return space.w_False - else: - raise OperationError(space.w_ValueError, - space.wrap("can't order recursive values")) - else: - token = _inprogress_dict[t] = t + if space.is_true(space.is_(w_typ1, w_typ2)): + w_right_impl = None + else: + w_right_src, w_right_impl = space.lookup_where(w_obj2, right) + if space.is_true(space.issubtype(w_typ2, w_typ1)) and not space.is_w(w_right_src, w_left_src): + w_obj1, w_obj2 = w_obj2, w_obj1 + w_left_impl, w_right_impl = w_right_impl, w_left_impl - if space.is_true(space.is_(w_typ1, w_typ2)): - w_right_impl = None - else: - w_right_src, w_right_impl = space.lookup_where(w_obj2, right) - if space.is_true(space.issubtype(w_typ2, w_typ1)) and not space.is_w(w_right_src, w_left_src): - w_obj1, w_obj2 = w_obj2, w_obj1 - w_left_impl, w_right_impl = w_right_impl, w_left_impl + w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) + if w_res is not None: + return w_res + w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) + if w_res is not None: + return w_res + # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... + w_res = _cmp(space, w_first, w_second) + res = space.int_w(w_res) + return space.wrap(op(res, 0)) - w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) - if w_res is not None: - return w_res - w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) - if w_res is not None: - return w_res - # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... - w_res = _cmp(space, w_first, w_second) - res = space.int_w(w_res) - return space.wrap(op(res, 0)) - finally: - ec._compare_nesting -= 1 - if token is not None: - try: - del _inprogress_dict[token] - except: - pass - return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_')) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/objspace.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/objspace.py Sat Jul 2 13:12:05 2005 @@ -174,7 +174,6 @@ def createexecutioncontext(self): # add space specific fields to execution context ec = ObjSpace.createexecutioncontext(self) - DescrOperation.setup_ec(self, ec) ec._py_repr = self.newdict([]) return ec From pedronis at codespeak.net Sat Jul 2 13:20:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 2 Jul 2005 13:20:54 +0200 (CEST) Subject: [pypy-svn] r14080 - in pypy/dist/pypy: interpreter/test lib tool Message-ID: <20050702112054.AC33027B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 2 13:20:53 2005 New Revision: 14080 Added: pypy/dist/pypy/interpreter/test/test_synerr.py (contents, props changed) Modified: pypy/dist/pypy/lib/_exceptions.py pypy/dist/pypy/tool/_enum_exceptions.py Log: fix raising of SyntaxError. tool/_enum_exceptions does not produce a correct output anymore. Added: pypy/dist/pypy/interpreter/test/test_synerr.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/test/test_synerr.py Sat Jul 2 13:20:53 2005 @@ -0,0 +1,8 @@ + + +class AppTestSyntaxErr: + + def test_synerr(self): + def x(): + exec "1 2" + raises(SyntaxError, x) Modified: pypy/dist/pypy/lib/_exceptions.py ============================================================================== --- pypy/dist/pypy/lib/_exceptions.py (original) +++ pypy/dist/pypy/lib/_exceptions.py Sat Jul 2 13:20:53 2005 @@ -221,50 +221,6 @@ class DeprecationWarning(Warning): """Base class for warnings about deprecated features.""" -class UnicodeEncodeError(UnicodeError): - """Unicode encoding error.""" - - # auto-generated code, please check carefully! - def __init__(self, *args): - argc = len(args) - self.args = args # modified: always assign args, no error check - if argc == 5: - if type(args[0]) == str: - self.encoding = args[0] - else: - raise TypeError('argument 0 must be str, not %s'%type(args[0])) - if type(args[1]) == unicode: - self.object = args[1] - else: - raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) - if type(args[2]) == int: - self.start = args[2] - else: - raise TypeError('argument 2 must be int, not %s'%type(args[2])) - if type(args[3]) == int: - self.end = args[3] - else: - raise TypeError('argument 3 must be int, not %s'%type(args[3])) - if type(args[4]) == str: - self.reason = args[4] - else: - raise TypeError('argument 4 must be str, not %s'%type(args[4])) - else: - raise TypeError('function takes exactly 5 arguments (%d given)'%argc) - - # auto-generated code, please check carefully! - def __str__(self): - # this is a bad hack, please supply an implementation - res = ' '.join([ - 'object=' + str(getattr(self, 'object', None)), - 'end=' + str(getattr(self, 'end', None)), - 'encoding=' + str(getattr(self, 'encoding', None)), - 'args=' + str(getattr(self, 'args', None)), - 'start=' + str(getattr(self, 'start', None)), - 'reason=' + str(getattr(self, 'reason', None)), - ]) - return res - class ArithmeticError(StandardError): """Base class for arithmetic errors.""" @@ -278,7 +234,7 @@ """Name not found globally.""" class OverflowWarning(Warning): - """Base class for warnings about numeric overflow.""" + """Base class for warnings about numeric overflow. Won't exist in Python 2.5.""" class IOError(EnvironmentError): """I/O operation failed.""" @@ -299,19 +255,19 @@ if argc >= 1: self.msg = args[0] if argc == 2: - if type(args[1][0]) == str: + if args[1][0] is None or type(args[1][0]) == str: self.filename = args[1][0] else: raise TypeError('argument 1 must be str, not %s'%type(args[1][0])) - if type(args[1][1]) == str: + if type(args[1][1]) == int: self.lineno = args[1][1] else: raise TypeError('argument 2 must be str, not %s'%type(args[1][1])) - if type(args[1][2]) == str: + if type(args[1][2]) == int: self.offset = args[1][2] else: raise TypeError('argument 3 must be str, not %s'%type(args[1][2])) - if type(args[1][3]) == str: + if args[1][3] is None or type(args[1][3]) == str: self.text = args[1][3] else: raise TypeError('argument 4 must be str, not %s'%type(args[1][3])) @@ -453,5 +409,46 @@ class OverflowError(ArithmeticError): """Result too large to be represented.""" -class WindowsError(OSError): - """MS-Windows OS system call failed.""" +class UnicodeEncodeError(UnicodeError): + """Unicode encoding error.""" + + # auto-generated code, please check carefully! + def __init__(self, *args): + argc = len(args) + self.args = args # modified: always assign args, no error check + if argc == 5: + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == unicode: + self.object = args[1] + else: + raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) + + # auto-generated code, please check carefully! + def __str__(self): + # this is a bad hack, please supply an implementation + res = ' '.join([ + 'object=' + str(getattr(self, 'object', None)), + 'end=' + str(getattr(self, 'end', None)), + 'encoding=' + str(getattr(self, 'encoding', None)), + 'args=' + str(getattr(self, 'args', None)), + 'start=' + str(getattr(self, 'start', None)), + 'reason=' + str(getattr(self, 'reason', None)), + ]) + return res Modified: pypy/dist/pypy/tool/_enum_exceptions.py ============================================================================== --- pypy/dist/pypy/tool/_enum_exceptions.py (original) +++ pypy/dist/pypy/tool/_enum_exceptions.py Sat Jul 2 13:20:53 2005 @@ -1,3 +1,6 @@ +# XXX this does not produce a correct _exceptions anymore because the logic to reconstruct +# type checks is broken + # this script is used for extracting # the information available for exceptions # via introspection. From gintas at codespeak.net Sat Jul 2 13:28:25 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 13:28:25 +0200 (CEST) Subject: [pypy-svn] r14081 - pypy/dist/pypy/lib Message-ID: <20050702112825.7A01E27B6E@code1.codespeak.net> Author: gintas Date: Sat Jul 2 13:28:25 2005 New Revision: 14081 Modified: pypy/dist/pypy/lib/_formatting.py Log: Removed an except: block in lib/_formatting.py that could hide interpreter errors. Modified: pypy/dist/pypy/lib/_formatting.py ============================================================================== --- pypy/dist/pypy/lib/_formatting.py (original) +++ pypy/dist/pypy/lib/_formatting.py Sat Jul 2 13:28:25 2005 @@ -467,12 +467,7 @@ # Switch to using the unicode formatters and retry. do_unicode = True format_registry = unicode_format_registry - try: - f = format_registry[t[0]] - except KeyError: - raise ValueError("unsupported format character " - "'%s' (0x%x) at index %d" - %(t[0], ord(t[0]), fmtiter.i-1)) + f = format_registry[t[0]] r.append(f(char, flags, width, prec, value).format()) else: From ac at codespeak.net Sat Jul 2 13:29:16 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 2 Jul 2005 13:29:16 +0200 (CEST) Subject: [pypy-svn] r14082 - in pypy/branch/dist-2.4.1/pypy: interpreter objspace/std Message-ID: <20050702112916.0FA1827B71@code1.codespeak.net> Author: ac Date: Sat Jul 2 13:29:15 2005 New Revision: 14082 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py pypy/branch/dist-2.4.1/pypy/objspace/std/dictobject.py Log: Remove some dead code. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py Sat Jul 2 13:29:15 2005 @@ -154,10 +154,6 @@ def leave_cache_building_mode(self, val): "hook for the flow object space" - def get_ec_state_dict(self): - "Return the 'state dict' from the active execution context." - return self.getexecutioncontext().get_state_dict() - def getexecutioncontext(self): "Return what we consider to be the active execution context." ec = self.threadlocals.executioncontext Modified: pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py Sat Jul 2 13:29:15 2005 @@ -10,7 +10,6 @@ def __init__(self, space): self.space = space self.framestack = Stack() - self.stateDict = {} self.w_tracefunc = None self.w_profilefunc = None self.is_tracing = 0 @@ -115,12 +114,6 @@ return frame.last_exception return None - def get_state_dict(self): - """A mechanism to store arbitrary per ExecutionContext data. - Similar to cpython's PyThreadState_GetDict. - """ - return self.stateDict - def settrace(self, w_func): """Set the global trace function.""" if self.space.is_true(self.space.is_(w_func, self.space.w_None)): Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/dictobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/dictobject.py Sat Jul 2 13:29:15 2005 @@ -293,7 +293,6 @@ def str__Dict(space, w_dict): if w_dict.used == 0: return space.wrap('{}') - statedict = space.get_ec_state_dict() w_currently_in_repr = space.getexecutioncontext()._py_repr return dictstr(space, w_currently_in_repr, w_dict) From cfbolz at codespeak.net Sat Jul 2 13:38:22 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 2 Jul 2005 13:38:22 +0200 (CEST) Subject: [pypy-svn] r14083 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702113822.61C8D27B73@code1.codespeak.net> Author: cfbolz Date: Sat Jul 2 13:38:22 2005 New Revision: 14083 Added: pypy/dist/pypy/translator/llvm2/node.py Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: (ericvrp, cfbolz): fixed FuncTypeNode to use the prepare properly, not change ref after construction etc. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 2 13:38:22 2005 @@ -10,12 +10,7 @@ def append(self, line): if show_line_numbers: - global line_number - try: - line_number += 1 - except: - line_number = 1 - line = "%-80s; %d" % (line, line_number) + line = "%-75s; %d" % (line, len(self._lines) + 1) self._lines.append(line) log(line) @@ -34,6 +29,10 @@ def arraydef(self, name, typerepr): self.append("%s = type { int, [0 x %s] }" % (name, typerepr)) + def funcdef(self, name, rettyperepr, argtypereprs): + self.append("%s = type %s (%s)" % (name, rettyperepr, + ", ".join(argtypereprs))) + def declare(self, decl): self.append("declare %s" %(decl,)) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jul 2 13:38:22 2005 @@ -1,8 +1,7 @@ from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.funcnode import FuncNode, FuncSig +from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode from pypy.translator.llvm2.structnode import StructNode, StructInstance from pypy.translator.llvm2.arraynode import ArrayNode -ArrayNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -55,7 +54,11 @@ else: log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var)) else: - log.prepare.ignore(const_or_var) + log.prepare.ignore(const_or_var) + + def prepare_repr_arg_multi(self, args): + for const_or_var in args: + self.prepare_repr_arg(const_or_var) def prepare_repr_arg_type(self, type_): if type_ in self.obj2node: @@ -69,7 +72,7 @@ self.addpending(type_, StructNode(self, type_)) elif isinstance(type_, lltype.FuncType): - self.addpending(type_, FuncSig(self, type_)) + self.addpending(type_, FuncTypeNode(self, type_)) elif isinstance(type_, lltype.Array): self.addpending(type_, ArrayNode(self, type_)) @@ -77,6 +80,10 @@ else: log.XXX("need to prepare typerepr", type_) + def prepare_repr_arg_type_multi(self, types): + for type_ in types: + self.prepare_repr_arg_type(type_) + def prepare_arg(self, const_or_var): log.prepare(const_or_var) self.prepare_repr_arg_type(const_or_var.concretetype) @@ -95,7 +102,7 @@ return res def get_typedecls(self): - return self.getobjects((StructNode, ArrayNode)) + return self.getobjects((StructNode, ArrayNode, FuncTypeNode)) def get_globaldata(self): return self.getobjects((StructInstance)) @@ -132,7 +139,7 @@ log.dump_db("*** unknown ***") for k,v in all_objs: - if isinstance(v, (FuncSig)): + if isinstance(v, (FuncTypeNode)): log.dump_db("%s ---> %s" % (k, v)) # __________________________________________________________ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 2 13:38:22 2005 @@ -3,28 +3,36 @@ from pypy.objspace.flow.model import flatten, mkentrymap, traverse from pypy.rpython import lltype from pypy.translator.llvm2.cfgtransform import prepare_graph +from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.log import log log = log.funcnode -class FuncSig(object): - """ XXX Not sure about this - should be combined with FuncNode? - Abstract function signature. """ - def __init__(self, db, typ): +class FuncTypeNode(LLVMNode): + func_type_node_counter = 0 + + def __init__(self, db, type_): self.db = db - self.typ = typ - # Hack around some debug statements - self.ref = "pending setup!" + self.type_ = type_ + ref = '"ft.%s.%s"' % (type_, FuncTypeNode.func_type_node_counter) + self.ref = ref.replace(" ", "") + FuncTypeNode.func_type_node_counter += 1 def __str__(self): - return "" % self.ref + return "" % self.ref def setup(self): - returntype = self.db.repr_arg_type(self.typ.RESULT) - inputargtypes = self.db.repr_arg_type_multi(self.typ.ARGS) - self.ref = "%s (%s)" % (returntype, ", ".join(inputargtypes)) + self.db.prepare_repr_arg_type(self.type_.RESULT) + self.db.prepare_repr_arg_type(self.type_.ARGS) + + def writedatatypedecl(self, codewriter): + returntype = self.db.repr_arg_type(self.type_.RESULT) + inputargtypes = self.db.repr_arg_type_multi(self.type_.ARGS) + decl = "%s type %s (%s)*" % (self.ref, returntype, + ", ".join(inputargtypes)) + codewriter.funcdef(self.ref, returntype, inputargtypes) -class FuncNode(object): +class FuncNode(LLVMNode): _issetup = False def __init__(self, db, const_ptr_func): Added: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/node.py Sat Jul 2 13:38:22 2005 @@ -0,0 +1,9 @@ +class LLVMNode(object): + def _get_ref(self): + return self._ref + def _set_ref(self, ref): + if hasattr(self, "_ref"): + raise TypeError, ("can only set ref once! currently: %s" % + (self._ref,)) + self._ref = ref + ref = property(_get_ref, _set_ref) From arigo at codespeak.net Sat Jul 2 13:42:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Jul 2005 13:42:58 +0200 (CEST) Subject: [pypy-svn] r14084 - in pypy/branch/dist-2.4.1/lib-python: . 2.4.1 2.4.1/bsddb 2.4.1/bsddb/test 2.4.1/compiler 2.4.1/curses 2.4.1/distutils 2.4.1/distutils/command 2.4.1/distutils/tests 2.4.1/email 2.4.1/email/test 2.4.1/email/test/data 2.4.1/encodings 2.4.1/hotshot 2.4.1/idlelib 2.4.1/lib-old 2.4.1/lib-tk 2.4.1/logging 2.4.1/plat-aix3 2.4.1/plat-aix4 2.4.1/plat-atheos 2.4.1/plat-beos5 2.4.1/plat-darwin 2.4.1/plat-freebsd2 2.4.1/plat-freebsd3 2.4.1/plat-freebsd4 2.4.1/plat-freebsd5 2.4.1/plat-freebsd6 2.4.1/plat-irix5 2.4.1/plat-irix6 2.4.1/plat-linux2 2.4.1/plat-mac 2.4.1/plat-mac/Carbon 2.4.1/plat-mac/lib-scriptpackages/CodeWarrior 2.4.1/plat-mac/lib-scriptpackages/Explorer 2.4.1/plat-mac/lib-scriptpackages/Finder 2.4.1/plat-mac/lib-scriptpackages/Netscape 2.4.1/plat-mac/lib-scriptpackages/StdSuites 2.4.1/plat-mac/lib-scriptpackages/SystemEvents 2.4.1/plat-mac/lib-scriptpackages/Terminal 2.4.1/plat-mac/lib-scriptpackages/_builtinSuites 2.4.1/plat-netbsd1 2.4.1/plat-os2emx 2.4.1/plat-riscos 2.4.1/plat-sunos5 2.4.1/plat-unixware7 2.4.1/test 2.4.1/xml 2.4.1/xml/dom 2.4.1/xml/parsers 2.4.1/xml/sax attic modified-2.4.1 modified-2.4.1/encodings modified-2.4.1/test Message-ID: <20050702114258.581BA27B76@code1.codespeak.net> Author: arigo Date: Sat Jul 2 13:42:40 2005 New Revision: 14084 Modified: pypy/branch/dist-2.4.1/lib-python/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/BaseHTTPServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/Bastion.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/CGIHTTPServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/ConfigParser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/Cookie.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/DocXMLRPCServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/HTMLParser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/MimeWriter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/Queue.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/SimpleHTTPServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/SimpleXMLRPCServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/SocketServer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/StringIO.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/UserDict.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/UserList.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/UserString.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/__future__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/__phello__.foo.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/_strptime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/aifc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/anydbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/asynchat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/asyncore.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/atexit.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/audiodev.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/base64.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bdb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/binhex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bisect.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/db.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/dbobj.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/dbrecio.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/dbshelve.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/dbtables.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/dbutils.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_all.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_associate.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_basics.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_compat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_dbobj.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_dbshelve.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_dbtables.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_env_close.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_get_none.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_join.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_lock.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_misc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_queue.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_recno.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/bsddb/test/test_thread.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/calendar.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/cgi.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/cgitb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/chunk.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/cmd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/code.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/codecs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/codeop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/colorsys.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/commands.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compileall.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/ast.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/consts.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/future.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/misc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/pyassem.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/pycodegen.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/symbols.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/syntax.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/transformer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/visitor.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/copy.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/copy_reg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/csv.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/ascii.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/has_key.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/panel.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/textpad.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/curses/wrapper.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dbhash.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/difflib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dircache.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dis.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/archive_util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/bcppcompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/ccompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/cmd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/bdist.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/bdist_dumb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/bdist_rpm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/bdist_wininst.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/build.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/build_clib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/build_ext.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/build_py.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/build_scripts.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/clean.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/config.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/install.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/install_data.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/install_headers.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/install_lib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/install_scripts.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/register.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/command/sdist.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/core.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/cygwinccompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/debug.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/dep_util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/dir_util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/dist.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/emxccompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/errors.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/extension.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/fancy_getopt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/file_util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/filelist.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/log.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/msvccompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/mwerkscompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/spawn.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/sysconfig.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/tests/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/text_file.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/unixccompiler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/distutils/version.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/doctest.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dumbdbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dummy_thread.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/dummy_threading.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Charset.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Encoders.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Errors.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Generator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Header.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Iterators.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEAudio.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEBase.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEImage.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEMessage.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEMultipart.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMENonMultipart.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/MIMEText.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Message.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Parser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/Utils.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/_parseaddr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/base64MIME.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/quopriMIME.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_01.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_02.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_03.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_04.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_05.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_06.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_07.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_08.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_09.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_10.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_11.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_12.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_13.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_14.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_15.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_16.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_17.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_18.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_19.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_20.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_21.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_22.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_23.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_24.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_25.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_27.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_28.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_29.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_30.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_31.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_32.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_33.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_34.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/data/msg_35.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/test_email.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/test_email_codecs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/email/test/test_email_torture.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/aliases.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/ascii.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/base64_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/charmap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp037.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1006.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1026.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1140.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1250.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1251.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1252.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1253.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1254.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1255.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1256.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1257.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp1258.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp424.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp437.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp500.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp737.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp775.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp850.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp852.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp855.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp856.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp857.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp860.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp861.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp862.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp863.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp864.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp865.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp866.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp869.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp874.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/cp875.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/hex_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/idna.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_1.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_10.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_13.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_14.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_15.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_3.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_4.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_5.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_6.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_7.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_8.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/iso8859_9.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/koi8_r.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/koi8_u.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/latin_1.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_cyrillic.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_greek.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_iceland.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_latin2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_roman.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mac_turkish.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/mbcs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/palmos.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/punycode.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/quopri_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/raw_unicode_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/rot_13.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/string_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/undefined.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/unicode_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/unicode_internal.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_16.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_16_be.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_16_le.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_7.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/utf_8.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/uu_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/encodings/zlib_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/filecmp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/fileinput.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/fnmatch.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/formatter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/fpformat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/ftplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/getopt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/getpass.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/gettext.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/glob.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/gopherlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/gzip.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/heapq.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hmac.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hotshot/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hotshot/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hotshot/log.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hotshot/stats.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/hotshot/stones.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/htmlentitydefs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/htmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/httplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/AutoExpand.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/Bindings.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/CREDITS.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/CallTipWindow.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/CallTips.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ClassBrowser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ColorDelegator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/Debugger.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/Delegator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/EditorWindow.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/FileList.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/FormatParagraph.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/GrepDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/HISTORY.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/IOBinding.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/IdleHistory.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/MultiStatusBar.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/NEWS.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ObjectBrowser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/OutputWindow.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ParenMatch.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/PathBrowser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/Percolator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/PyParse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/PyShell.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/README.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/RemoteDebugger.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/RemoteObjectBrowser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ReplaceDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ScriptBinding.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ScrolledList.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/SearchDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/SearchDialogBase.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/SearchEngine.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/StackViewer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/TODO.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ToolTip.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/TreeWidget.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/UndoDelegator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/WidgetRedirector.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/WindowList.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/ZoomHeight.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/aboutDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/buildapp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/configDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/configHandler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/configHelpSourceEdit.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/configSectionNameDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/dynOptionMenuWidget.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/extend.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/help.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/idle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/idlever.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/keybindingDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/rpc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/run.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/tabpage.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/testcode.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/idlelib/textView.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/ihooks.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/imaplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/imghdr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/imputil.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/inspect.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/keyword.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/Para.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/addpack.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/cmp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/cmpcache.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/codehack.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/dircmp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/dump.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/find.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/fmt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/grep.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/lockfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/newdir.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/ni.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/packmail.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/poly.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/rand.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/tb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/util.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/whatsound.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-old/zmod.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Canvas.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Dialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/FileDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/FixTk.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/ScrolledText.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/SimpleDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Tix.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Tkconstants.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Tkdnd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/Tkinter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkColorChooser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkCommonDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkFileDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkFont.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkMessageBox.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/tkSimpleDialog.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/lib-tk/turtle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/linecache.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/locale.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/logging/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/logging/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/logging/config.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/logging/handlers.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/macpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/macurl2path.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mailbox.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mailcap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/markupbase.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mhlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mimetools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mimetypes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mimify.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/modulefinder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/multifile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/mutex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/netrc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/new.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/nntplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/ntpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/nturl2path.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/opcode.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/optparse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/os.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/os2emxpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pdb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pickle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pickletools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pipes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pkgutil.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-aix3/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-aix3/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-aix4/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-aix4/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-atheos/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-atheos/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-atheos/TYPES.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-beos5/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-beos5/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-darwin/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-darwin/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd2/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd2/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd3/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd3/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd4/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd4/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd5/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd5/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-freebsd6/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/AL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/CD.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/CL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/CL_old.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/DEVICE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/ERRNO.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/FILE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/FL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/GET.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/GL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/GLWS.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/IOCTL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/SV.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/WAIT.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/cddb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/cdplayer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/flp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/jpeg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/panel.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/panelparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/readcd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix5/torgb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/AL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/CD.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/CL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/DEVICE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/ERRNO.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/FILE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/FL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/GET.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/GL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/GLWS.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/IOCTL.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/SV.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/WAIT.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/cddb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/cdplayer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/flp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/jpeg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/panel.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/panelparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/readcd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-irix6/torgb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-linux2/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-linux2/CDROM.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-linux2/DLFCN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-linux2/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-linux2/TYPES.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Audio_mac.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/AE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/AH.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Alias.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Aliases.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/App.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Appearance.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/AppleEvents.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/AppleHelp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CF.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CG.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CarbonEvents.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CarbonEvt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Cm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Components.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/ControlAccessor.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Controls.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CoreFoundation.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/CoreGraphics.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Ctl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Dialogs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Dlg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Drag.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Dragconst.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Events.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Evt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/File.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Files.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Fm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Folder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Folders.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Fonts.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Help.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/IBCarbon.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/IBCarbonRuntime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Icn.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Icons.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/List.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Lists.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/MacHelp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/MacTextEditor.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/MediaDescr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Menu.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Menus.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Mlte.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/QDOffscreen.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Qd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Qdoffs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Qt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/QuickDraw.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/QuickTime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Res.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Resources.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Scrap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Snd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Sndihooks.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Sound.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/TE.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/TextEdit.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/WASTEconst.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Win.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/Carbon/Windows.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/EasyDialogs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/FrameWork.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/MiniAEFrame.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/PixMapWrapper.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/WASTEconst.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/aepack.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/aetools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/aetypes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/applesingle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/appletrawmain.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/appletrunner.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/argvemulator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/bgenlocations.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/buildtools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/bundlebuilder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/cfmfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/findertools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/gensuitemodule.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/ic.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/icopen.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/CodeWarrior_suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/Metrowerks_Shell_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/Required.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/CodeWarrior/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/Microsoft_Internet_Explorer.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/Netscape_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/Required_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/URL_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/Web_Browser_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Explorer/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Containers_and_folders.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Enumerations.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Files.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Finder_Basics.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Finder_items.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Legacy_suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Type_Definitions.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/Window_classes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Finder/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/Mozilla_suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/PowerPlant.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/Required_suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/Text.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/WorldWideWeb_suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Netscape/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/AppleScript_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Macintosh_Connectivity_Clas.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/QuickDraw_Graphics_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/QuickDraw_Graphics_Suppleme.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Required_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Table_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Text_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/Type_Names_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/StdSuites/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Disk_Folder_File_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Folder_Actions_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Hidden_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Login_Items_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Power_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Processes_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/System_Events_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/Text_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/SystemEvents/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Terminal/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Terminal/Standard_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Terminal/Terminal_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Terminal/Text_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/Terminal/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/_builtinSuites/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/_builtinSuites/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/lib-scriptpackages/_builtinSuites/builtin_Suite.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/macerrors.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/macfs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/macostools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/macresource.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/pimp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/plistlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/terminalcommand.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-mac/videoreader.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-netbsd1/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-netbsd1/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-os2emx/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-os2emx/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-os2emx/SOCKET.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-os2emx/grp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-os2emx/pwd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-riscos/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-riscos/riscosenviron.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-riscos/riscospath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-riscos/rourl2path.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/CDIO.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/DLFCN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/STROPTS.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/SUNAUDIODEV.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-sunos5/TYPES.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-unixware7/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-unixware7/IN.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/plat-unixware7/STROPTS.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/platform.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/popen2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/poplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/posixfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/posixpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pprint.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/profile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pstats.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pty.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/py_compile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pyclbr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/pydoc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/quopri.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/random.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/re.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/reconvert.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/regex_syntax.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/regsub.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/repr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/rexec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/rfc822.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/rlcompleter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/robotparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sched.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sets.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sgmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/shelve.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/shlex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/shutil.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/site.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/smtpd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/smtplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sndhdr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/socket.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sre.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_compile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_constants.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_parse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/stat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/statcache.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/statvfs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/string.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/stringold.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/stringprep.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sunau.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/sunaudio.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/symbol.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/symtable.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tabnanny.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tarfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/telnetlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tempfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/autotest.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_future3.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_future4.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_future5.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_future6.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_future7.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/badsyntax_nocaret.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/double_const.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/pickletester.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/pydocfodder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/pystone.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/re_tests.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/regex_tests.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/regrtest.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/reperf.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/sortperf.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/string_tests.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_MimeWriter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_StringIO.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test___all__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test___future__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_aepack.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_al.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_anydbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_array.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_asynchat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_atexit.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_audioop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_augassign.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_base64.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bastion.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_binascii.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_binhex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_binop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bisect.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bool.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bsddb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bsddb185.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bsddb3.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bufio.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_builtin.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bz2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_calendar.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_call.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_capi.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cfgparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cgi.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_charmapcodec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_class.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cmath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_codeccallbacks.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_codecs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_codeop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_coercion.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_commands.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_compare.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_compile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_complex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_contains.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cookie.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_copy.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_copy_reg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_cpickle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_crypt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_csv.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_curses.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_datetime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_descr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_descrtut.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_difflib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dircache.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dis.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_doctest.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_doctest2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dumbdbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dummy_thread.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_dummy_threading.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_email.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_email_codecs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_enumerate.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_eof.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_errno.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_exceptions.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_extcall.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_fcntl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_file.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_filecmp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_fileinput.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_fnmatch.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_fork1.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_format.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_fpformat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_frozen.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_funcattrs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_future.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_future1.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_future2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_future3.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_gc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_gdbm.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_generators.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_getargs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_getargs2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_getopt.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_gettext.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_gl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_glob.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_global.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_grammar.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_grp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_gzip.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_hash.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_heapq.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_hexoct.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_hmac.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_hotshot.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_htmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_htmlparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_httplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_imageop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_imaplib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_imgfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_imp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_import.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_importhooks.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_inspect.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_ioctl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_isinstance.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_iter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_itertools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_largefile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_linuxaudiodev.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_locale.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_logging.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_long.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_long_future.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_longexp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_macfs.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_macostools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_macpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mailbox.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_marshal.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_math.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_md5.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mhlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mimetools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mimetypes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_minidom.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mmap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_module.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_multifile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mutants.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_netrc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_new.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_nis.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_normalization.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_ntpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_opcodes.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_openpty.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_operations.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_operator.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_optparse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_os.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_ossaudiodev.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_parser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pep247.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pep277.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pickle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pickletools.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pkg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pkgimport.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_plistlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_poll.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_popen.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_popen2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_posix.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_posixpath.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pow.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pprint.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_profile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_profilehooks.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pty.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pwd.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pyclbr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_pyexpat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_queue.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_quopri.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_random.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_re.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_regex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_repr.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_resource.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_rfc822.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_rgbimg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_richcmp.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_robotparser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sax.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_scope.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_scriptpackages.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_select.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sets.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sgmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sha.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_shelve.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_shlex.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_shutil.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_signal.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_slice.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_socket.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_socket_ssl.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_socketserver.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_softspace.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sort.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_str.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_strftime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_string.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_stringprep.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_strop.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_strptime.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_struct.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_structseq.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sunaudiodev.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sundry.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_support.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_symtable.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_syntax.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sys.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tarfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tempfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_textwrap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_thread.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_threaded_import.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_threadedtempfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_threading.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_time.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_timeout.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_timing.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tokenize.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_trace.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_traceback.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_types.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_ucn.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_unary.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_unicode.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_unicode_file.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_unicodedata.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_univnewlines.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_unpack.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllib2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllibnet.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urlparse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_userdict.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_userlist.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_userstring.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_uu.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_warnings.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_wave.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_weakref.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_whichdb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_winreg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_winsound.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_xmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_xmlrpc.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_xpickle.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_zipfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_zipimport.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_zlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/testall.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/testcodec.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/tf_inherit_check.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/tokenize_tests.txt (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/test/xmltests.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/textwrap.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/this.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/threading.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/timeit.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/toaiff.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/token.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tokenize.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/trace.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/traceback.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tty.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/types.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/tzparse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/unittest.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/urllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/urllib2.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/urlparse.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/user.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/uu.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/warnings.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/wave.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/weakref.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/webbrowser.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/whichdb.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/whrandom.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xdrlib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/NodeFilter.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/domreg.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/expatbuilder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/minicompat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/minidom.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/pulldom.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/dom/xmlbuilder.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/parsers/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/parsers/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/parsers/expat.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/ (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/_exceptions.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/expatreader.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/handler.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/saxutils.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xml/sax/xmlreader.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xmllib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/xmlrpclib.py (props changed) pypy/branch/dist-2.4.1/lib-python/2.4.1/zipfile.py (props changed) pypy/branch/dist-2.4.1/lib-python/attic/ (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/ (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/__init__.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/aliases.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/ascii.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/base64_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/charmap.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp037.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1006.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1026.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1140.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1250.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1251.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1252.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1253.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1254.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1255.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1256.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1257.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp1258.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp424.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp437.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp500.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp737.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp775.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp850.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp852.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp855.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp856.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp857.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp860.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp861.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp862.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp863.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp864.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp865.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp866.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp869.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp874.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/cp875.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/hex_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/idna.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_1.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_10.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_13.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_14.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_15.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_2.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_3.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_4.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_5.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_6.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_7.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_8.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/iso8859_9.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/koi8_r.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/koi8_u.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/latin_1.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_cyrillic.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_greek.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_iceland.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_latin2.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_roman.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mac_turkish.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/mbcs.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/palmos.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/punycode.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/quopri_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/raw_unicode_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/rot_13.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/string_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/undefined.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_escape.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/unicode_internal.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_16.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_16_be.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_16_le.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_7.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/utf_8.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/uu_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/encodings/zlib_codec.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/ (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_class.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_itertools.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_struct.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/traceback.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/types.py (props changed) pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/warnings.py (props changed) Log: fixeol. From adim at codespeak.net Sat Jul 2 13:43:43 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sat, 2 Jul 2005 13:43:43 +0200 (CEST) Subject: [pypy-svn] r14085 - in pypy/dist/pypy/rpython: . test Message-ID: <20050702114343.219C527B7D@code1.codespeak.net> Author: adim Date: Sat Jul 2 13:43:42 2005 New Revision: 14085 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: added trivial implementation of string.upper and string.lower (+tests) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 2 13:43:42 2005 @@ -104,6 +104,18 @@ v_str, v_value = hop.inputargs(string_repr, string_repr) return hop.gendirectcall(ll_endswith, v_str, v_value) + def rtype_method_find(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_find, v_str, v_value) + + def rtype_method_upper(_, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_upper, v_str) + + def rtype_method_lower(_, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_lower, v_str) + def rtype_method_join(_, hop): r_lst = hop.args_r[1] s_item = r_lst.listitem.s_value @@ -558,6 +570,40 @@ emptystr = string_repr.convert_const("") +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: + ochar = ord(s_chars[i]) + if ochar >= 97 and ochar <= 122: + upperchar = ochar - 32 + else: + upperchar = ochar + result.chars[i] = chr(upperchar) + 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: + ochar = ord(s_chars[i]) + if ochar >= 65 and ochar <= 96: + lowerchar = ochar + 32 + else: + lowerchar = ochar + result.chars[i] = chr(lowerchar) + i += 1 + return result + def ll_join(s, items): s_chars = s.chars s_len = len(s_chars) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sat Jul 2 13:43:42 2005 @@ -180,6 +180,22 @@ res = interpret(fn, [i,j]) assert res is fn(i, j) +def test_upper(): + def fn(i): + strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,'] + return strings[i].upper() + for i in range(5): + res = interpret(fn, [i]) + assert ''.join(res.chars) == fn(i) + +def test_lower(): + def fn(i): + strings = ['', ' ', 'lower', 'LoWeR', ',lowEr,'] + return strings[i].lower() + for i in range(5): + res = interpret(fn, [i]) + assert ''.join(res.chars) == fn(i) + def test_join(): res = interpret(lambda: ''.join([]), []) assert ''.join(res.chars) == "" From adim at codespeak.net Sat Jul 2 13:53:46 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sat, 2 Jul 2005 13:53:46 +0200 (CEST) Subject: [pypy-svn] r14086 - pypy/dist/pypy/annotation Message-ID: <20050702115346.24D0727B82@code1.codespeak.net> Author: adim Date: Sat Jul 2 13:53:45 2005 New Revision: 14086 Modified: pypy/dist/pypy/annotation/unaryop.py Log: defined unary operations for string.upper and string.lower Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jul 2 13:53:45 2005 @@ -324,6 +324,12 @@ def method_replace(str, s1, s2): return SomeString() + def method_lower(str): + return SomeString() + + def method_upper(str): + return SomeString() + class __extend__(SomeChar): From cfbolz at codespeak.net Sat Jul 2 14:00:25 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 2 Jul 2005 14:00:25 +0200 (CEST) Subject: [pypy-svn] r14087 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050702120025.F146627B83@code1.codespeak.net> Author: cfbolz Date: Sat Jul 2 14:00:25 2005 New Revision: 14087 Removed: pypy/dist/pypy/translator/llvm2/cfgtransform.py Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (ericvrp, cfbolz) a small cleanup, a (failing) test for lists and removal of unneeded cfgtransform (functionality moved to translator/backendoptimization.py Deleted: /pypy/dist/pypy/translator/llvm2/cfgtransform.py ============================================================================== --- /pypy/dist/pypy/translator/llvm2/cfgtransform.py Sat Jul 2 14:00:25 2005 +++ (empty file) @@ -1,44 +0,0 @@ -from pypy.objspace.flow.model import traverse, Block, checkgraph -from pypy.translator.unsimplify import remove_double_links - - -def remove_same_as(graph): - same_as_positions = [] - def visit(node): - if isinstance(node, Block): - for i, op in enumerate(node.operations): - if op.opname == 'same_as': - same_as_positions.append((node, i)) - traverse(visit, graph) - while same_as_positions: - block, index = same_as_positions.pop() - same_as_result = block.operations[index].result - same_as_arg = block.operations[index].args[0] - # replace the new variable (same_as_result) with the old variable - # (from all subsequent positions) - for op in block.operations[index:]: - if op is not None: - for i in range(len(op.args)): - if op.args[i] == same_as_result: - op.args[i] = same_as_arg - for link in block.exits: - for i in range(len(link.args)): - if link.args[i] == same_as_result: - link.args[i] = same_as_arg - if block.exitswitch == same_as_result: - block.exitswitch = same_as_arg - block.operations[index] = None - - # remove all same_as operations - def visit(node): - if isinstance(node, Block) and node.operations: - node.operations[:] = filter(None, node.operations) - traverse(visit, graph) - checkgraph(graph) - - -def prepare_graph(graph, translator): - remove_same_as(graph) - remove_double_links(translator, graph) - return graph - Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 2 14:00:25 2005 @@ -17,6 +17,9 @@ def comment(self, line): self.append(";; " + line) + def newline(self): + self.append("") + def indent(self, line): self.append(" " + line) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 2 14:00:25 2005 @@ -21,7 +21,7 @@ entrynode = db.obj2node[c] codewriter = CodeWriter() comment = codewriter.comment - nl = lambda: codewriter.append("") + nl = codewriter.newline nl(); comment("Type Declarations"); nl() for typ_decl in db.get_typedecls(): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jul 2 14:00:25 2005 @@ -185,6 +185,16 @@ assert f(-1) == 3 assert f(0) == 5 +def test_list_getitem(): + def list_getitem(i): + l = [1,2,i] + return l[i] + f = compile_function(list_getitem, [int]) + assert f(0) == 1 + assert f(1) == 2 + assert f(3) == 3 + + def DONOT_test_simple_chars(): def char_constant2(s): s = s + s + s From ludal at codespeak.net Sat Jul 2 14:09:14 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sat, 2 Jul 2005 14:09:14 +0200 (CEST) Subject: [pypy-svn] r14088 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050702120914.15B9C27B85@code1.codespeak.net> Author: ludal Date: Sat Jul 2 14:09:13 2005 New Revision: 14088 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: implements ll rpython string find method Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jul 2 14:09:13 2005 @@ -301,6 +301,9 @@ def method_endswith(str, frag): return SomeBool() + def method_find(str, frag): + return SomeInteger() + def method_join(str, s_list): getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 2 14:09:13 2005 @@ -26,6 +26,8 @@ STR = GcStruct('str', ('hash', Signed), ('chars', Array(Char))) +SIGNED_ARRAY = GcArray(Signed) + class __extend__(annmodel.SomeString): def rtyper_makerepr(self, rtyper): @@ -568,6 +570,47 @@ return True +def ll_find(s1, s2): + """Knuth Morris Prath algorithm for substring match""" + len1 = len(s1.chars) + len2 = len(s2.chars) + # 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 ) + i = 0 + j = -1 + while i=0 and s2.chars[i] == s2.chars[j]: + j += 1 + T[i] = j + i += 1 + elif j>0: + j = T[j-1] + else: + T[i] = 0 + i += 1 + j = 0 + + # Now the find algorithm + i = 0 + m = 0 + while m+i0: + i = e + return -1 + emptystr = string_repr.convert_const("") def ll_upper(s): 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 Jul 2 14:09:13 2005 @@ -180,6 +180,16 @@ res = 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(6): + res = interpret(fn, [i,j]) + assert res == fn(i, j) + def test_upper(): def fn(i): strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,'] From gintas at codespeak.net Sat Jul 2 14:13:37 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 14:13:37 +0200 (CEST) Subject: [pypy-svn] r14089 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050702121337.7CACB27B8A@code1.codespeak.net> Author: gintas Date: Sat Jul 2 14:13:37 2005 New Revision: 14089 Modified: pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/objspace/std/test/test_stringobject.py Log: Fixed a bug in string formatting ("a" % u"b" would not raise a TypeError). Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Sat Jul 2 14:13:37 2005 @@ -1020,7 +1020,8 @@ # CPython's logic for deciding if ""%values is # an error (1 value, 0 %-formatters) or not # (values is of a mapping type) - if hasattr(values, '__getitem__') and not isinstance(values, str): + if (hasattr(values, '__getitem__') + and not isinstance(values, basestring)): return _formatting.format(format, (values,), values) else: return _formatting.format(format, (values,), None) 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 Sat Jul 2 14:13:37 2005 @@ -116,9 +116,24 @@ assert self.space.eq_w(space.getitem(w_str, w_slice), w('el')) class AppTestStringObject: + def test_format_wrongchar(self): raises(ValueError, 'a%Zb'.__mod__, ((23,),)) + def test_format(self): + raises(TypeError, "foo".__mod__, "bar") + raises(TypeError, u"foo".__mod__, "bar") + raises(TypeError, "foo".__mod__, u"bar") + + for format, arg, cls in [("a %s b", "foo", str), + (u"a %s b", "foo", unicode), + ("a %s b", u"foo", unicode), + (u"a %s b", u"foo", unicode)]: + raises(TypeError, format[:2].__mod__, arg) + result = format % arg + assert result == "a foo b" + assert isinstance(result, cls) + def test_split(self): assert "".split() == [] assert " ".split() == [] From gintas at codespeak.net Sat Jul 2 14:20:58 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 14:20:58 +0200 (CEST) Subject: [pypy-svn] r14090 - pypy/dist/pypy/lib Message-ID: <20050702122058.BF09B27B8C@code1.codespeak.net> Author: gintas Date: Sat Jul 2 14:20:58 2005 New Revision: 14090 Modified: pypy/dist/pypy/lib/_formatting.py Log: Fixed a bug. E.g., u"%\u0105" % 1 would crash the interpreter. Modified: pypy/dist/pypy/lib/_formatting.py ============================================================================== --- pypy/dist/pypy/lib/_formatting.py (original) +++ pypy/dist/pypy/lib/_formatting.py Sat Jul 2 14:20:58 2005 @@ -453,9 +453,12 @@ try: f = format_registry[t[0]] except KeyError: + char = t[0] + if isinstance(char, unicode): + char = char.encode(sys.getdefaultencoding(), 'replace') raise ValueError("unsupported format character " "'%s' (0x%x) at index %d" - %(t[0], ord(t[0]), fmtiter.i-1)) + % (char, ord(t[0]), fmtiter.i - 1)) # Trying to translate this using the flow space. # Currently, star args give a problem there, # so let's be explicit about the args: From ignas at codespeak.net Sat Jul 2 14:34:16 2005 From: ignas at codespeak.net (ignas at codespeak.net) Date: Sat, 2 Jul 2005 14:34:16 +0200 (CEST) Subject: [pypy-svn] r14091 - in pypy/branch/dist-2.4.1/pypy/objspace/std: . test Message-ID: <20050702123416.A453927B8E@code1.codespeak.net> Author: ignas Date: Sat Jul 2 14:34:15 2005 New Revision: 14091 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Log: Make center on unicode string behave in the smae manner as center on siple strings does. Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py Sat Jul 2 14:34:15 2005 @@ -112,6 +112,27 @@ raises(ValueError, u'abc'.rsplit, '') raises(ValueError, 'abc'.rsplit, u'') + def test_center(self): + s=u"a b" + assert s.center(0) == u"a b" + assert s.center(1) == u"a b" + assert s.center(2) == u"a b" + assert s.center(3) == u"a b" + assert s.center(4) == u"a b " + assert s.center(5) == u" a b " + assert s.center(6) == u" a b " + assert s.center(7) == u" a b " + assert s.center(8) == u" a b " + assert s.center(9) == u" a b " + assert u'abc'.center(10) == u' abc ' + assert u'abc'.center(6) == u' abc ' + assert u'abc'.center(3) == u'abc' + assert u'abc'.center(2) == u'abc' + assert u'abc'.center(5, u'*') == u'*abc*' # Python 2.4 + assert u'abc'.center(5, '*') == u'*abc*' # Python 2.4 + assert 'abc'.center(5, u'*') == u'*abc*' # Python 2.4 + raises(TypeError, u'abc'.center, 4, u'cba') + def test_long_from_unicode(self): assert long(u'12345678901234567890') == 12345678901234567890 assert int(u'12345678901234567890') == 12345678901234567890 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py Sat Jul 2 14:34:15 2005 @@ -505,19 +505,32 @@ return space.w_False return space.w_True -def unicode_center__Unicode_ANY(space, w_self, w_width): +def unicode_center__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value width = space.int_w(w_width) + + if space.is_true(space.isinstance(w_fillchar, space.w_str)): + fillchar = space.str_w(w_fillchar) + if len(fillchar) != 1: + raise OperationError( + space.w_TypeError, + space.wrap("center() argument 2 must be a single character")) + elif space.is_true(space.isinstance(w_fillchar, space.w_unicode)): + if len(w_fillchar._value) != 1: + raise OperationError( + space.w_TypeError, + space.wrap("center() argument 2 must be a single character")) + fillchar = w_fillchar._value[0] + padding = width - len(self) if padding < 0: return space.call_function(space.w_unicode, w_self) leftpad = padding // 2 + (padding & width & 1) - result = [u' '] * width + result = [fillchar] * width for i in range(len(self)): result[leftpad + i] = self[i] return W_UnicodeObject(space, result) - def unicode_ljust__Unicode_ANY(space, w_self, w_width): self = w_self._value width = space.int_w(w_width) @@ -902,4 +915,8 @@ return space.call_method(space.call_function(space.w_unicode, w_self), 'rsplit', w_delim, w_maxsplit) + def str_center__String_ANY_Unicode(space, w_self, w_width, w_fillchar): + return space.call_method(space.call_function(space.w_unicode, w_self), + 'center', w_width, w_fillchar) + register_all(vars(), stringtype) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Sat Jul 2 14:34:15 2005 @@ -5,7 +5,7 @@ from sys import maxint unicode_capitalize = MultiMethod('capitalize', 1) -unicode_center = MultiMethod('center', 2, ) +unicode_center = MultiMethod('center', 3, defaults=(' ',)) unicode_count = MultiMethod('count', 4, defaults=(0, maxint)) unicode_encode = MultiMethod('encode', 3, defaults=(None, None)) unicode_endswith = MultiMethod('endswith', 4, defaults=(0,maxint)) From gintas at codespeak.net Sat Jul 2 14:37:53 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 14:37:53 +0200 (CEST) Subject: [pypy-svn] r14092 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050702123753.B279527B8B@code1.codespeak.net> Author: gintas Date: Sat Jul 2 14:37:52 2005 New Revision: 14092 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_format.py - copied, changed from r14077, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_format.py Log: Updated test_format to run quicker, fixed minor incompatibility. This test depends on several fixes in trunk (r14089, r14090). I did not port them to the branch to prevent merging problems. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_format.py (from r14077, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_format.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_format.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_format.py Sat Jul 2 14:37:52 2005 @@ -53,7 +53,8 @@ testboth("%#.*g", (110, -1.e+100/3.)) # test some ridiculously large precision, expect overflow -testboth('%12.*f', (123456, 1.0)) +#Too slow on PyPy +#testboth('%12.*f', (123456, 1.0)) # Formatting of long integers. Overflow is not ok overflowok = 0 @@ -234,7 +235,8 @@ # crashes 2.2.1 and earlier: try: "%*d"%(sys.maxint, -127) - except MemoryError: - pass + except (MemoryError, OverflowError): + pass # CPython raises MemoryError, but both CPython and PyPy raise + # OverflowError for string concatenation else: raise TestFailed, '"%*d"%(sys.maxint, -127) should fail' From gintas at codespeak.net Sat Jul 2 14:51:33 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 14:51:33 +0200 (CEST) Subject: [pypy-svn] r14093 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050702125133.D3CDA27B94@code1.codespeak.net> Author: gintas Date: Sat Jul 2 14:51:32 2005 New Revision: 14093 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_bufio.py - copied, changed from r14077, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bufio.py Log: Added an override for test_bufio.py to make it significantly faster. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_bufio.py (from r14077, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bufio.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_bufio.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_bufio.py Sat Jul 2 14:51:32 2005 @@ -48,8 +48,11 @@ nullpat = "\0" * 1000 try: - for size in range(1, 257) + [512, 1000, 1024, 2048, 4096, 8192, 10000, - 16384, 32768, 65536, 1000000]: +# Too slow for PyPy. +# for size in range(1, 257) + [512, 1000, 1024, 2048, 4096, 8192, 10000, +# 16384, 32768, 65536, 1000000]: + for size in range(1, 9) + [9, 63, 64, 65, 128, 129, 254, 255, 256, 512, + 1000, 1024, 2048, 4096, 8192, 10000, 16384]: drive_one(primepat, size) drive_one(nullpat, size) finally: From hpk at codespeak.net Sat Jul 2 15:54:26 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 2 Jul 2005 15:54:26 +0200 (CEST) Subject: [pypy-svn] r14094 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702135426.EE34A27B6D@code1.codespeak.net> Author: hpk Date: Sat Jul 2 15:54:26 2005 New Revision: 14094 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py Log: fix actual invocation of backend optimizations (untested right here on osx) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 2 15:54:26 2005 @@ -2,7 +2,7 @@ from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.objspace.flow.model import flatten, mkentrymap, traverse from pypy.rpython import lltype -from pypy.translator.llvm2.cfgtransform import prepare_graph +from pypy.translator.backendoptimization import remove_same_as from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.log import log log = log.funcnode @@ -38,8 +38,9 @@ def __init__(self, db, const_ptr_func): self.db = db self.ref = "%" + const_ptr_func.value._obj._name - self.graph = prepare_graph(const_ptr_func.value._obj.graph, - db._translator) + self.graph = const_ptr_func.value._obj.graph + remove_same_as(self.graph) + def __str__(self): return "" %(self.ref,) @@ -53,6 +54,7 @@ for op in node.operations: map(self.db.prepare_arg, op.args) self.db.prepare_arg(op.result) + assert self.graph, "cannot traverse" traverse(visit, self.graph) self._issetup = True # ______________________________________________________________________ From ac at codespeak.net Sat Jul 2 15:56:08 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 2 Jul 2005 15:56:08 +0200 (CEST) Subject: [pypy-svn] r14095 - pypy/branch/dist-2.4.1/lib-python Message-ID: <20050702135608.785D827B6D@code1.codespeak.net> Author: ac Date: Sat Jul 2 15:56:08 2005 New Revision: 14095 Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py Log: Add tests that are new to Python 2.4 Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/conftest.py (original) +++ pypy/branch/dist-2.4.1/lib-python/conftest.py Sat Jul 2 15:56:08 2005 @@ -350,9 +350,11 @@ RegrTest('test___all__.py', enabled=False, core=True), # fixable RegrTest('test___future__.py', enabled=True, dumbtest=1, core=True), + RegrTest('test__locale.py', enabled=True), RegrTest('test_aepack.py', enabled=False), RegrTest('test_al.py', enabled=False, dumbtest=1), RegrTest('test_anydbm.py', enabled=True, core=True), + RegrTest('test_applesingle.py', enabled=False), RegrTest('test_array.py', enabled=False), # c-extension #rev 10840: Uncaught interp-level exception: Same place as test_cfgparser @@ -395,6 +397,17 @@ RegrTest('test_cmath.py', enabled=True, dumbtest=1, core=True), RegrTest('test_codeccallbacks.py', enabled=False), #rev 10840: Uncaught interp-level exception: Same place as test_cfgparser + RegrTest('test_codecencodings_cn.py', enabled=False), + RegrTest('test_codecencodings_hk.py', enabled=False), + RegrTest('test_codecencodings_jp.py', enabled=False), + RegrTest('test_codecencodings_kr.py', enabled=False), + RegrTest('test_codecencodings_tw.py', enabled=False), + + RegrTest('test_codecmaps_cn.py', enabled=False), + RegrTest('test_codecmaps_hk.py', enabled=False), + RegrTest('test_codecmaps_jp.py', enabled=False), + RegrTest('test_codecmaps_kr.py', enabled=False), + RegrTest('test_codecmaps_tw.py', enabled=False), RegrTest('test_codecs.py', enabled=False), #rev 10840: Uncaught interp-level exception: Same place as test_cfgparser @@ -402,14 +415,18 @@ RegrTest('test_codeop.py', enabled=True, core=True), RegrTest('test_coercion.py', enabled=False, oldstyle=True, core=True), # needed changes because our exceptions are new-style and so have a different str(.) behavior + + RegrTest('test_colorsys.py', enabled=True, core=True), RegrTest('test_commands.py', enabled=True), RegrTest('test_compare.py', enabled=True, oldstyle=True, core=True), RegrTest('test_compile.py', enabled=True, core=True), + RegrTest('test_compiler.py', enabled=True, core=True), RegrTest('test_complex.py', enabled=False, core=True), #rev 10840: at least one test fails, after several hours I gave up waiting for the rest RegrTest('test_contains.py', enabled=True, dumbtest=1, core=True), RegrTest('test_cookie.py', enabled=False, core=True), + RegrTest('test_cookielib.py', enabled=False, core=True), RegrTest('test_copy.py', enabled=True, core=True), RegrTest('test_copy_reg.py', enabled=True, core=True), RegrTest('test_cpickle.py', enabled=False, core=True), @@ -420,12 +437,17 @@ RegrTest('test_curses.py', enabled=False, dumbtest=1), RegrTest('test_datetime.py', enabled=True, core=True), RegrTest('test_dbm.py', enabled=False, dumbtest=1), + RegrTest('test_decimal.py', enabled=True, core=True), + RegrTest('test_decorators.py', enabled=True, core=True), + RegrTest('test_deque.py', enabled=True, core=True), RegrTest('test_descr.py', enabled=False, core=True, oldstyle=True), RegrTest('test_descrtut.py', enabled=False, core=True, oldstyle=True), + RegrTest('test_dict.py', enabled=True, core=True), RegrTest('test_difflib.py', enabled=True, dumbtest=1, core=True), RegrTest('test_dircache.py', enabled=True, core=True), RegrTest('test_dis.py', enabled=True), + RegrTest('test_distutils.py', enabled=True, core=True), RegrTest('test_dl.py', enabled=False, dumbtest=1), RegrTest('test_doctest.py', enabled=True, core=True), RegrTest('test_doctest2.py', enabled=True, core=True), @@ -461,7 +483,7 @@ RegrTest('test_gdbm.py', enabled=False, dumbtest=1), RegrTest('test_generators.py', enabled=False, core=True), #rev 10840: 30 of 152 tests fail - + RegrTest('test_genexps.py', enabled=True, core=True), RegrTest('test_getargs.py', enabled=False, dumbtest=1), RegrTest('test_getargs2.py', enabled=False), #rev 10840: ImportError: _testcapi @@ -503,12 +525,13 @@ RegrTest('test_isinstance.py', enabled=True, core=True), RegrTest('test_iter.py', enabled=False, core=True, uselibfile=True), #rev 10840: Uncaught interp-level exception: Same place as test_cfgparser - + RegrTest('test_iterlen.py', enabled=True, core=True) RegrTest('test_itertools.py', enabled=True, core=True), # modified version in pypy/lib/test2 RegrTest('test_largefile.py', enabled=True, dumbtest=1), RegrTest('test_linuxaudiodev.py', enabled=False), + RegrTest('test_list.py', enabled=True, core=True), RegrTest('test_locale.py', enabled=False, dumbtest=1), RegrTest('test_logging.py', enabled=False), RegrTest('test_long.py', enabled=True, dumbtest=1, core=True), @@ -528,7 +551,8 @@ RegrTest('test_minidom.py', enabled=False, dumbtest=1), RegrTest('test_mmap.py', enabled=False), RegrTest('test_module.py', enabled=False, dumbtest=1, core=True), - RegrTest('test_mpz.py', enabled=False, dumbtest=1), + RegrTest('test_multibytecodec.py', enabled=True, core=True), + RegrTest('test_multibytecodec_support.py', enabled=True, core=True), RegrTest('test_multifile.py', enabled=True, core=True), RegrTest('test_mutants.py', enabled=False, dumbtest=1, core="possibly"), RegrTest('test_netrc.py', enabled=True, core=True), @@ -550,12 +574,14 @@ RegrTest('test_parser.py', enabled=False), #rev 10840: 18 of 18 tests fail + RegrTest('test_peepholer.py', enabled=True), RegrTest('test_pep247.py', enabled=False, dumbtest=1), RegrTest('test_pep263.py', enabled=True, dumbtest=1), RegrTest('test_pep277.py', enabled=False), # XXX this test is _also_ an output test, damn it # seems to be the only one that invokes run_unittest # and is an unittest + RegrTest('test_pep292.py', enabled=True, core=True), RegrTest('test_pickle.py', enabled=False, core=True), RegrTest('test_pickletools.py', enabled=False, dumbtest=1, core=True), RegrTest('test_pkg.py', enabled=False, core=True), @@ -600,11 +626,11 @@ #rev 10840: 1 of 11 test fails. The failing one had an infinite recursion. RegrTest('test_robotparser.py', enabled=True, core=True), - RegrTest('test_rotor.py', enabled=False), RegrTest('test_sax.py', enabled=False, dumbtest=1), RegrTest('test_scope.py', enabled=True, core=True), RegrTest('test_scriptpackages.py', enabled=False), RegrTest('test_select.py', enabled=False, dumbtest=1), + RegrTest('test_set.py', enabled=True, core=True), RegrTest('test_sets.py', enabled=True, core=True), RegrTest('test_sgmllib.py', enabled=True, core=True), RegrTest('test_sha.py', enabled=True), @@ -613,6 +639,8 @@ RegrTest('test_shlex.py', enabled=True, core=True), RegrTest('test_shutil.py', enabled=True, core=True), RegrTest('test_signal.py', enabled=False), + RegrTest('test_site.py', enabled=False, core=True), + # Needs non-faked codecs. RegrTest('test_slice.py', enabled=True, dumbtest=1, core=True), RegrTest('test_socket.py', enabled=False), #rev 10840: ImportError: thread @@ -638,12 +666,14 @@ RegrTest('test_struct.py', enabled=False, dumbtest=1), RegrTest('test_structseq.py', enabled=False, dumbtest=1), + RegrTest('test_subprocess.py', enabled=False), RegrTest('test_sunaudiodev.py', enabled=False, dumbtest=1), RegrTest('test_sundry.py', enabled=False, dumbtest=1), # test_support is not a test RegrTest('test_symtable.py', enabled=False, dumbtest=1), RegrTest('test_syntax.py', enabled=True, core=True), RegrTest('test_sys.py', enabled=True, core=True), + RegrTest('test_tcl.py', enabled=False), RegrTest('test_tarfile.py', enabled=False, core="possibly"), #rev 10840: 13 of 13 test fail @@ -659,6 +689,8 @@ RegrTest('test_threading.py', enabled=False, dumbtest=1), #rev 10840: ImportError: thread + RegrTest('test_threading_local.py', enabled=False, dumbtest=1), + RegrTest('test_threadsignals.py', enabled=False, dumbtest=1), RegrTest('test_time.py', enabled=True, core=True), RegrTest('test_timeout.py', enabled=False), @@ -669,6 +701,8 @@ RegrTest('test_trace.py', enabled=True, core=True), RegrTest('test_traceback.py', enabled=False, core=True), #rev 10840: 2 of 2 tests fail + RegrTest('test_transformer.py', enabled=True, core=True), + RegrTest('test_tuple.py', enabled=True, core=True), RegrTest('test_types.py', enabled=True, core=True), #rev 11598: one of the mod related to dict iterators is questionable @@ -680,10 +714,12 @@ RegrTest('test_unicode.py', enabled=False), #, core=True), RegrTest('test_unicode_file.py', enabled=False), RegrTest('test_unicodedata.py', enabled=False), + RegrTest('test_unittest.py', enabled=True, core=True), RegrTest('test_univnewlines.py', enabled=True, core=True), RegrTest('test_unpack.py', enabled=True, dumbtest=1, core=True), RegrTest('test_urllib.py', enabled=True, core=True), RegrTest('test_urllib2.py', enabled=True, dumbtest=1, core=True), + RegrTest('test_urllib2net.py', enabled=True), RegrTest('test_urllibnet.py', enabled=False), # try to understand failure!!! RegrTest('test_urlparse.py', enabled=True, core=True), @@ -706,7 +742,7 @@ #rev 10840: 2 of 5 tests fail RegrTest('test_xpickle.py', enabled=False), - RegrTest('test_xreadline.py', enabled=False), + RegrTest('test_xrange.py', enabled=True, core=True), RegrTest('test_zipfile.py', enabled=False, dumbtest=1), RegrTest('test_zipimport.py', enabled=False), #rev 10840: ImportError: zlib From hpk at codespeak.net Sat Jul 2 16:04:15 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 2 Jul 2005 16:04:15 +0200 (CEST) Subject: [pypy-svn] r14096 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050702140415.32F8827B6C@code1.codespeak.net> Author: hpk Date: Sat Jul 2 16:04:14 2005 New Revision: 14096 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: fix invocations of optimizations and unsimplificiations even more Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 2 16:04:14 2005 @@ -3,6 +3,7 @@ from pypy.objspace.flow.model import flatten, mkentrymap, traverse from pypy.rpython import lltype from pypy.translator.backendoptimization import remove_same_as +from pypy.translator.unsimplify import remove_double_links from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.log import log log = log.funcnode @@ -40,6 +41,7 @@ self.ref = "%" + const_ptr_func.value._obj._name self.graph = const_ptr_func.value._obj.graph remove_same_as(self.graph) + remove_double_links(self.db._translator, self.graph) def __str__(self): return "" %(self.ref,) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jul 2 16:04:14 2005 @@ -23,6 +23,8 @@ a = t.annotate(annotate) t.specialize() a.simplify() + if view: + t.view() return genllvm(t) @@ -32,6 +34,20 @@ f = compile_function(simple1, []) assert f() == 1 +def Xtest_simple_function_pointer(): + def f1(x): + return x + 1 + def f2(x): + return x + 2 + + l = [f1, f2] + + def pointersimple(i): + return l[i] + + f = compile_function(pointersimple, [int]) + assert f + def test_simple_branching(): def simple5(b): if b: @@ -153,7 +169,7 @@ if m == 0: return ackermann(n - 1, 1) return ackermann(n - 1, ackermann(n, m - 1)) - f = compile_function(call_ackermann, [int, int]) + f = compile_function(call_ackermann, [int, int], view=False) assert f(0, 2) == 3 def test_tuple_getitem(): From ericvrp at codespeak.net Sat Jul 2 16:16:09 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 2 Jul 2005 16:16:09 +0200 (CEST) Subject: [pypy-svn] r14097 - in pypy/dist/pypy/translator: . llvm2 test Message-ID: <20050702141609.BF1FA27B6C@code1.codespeak.net> Author: ericvrp Date: Sat Jul 2 16:16:09 2005 New Revision: 14097 Added: pypy/dist/pypy/translator/test/test_backendoptimization.py Modified: pypy/dist/pypy/translator/backendoptimization.py pypy/dist/pypy/translator/llvm2/genllvm.py Log: (ericvrp, cfbolz) added remove_void which tries to get rid of unneccessary voids in the flow graph. works only for void function arguments at the moment. Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Sat Jul 2 16:16:09 2005 @@ -1,9 +1,10 @@ import autopath from pypy.translator.translator import Translator from pypy.objspace.flow.model import Variable, Constant, Block, Link +from pypy.objspace.flow.model import SpaceOperation from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph from pypy.tool.unionfind import UnionFind - +from pypy.rpython.lltype import Void def remove_same_as(graph): """Remove all 'same_as' operations. @@ -41,6 +42,21 @@ traverse(visit, graph) +def remove_void(translator): + for func, graph in translator.flowgraphs.iteritems(): + args = [arg for arg in graph.startblock.inputargs + if arg.concretetype is not Void] + graph.startblock.inputargs = args + def visit(block): + if isinstance(block, Block): + for op in block.operations: + if op.opname == 'direct_call': + args = [arg for arg in op.args + if arg.concretetype is not Void] + op.args = args + for func, graph in translator.flowgraphs.iteritems(): + traverse(visit, graph) + def SSI_to_SSA(graph): """Rename the variables in a flow graph as much as possible without violating the SSA rule. 'SSI' means that each Variable in a flow graph is Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 2 16:16:09 2005 @@ -8,8 +8,10 @@ from pypy.rpython import lltype from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter +from pypy.translator.backendoptimization import remove_void def genllvm(translator): + remove_void(translator) func = translator.entrypoint db = Database(translator) Added: pypy/dist/pypy/translator/test/test_backendoptimization.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/test/test_backendoptimization.py Sat Jul 2 16:16:09 2005 @@ -0,0 +1,24 @@ +from pypy.translator.backendoptimization import remove_void +from pypy.translator.translator import Translator +from pypy.rpython.lltype import Void +from pypy.rpython.llinterp import LLInterpreter +from pypy.objspace.flow.model import checkgraph + +def annotate_and_remove_void(f, annotate): + t = Translator(f) + a = t.annotate(annotate) + t.specialize() + remove_void(t) + return t + +def test_remove_void_args(): + def f(i): + return [1,2,3,i][i] + t = annotate_and_remove_void(f, [int]) + for func, graph in t.flowgraphs.iteritems(): + assert checkgraph(graph) is None + for arg in graph.startblock.inputargs: + assert arg.concretetype is not Void + interp = LLInterpreter(t.flowgraphs, t.rtyper) + assert interp.eval_function(f, [0]) == 1 + From rxe at codespeak.net Sat Jul 2 16:41:53 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 2 Jul 2005 16:41:53 +0200 (CEST) Subject: [pypy-svn] r14098 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050702144153.63AE527B44@code1.codespeak.net> Author: rxe Date: Sat Jul 2 16:41:52 2005 New Revision: 14098 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Small developments towards varsized structs/arrays. Renamed StructInstance to StructNode and StructNode to StructTypeNode. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sat Jul 2 16:41:52 2005 @@ -1,21 +1,21 @@ import py +from pypy.rpython import lltype from pypy.translator.llvm2.log import log log = log.structnode -class ArrayNode(object): +class ArrayTypeNode(object): _issetup = False - array_counter = 0 - def __init__(self, db, array): self.db = db self.array = array - self.ref = "%%array.%s.%s" % (array.OF, ArrayNode.array_counter) - ArrayNode.array_counter += 1 - + self.ref_template = "%%array.%s" % array.OF + self.ref = self.ref_template + ".0" + def __str__(self): - return "" % self.ref + return "" % self.ref def setup(self): + self.db.prepare_repr_arg_type(self.array.OF) self._issetup = True # ______________________________________________________________________ @@ -23,3 +23,55 @@ # def writedatatypedecl(self, codewriter): codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) + + +# Each ArrayNode is a global constant. This needs to have a specific type of +# a certain type. + +class ArrayNode(object): + + _issetup = False + array_counter = 0 + + def __init__(self, db, value): + self.db = db + self.name = "%s.%s" % (value._TYPE.OF, ArrayNode.array_counter) + self.ref = "%%stinstance.%s" % self.name + self.value = value + ArrayNode.array_counter += 1 + + def __str__(self): + return "" %(self.ref,) + + def setup(self): + T = self.value._TYPE.OF + for item in self.value.items: + if not isinstance(T, lltype.Primitive): + value = getattr(self.value, name) + # Create a dummy constant hack XXX + c = Constant(value, T) + self.db.prepare_arg(c) + + self._issetup = True + + def get_values(self): + res = [] + + T = self.value._TYPE.OF + typval = self.db.repr_arg_type(self.value._TYPE.OF) + for value in self.value.items: + if not isinstance(T, lltype.Primitive): + # Create a dummy constant hack XXX + value = self.db.repr_arg(Constant(value, T)) + else: + value = repr(value) + res.append((typval, value)) + + return ", ".join(["%s %s" % (t, v) for t, v in res]) + + def writedata(self, codewriter): + lenitems = len(self.value.items) + lenstr = ".%s" % lenitems + codewriter.globalinstance(self.ref, + self.db.repr_arg_type() + lenstr, + self.get_values()) Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 2 16:41:52 2005 @@ -26,6 +26,9 @@ def label(self, name): self.append(" %s:" % name) + def globalinstance(self, name, type, data): + self.append("%s = internal constant %s {%s}" % (name, type, data)) + def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jul 2 16:41:52 2005 @@ -1,7 +1,7 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode -from pypy.translator.llvm2.structnode import StructNode, StructInstance -from pypy.translator.llvm2.arraynode import ArrayNode +from pypy.translator.llvm2.structnode import StructNode, StructTypeNode +from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -42,19 +42,22 @@ if isinstance(ct, lltype.FuncType): self.addpending(const_or_var, FuncNode(self, const_or_var)) else: - #value = const_or_var.value - #while hasattr(value, "_obj"): - # value = value._obj - + value = const_or_var.value + while hasattr(value, "_obj"): + value = value._obj + if isinstance(ct, lltype.Struct): - self.addpending(const_or_var, StructInstance(self, value)) + self.addpending(const_or_var, StructNode(self, value)) + + elif isinstance(ct, lltype.Array): + self.addpending(const_or_var, ArrayNode(self, value)) elif isinstance(ct, lltype.Primitive): log.prepare(const_or_var, "(is primitive)") else: log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var)) else: - log.prepare.ignore(const_or_var) + log.prepare(const_or_var, type(const_or_var)) #XXX dont checkin def prepare_repr_arg_multi(self, args): for const_or_var in args: @@ -69,13 +72,13 @@ self.prepare_repr_arg_type(type_.TO) elif isinstance(type_, lltype.Struct): - self.addpending(type_, StructNode(self, type_)) + self.addpending(type_, StructTypeNode(self, type_)) elif isinstance(type_, lltype.FuncType): self.addpending(type_, FuncTypeNode(self, type_)) elif isinstance(type_, lltype.Array): - self.addpending(type_, ArrayNode(self, type_)) + self.addpending(type_, ArrayTypeNode(self, type_)) else: log.XXX("need to prepare typerepr", type_) @@ -91,7 +94,9 @@ def setup_all(self): while self._pendingsetup: - self._pendingsetup.pop().setup() + x = self._pendingsetup.pop() + log.setup_all(x) + x.setup() def getobjects(self, subset_types=None): res = [] @@ -102,13 +107,13 @@ return res def get_typedecls(self): - return self.getobjects((StructNode, ArrayNode, FuncTypeNode)) + return self.getobjects((StructTypeNode, ArrayTypeNode, FuncTypeNode)) def get_globaldata(self): - return self.getobjects((StructInstance)) + return self.getobjects((StructNode, ArrayNode)) def get_functions(self): - struct_nodes = [n for n in self.getobjects(StructNode) if n.inline_struct] + struct_nodes = [n for n in self.getobjects(StructTypeNode) if n.inline_struct] return struct_nodes + self.getobjects(FuncNode) def dump(self): @@ -119,12 +124,12 @@ log.dump_db("*** type declarations ***") for k,v in all_objs: - if isinstance(v, (StructNode, ArrayNode)): + if isinstance(v, (StructTypeNode, ArrayTypeNode)): log.dump_db("%s ---> %s" % (k, v)) log.dump_db("*** global data ***") for k,v in all_objs: - if isinstance(v, (StructInstance)): + if isinstance(v, (StructNode)): log.dump_db("%s ---> %s" % (k, v)) log.dump_db("*** function protos ***") Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 2 16:41:52 2005 @@ -4,7 +4,7 @@ from pypy.rpython import lltype log = log.structnode -class StructNode(object): +class StructTypeNode(object): _issetup = False struct_counter = 0 @@ -14,24 +14,20 @@ self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name, StructNode.struct_counter) + self.name = "%s.%s" % (self.struct._name, StructTypeNode.struct_counter) self.ref = "%%st.%s" % self.name self.inline_struct = self.struct._arrayfld - StructNode.struct_counter += 1 + StructTypeNode.struct_counter += 1 def __str__(self): - return "" %(self.ref,) + return "" %(self.ref,) def setup(self): # Recurse for fieldname in self.struct._names: field_type = getattr(self.struct, fieldname) self.db.prepare_repr_arg_type(field_type) - - if self.inline_struct: - log.XXX("Register me", self) - self._issetup = True def get_decl_for_varsize(self): @@ -57,7 +53,6 @@ codewriter.declare(self.get_decl_for_varsize()) def writeimpl(self, codewriter): - if self.inline_struct: log.writeimpl(self.ref) codewriter.openfunc(self.get_decl_for_varsize()) @@ -89,42 +84,46 @@ codewriter.closefunc() -class StructInstance(object): +class StructNode(object): _issetup = False struct_counter = 0 def __init__(self, db, value): self.db = db - self.name = "%s.%s" % (value._TYPE._name, StructInstance.struct_counter) + self.name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) self.ref = "%%stinstance.%s" % self.name self.value = value - StructInstance.struct_counter += 1 + StructNode.struct_counter += 1 def __str__(self): - return "" %(self.ref,) + return "" %(self.ref,) def setup(self): - # Recurse fields (XXX Messy!) for name in self.value._TYPE._names: T = self.value._TYPE._flds[name] - self.db.prepare_repr_arg_type(T) if not isinstance(T, lltype.Primitive): value = getattr(self.value, name) - self.db.prepare_repr_arg(value) + # Create a dummy constant hack XXX + c = Constant(value, T) + self.db.prepare_arg(c) self._issetup = True -# def struct_repr(self): -# typ = repr_arg_type(self.value) -# self.value._TYPE._names -# typevaluepairs = ["%s %s" % for t, v in -# typevaluepairsstr = ", ".join(typevaluepairs) -# return "%s { %s }" % (typ, typevaluepairsstr) + def get_values(self): + res = [] + for name in self.value._TYPE._names: + T = self.value._TYPE._flds[name] + value = getattr(self.value, name) + if not isinstance(T, lltype.Primitive): + # Create a dummy constant hack XXX + value = self.db.repr_arg(Constant(value, T)) + else: + value = str(value) + res.append((self.db.repr_arg_type(T), value)) + return ", ".join(["%s %s" % (t, v) for t, v in res]) def writedata(self, codewriter): - log.XXXXXXXXXX("ooops TODO should write - ", self.ref) - for name in self.value._TYPE._names: - log.XXXXXXXXXX("ooops ", getattr(self.value, name)) - typ = self.db.repr_arg_type(self.value._TYPE) - # XXX constant you say? - codewriter.append("%s = internal constant %s* null" % (self.ref, typ)) + codewriter.globalinstance(self.ref, + self.db.repr_arg_type(self.value._TYPE), + self.get_values()) + Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jul 2 16:41:52 2005 @@ -23,11 +23,10 @@ a = t.annotate(annotate) t.specialize() a.simplify() - if view: + if view: t.view() return genllvm(t) - def test_return1(): def simple1(): return 1 @@ -201,16 +200,6 @@ assert f(-1) == 3 assert f(0) == 5 -def test_list_getitem(): - def list_getitem(i): - l = [1,2,i] - return l[i] - f = compile_function(list_getitem, [int]) - assert f(0) == 1 - assert f(1) == 2 - assert f(3) == 3 - - def DONOT_test_simple_chars(): def char_constant2(s): s = s + s + s @@ -220,7 +209,23 @@ f = compile_function(char_constant, []) assert f() == 7 -def DONOTtest_string_getitem(): +def DONOT_test_list_getitem(): + def list_getitem(i): + l = [1,2,i] + return l[i] + f = compile_function(list_getitem, [int]) + assert f(0) == 1 + assert f(1) == 2 + assert f(3) == 3 + +def DONOT_test_string_getitem1(): + l = "Hello, World" + def string_test(i): + return l[i] + f = compile_function(string_test, [int], view=True) + assert f(0) == ord("H") + +def DONOT_test_string_getitem2(): def string_test(i): l = "Hello, World" return l[i] From ludal at codespeak.net Sat Jul 2 17:03:02 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sat, 2 Jul 2005 17:03:02 +0200 (CEST) Subject: [pypy-svn] r14099 - pypy/dist/pypy/interpreter Message-ID: <20050702150302.639DB27B4A@code1.codespeak.net> Author: ludal Date: Sat Jul 2 17:03:00 2005 New Revision: 14099 Added: pypy/dist/pypy/interpreter/pycompiler.py - copied unchanged from r14098, pypy/dist/pypy/interpreter/compiler.py Removed: pypy/dist/pypy/interpreter/compiler.py Modified: pypy/dist/pypy/interpreter/executioncontext.py Log: renamed interpreter/compiler.py to prevent name conflict with compiler.py from std lib Deleted: /pypy/dist/pypy/interpreter/compiler.py ============================================================================== --- /pypy/dist/pypy/interpreter/compiler.py Sat Jul 2 17:03:00 2005 +++ (empty file) @@ -1,165 +0,0 @@ -""" -General classes for bytecode compilers. -Compiler instances are stored into 'space.getexecutioncontext().compiler'. -""" -from codeop import PyCF_DONT_IMPLY_DEDENT -from pypy.interpreter.error import OperationError - - -class Compiler: - """Abstract base class for a bytecode compiler.""" - - # The idea is to grow more methods here over the time, - # e.g. to handle .pyc files in various ways if we have multiple compilers. - - def __init__(self, space): - self.space = space - - def compile(self, source, filename, mode, flags): - """Compile and return an pypy.interpreter.eval.Code instance.""" - raise NotImplementedError - - def getcodeflags(self, code): - """Return the __future__ compiler flags that were used to compile - the given code object.""" - return 0 - - def compile_command(self, source, filename, mode, flags): - """Same as compile(), but tries to compile a possibly partial - interactive input. If more input is needed, it returns None. - """ - # Hackish default implementation based on the stdlib 'codeop' module. - # See comments over there. - space = self.space - flags |= PyCF_DONT_IMPLY_DEDENT - # Check for source consisting of only blank lines and comments - if mode != "eval": - in_comment = False - for c in source: - if c in ' \t\f\v': # spaces - pass - elif c == '#': - in_comment = True - elif c in '\n\r': - in_comment = False - elif not in_comment: - break # non-whitespace, non-comment character - else: - source = "pass" # Replace it with a 'pass' statement - - try: - code = self.compile(source, filename, mode, flags) - return code # success - except OperationError, err: - if not err.match(space, space.w_SyntaxError): - raise - - try: - self.compile(source + "\n", filename, mode, flags) - return None # expect more - except OperationError, err1: - if not err1.match(space, space.w_SyntaxError): - raise - - try: - self.compile(source + "\n\n", filename, mode, flags) - raise # uh? no error with \n\n. re-raise the previous error - except OperationError, err2: - if not err2.match(space, space.w_SyntaxError): - raise - - if space.eq_w(err1.w_value, err2.w_value): - raise # twice the same error, re-raise - - return None # two different errors, expect more - - -# ____________________________________________________________ -# faked compiler - -import warnings -import __future__ -compiler_flags = 0 -for fname in __future__.all_feature_names: - compiler_flags |= getattr(__future__, fname).compiler_flag - - -class CPythonCompiler(Compiler): - """Faked implementation of a compiler, using the underlying compile().""" - - def compile(self, source, filename, mode, flags): - flags |= __future__.generators.compiler_flag # always on (2.2 compat) - space = self.space - try: - old = self.setup_warn_explicit(warnings) - try: - c = compile(source, filename, mode, flags, True) - finally: - self.restore_warn_explicit(warnings, old) - # It would be nice to propagate all exceptions to app level, - # but here we only propagate the 'usual' ones, until we figure - # out how to do it generically. - except SyntaxError,e: - w_synerr = space.newtuple([space.wrap(e.msg), - space.newtuple([space.wrap(e.filename), - space.wrap(e.lineno), - space.wrap(e.offset), - space.wrap(e.text)])]) - raise OperationError(space.w_SyntaxError, w_synerr) - except ValueError,e: - raise OperationError(space.w_ValueError,space.wrap(str(e))) - except TypeError,e: - raise OperationError(space.w_TypeError,space.wrap(str(e))) - from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) - compile._annspecialcase_ = "override:cpy_compile" - - def getcodeflags(self, code): - from pypy.interpreter.pycode import PyCode - if isinstance(code, PyCode): - return code.co_flags & compiler_flags - else: - return 0 - - def _warn_explicit(self, message, category, filename, lineno, - module=None, registry=None): - if hasattr(category, '__bases__') and \ - issubclass(category, SyntaxWarning): - assert isinstance(message, str) - space = self.space - w_mod = space.sys.getmodule('warnings') - if w_mod is not None: - w_dict = w_mod.getdict() - w_reg = space.call_method(w_dict, 'setdefault', - space.wrap("__warningregistry__"), - space.newdict([])) - try: - space.call_method(w_mod, 'warn_explicit', - space.wrap(message), - space.w_SyntaxWarning, - space.wrap(filename), - space.wrap(lineno), - space.w_None, - space.w_None) - except OperationError, e: - if e.match(space, space.w_SyntaxWarning): - raise OperationError( - space.w_SyntaxError, - space.wrap(message)) - raise - - def setup_warn_explicit(self, warnings): - """ - this is a hack until we have our own parsing/compiling - in place: we bridge certain warnings to the applevel - warnings module to let it decide what to do with - a syntax warning ... - """ - # there is a hack to make the flow space happy: - # 'warnings' should not look like a Constant - old_warn_explicit = warnings.warn_explicit - warnings.warn_explicit = self._warn_explicit - return old_warn_explicit - - def restore_warn_explicit(self, warnings, old_warn_explicit): - warnings.warn_explicit = old_warn_explicit Modified: pypy/dist/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/dist/pypy/interpreter/executioncontext.py (original) +++ pypy/dist/pypy/interpreter/executioncontext.py Sat Jul 2 17:03:00 2005 @@ -1,7 +1,7 @@ import sys from pypy.interpreter.miscutils import Stack from pypy.interpreter.error import OperationError -from pypy.interpreter.compiler import CPythonCompiler +from pypy.interpreter.pycompiler import CPythonCompiler class ExecutionContext: """An ExecutionContext holds the state of an execution thread From arigo at codespeak.net Sat Jul 2 17:09:47 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Jul 2005 17:09:47 +0200 (CEST) Subject: [pypy-svn] r14100 - pypy/branch/dist-2.4.1/lib-python Message-ID: <20050702150947.2C8C527B56@code1.codespeak.net> Author: arigo Date: Sat Jul 2 17:09:45 2005 New Revision: 14100 Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py Log: Typo. Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/conftest.py (original) +++ pypy/branch/dist-2.4.1/lib-python/conftest.py Sat Jul 2 17:09:45 2005 @@ -525,7 +525,7 @@ RegrTest('test_isinstance.py', enabled=True, core=True), RegrTest('test_iter.py', enabled=False, core=True, uselibfile=True), #rev 10840: Uncaught interp-level exception: Same place as test_cfgparser - RegrTest('test_iterlen.py', enabled=True, core=True) + RegrTest('test_iterlen.py', enabled=True, core=True), RegrTest('test_itertools.py', enabled=True, core=True), # modified version in pypy/lib/test2 From arigo at codespeak.net Sat Jul 2 17:14:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Jul 2005 17:14:05 +0200 (CEST) Subject: [pypy-svn] r14101 - pypy/branch/dist-2.4.1/pypy/objspace Message-ID: <20050702151405.48E4A27B56@code1.codespeak.net> Author: arigo Date: Sat Jul 2 17:14:03 2005 New Revision: 14101 Modified: pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py Log: Removed unnecessary line left behind. Modified: pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/descroperation.py Sat Jul 2 17:14:03 2005 @@ -282,8 +282,6 @@ if w_del is not None: space.get_and_call_function(w_del, w_obj) - _NESTING_LIMIT = 20 - def cmp(space, w_v, w_w): if space.is_w(w_v, w_w): From arigo at codespeak.net Sat Jul 2 17:22:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 2 Jul 2005 17:22:39 +0200 (CEST) Subject: [pypy-svn] r14102 - in pypy/branch/dist-2.4.1/pypy: interpreter/test lib tool Message-ID: <20050702152239.ADEE327B56@code1.codespeak.net> Author: arigo Date: Sat Jul 2 17:22:35 2005 New Revision: 14102 Added: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_synerr.py (props changed) - copied unchanged from r14080, pypy/dist/pypy/interpreter/test/test_synerr.py Modified: pypy/branch/dist-2.4.1/pypy/lib/_exceptions.py pypy/branch/dist-2.4.1/pypy/tool/_enum_exceptions.py Log: Merged revision 14080 into the 2.4.1 branch. Modified: pypy/branch/dist-2.4.1/pypy/lib/_exceptions.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/_exceptions.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/_exceptions.py Sat Jul 2 17:22:35 2005 @@ -221,50 +221,6 @@ class DeprecationWarning(Warning): """Base class for warnings about deprecated features.""" -class UnicodeEncodeError(UnicodeError): - """Unicode encoding error.""" - - # auto-generated code, please check carefully! - def __init__(self, *args): - argc = len(args) - self.args = args # modified: always assign args, no error check - if argc == 5: - if type(args[0]) == str: - self.encoding = args[0] - else: - raise TypeError('argument 0 must be str, not %s'%type(args[0])) - if type(args[1]) == unicode: - self.object = args[1] - else: - raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) - if type(args[2]) == int: - self.start = args[2] - else: - raise TypeError('argument 2 must be int, not %s'%type(args[2])) - if type(args[3]) == int: - self.end = args[3] - else: - raise TypeError('argument 3 must be int, not %s'%type(args[3])) - if type(args[4]) == str: - self.reason = args[4] - else: - raise TypeError('argument 4 must be str, not %s'%type(args[4])) - else: - raise TypeError('function takes exactly 5 arguments (%d given)'%argc) - - # auto-generated code, please check carefully! - def __str__(self): - # this is a bad hack, please supply an implementation - res = ' '.join([ - 'object=' + str(getattr(self, 'object', None)), - 'end=' + str(getattr(self, 'end', None)), - 'encoding=' + str(getattr(self, 'encoding', None)), - 'args=' + str(getattr(self, 'args', None)), - 'start=' + str(getattr(self, 'start', None)), - 'reason=' + str(getattr(self, 'reason', None)), - ]) - return res - class ArithmeticError(StandardError): """Base class for arithmetic errors.""" @@ -278,7 +234,7 @@ """Name not found globally.""" class OverflowWarning(Warning): - """Base class for warnings about numeric overflow.""" + """Base class for warnings about numeric overflow. Won't exist in Python 2.5.""" class IOError(EnvironmentError): """I/O operation failed.""" @@ -299,19 +255,19 @@ if argc >= 1: self.msg = args[0] if argc == 2: - if type(args[1][0]) == str: + if args[1][0] is None or type(args[1][0]) == str: self.filename = args[1][0] else: raise TypeError('argument 1 must be str, not %s'%type(args[1][0])) - if type(args[1][1]) == str: + if type(args[1][1]) == int: self.lineno = args[1][1] else: raise TypeError('argument 2 must be str, not %s'%type(args[1][1])) - if type(args[1][2]) == str: + if type(args[1][2]) == int: self.offset = args[1][2] else: raise TypeError('argument 3 must be str, not %s'%type(args[1][2])) - if type(args[1][3]) == str: + if args[1][3] is None or type(args[1][3]) == str: self.text = args[1][3] else: raise TypeError('argument 4 must be str, not %s'%type(args[1][3])) @@ -453,5 +409,46 @@ class OverflowError(ArithmeticError): """Result too large to be represented.""" -class WindowsError(OSError): - """MS-Windows OS system call failed.""" +class UnicodeEncodeError(UnicodeError): + """Unicode encoding error.""" + + # auto-generated code, please check carefully! + def __init__(self, *args): + argc = len(args) + self.args = args # modified: always assign args, no error check + if argc == 5: + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == unicode: + self.object = args[1] + else: + raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) + + # auto-generated code, please check carefully! + def __str__(self): + # this is a bad hack, please supply an implementation + res = ' '.join([ + 'object=' + str(getattr(self, 'object', None)), + 'end=' + str(getattr(self, 'end', None)), + 'encoding=' + str(getattr(self, 'encoding', None)), + 'args=' + str(getattr(self, 'args', None)), + 'start=' + str(getattr(self, 'start', None)), + 'reason=' + str(getattr(self, 'reason', None)), + ]) + return res Modified: pypy/branch/dist-2.4.1/pypy/tool/_enum_exceptions.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/tool/_enum_exceptions.py (original) +++ pypy/branch/dist-2.4.1/pypy/tool/_enum_exceptions.py Sat Jul 2 17:22:35 2005 @@ -1,3 +1,6 @@ +# XXX this does not produce a correct _exceptions anymore because the logic to reconstruct +# type checks is broken + # this script is used for extracting # the information available for exceptions # via introspection. From bert at codespeak.net Sat Jul 2 17:57:33 2005 From: bert at codespeak.net (bert at codespeak.net) Date: Sat, 2 Jul 2005 17:57:33 +0200 (CEST) Subject: [pypy-svn] r14103 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702155733.CD5E827B5D@code1.codespeak.net> Author: bert Date: Sat Jul 2 17:57:32 2005 New Revision: 14103 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py Log: (bert,ericvrp): - use distutils instead of hard-coding gcc for llvm2 - this fixes module generation on Mac OS X - also removes hard-coded python2.3 reference Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sat Jul 2 17:57:32 2005 @@ -28,6 +28,8 @@ modname = pyxfile.purebasename b = llvmfile.purebasename + usedistutils = sys.platform == "darwin" + if sys.maxint == 2147483647: #32 bit platform if optimize: ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), @@ -38,8 +40,19 @@ ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b), "as %s.s -o %s.o" % (b, b)] - ops2 = ["gcc -c -shared -I/usr/include/python2.3 %s.c" % pyxfile.purebasename, - "gcc -shared %s.o %s.o -o %s.so" % (b, modname, modname)] + if usedistutils: + open("setup.py", "w").write(str(py.code.Source(''' + from distutils.core import setup + from distutils.extension import Extension + setup(name="%s_wrapper", + ext_modules = [Extension(name = "%s_wrapper", + sources = ["%s_wrapper.c"], + extra_objects = ["%s.o"])]) + ''' % (b, b, b, b)))) + ops2 = ["python setup.py build_ext --inplace"] + else: + ops2 = ["gcc -c -shared -I/usr/include/python2.3 %s.c" % pyxfile.purebasename, + "gcc -shared %s.o %s.o -o %s.so" % (b, modname, modname)] else: #assume 64 bit platform (x86-64?) #this special case for x86-64 (called ia64 in llvm) can go as soon as llc supports ia64 assembly output! if optimize: From bert at codespeak.net Sat Jul 2 18:11:40 2005 From: bert at codespeak.net (bert at codespeak.net) Date: Sat, 2 Jul 2005 18:11:40 +0200 (CEST) Subject: [pypy-svn] r14104 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702161140.6204827B5D@code1.codespeak.net> Author: bert Date: Sat Jul 2 18:11:39 2005 New Revision: 14104 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py Log: (bert,ericvrp): - use compilation via distutils in general, not just for OSX - generate individual test_setup.py files Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sat Jul 2 18:11:39 2005 @@ -28,8 +28,6 @@ modname = pyxfile.purebasename b = llvmfile.purebasename - usedistutils = sys.platform == "darwin" - if sys.maxint == 2147483647: #32 bit platform if optimize: ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), @@ -40,8 +38,7 @@ ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b), "as %s.s -o %s.o" % (b, b)] - if usedistutils: - open("setup.py", "w").write(str(py.code.Source(''' + open("%s_setup.py" % b, "w").write(str(py.code.Source(''' from distutils.core import setup from distutils.extension import Extension setup(name="%s_wrapper", @@ -49,10 +46,7 @@ sources = ["%s_wrapper.c"], extra_objects = ["%s.o"])]) ''' % (b, b, b, b)))) - ops2 = ["python setup.py build_ext --inplace"] - else: - ops2 = ["gcc -c -shared -I/usr/include/python2.3 %s.c" % pyxfile.purebasename, - "gcc -shared %s.o %s.o -o %s.so" % (b, modname, modname)] + ops2 = ["python %s_setup.py build_ext --inplace" % b] else: #assume 64 bit platform (x86-64?) #this special case for x86-64 (called ia64 in llvm) can go as soon as llc supports ia64 assembly output! if optimize: From hpk at codespeak.net Sat Jul 2 18:25:57 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 2 Jul 2005 18:25:57 +0200 (CEST) Subject: [pypy-svn] r14105 - pypy/extradoc/sprintinfo Message-ID: <20050702162557.8207D27B50@code1.codespeak.net> Author: hpk Date: Sat Jul 2 18:25:56 2005 New Revision: 14105 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: status after update meeting Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sat Jul 2 18:25:56 2005 @@ -39,36 +39,33 @@ we decide about pairing at the venue (after everybody tells what he/she is interested in). These are the people expected currently:: - Gustavo Niemeyer until 2nd (including) + Adrien Di Mascio until 4th (including) - Eric van Riet Paap until 8th Carl Friedrich Bolz until 5th afternoon - Richard Emslie whole-time - - Gintas M. until 2nd (including) - Marius Gedminas until 2nd (including) - Mikael Jansson until 3rd (probably) + Richard Emslie whole-time (until 10th) Armin Rigo whole-time + + Mikael Jansson until 2nd (including) Niklaus Haldimann until 4th (including) + Ludovic Aubry until 4th (including) Anders Chrigstroem whole-time (likely) Anders Qvist whole-time (likely) - Ignas M. until 2nd (including) - - Bert Freudenberg whole-time Holger Krekel whole-time - Jacob Hallen whole-time Christian Tismer whole-time - Laura Creighton whole-time - Samuele Pedroni whole-time + Eric van Riet Paap until 8th + Bert Freudenberg whole-time + Marius Gedminas until 2nd (including) + Gintas M. until 2nd (including) + Ignas M. until 2nd (including) Beatrice Duering (visiting, 5th-) Rob Collins until 2nd afternoon #Joe Wrigley until 2nd morning @@ -128,14 +125,20 @@ and the standard library * use lib-python/2.4.1 instead of 2.3.4, review all modified - tests and library modules + tests and library modules (good progress, we still need to + review ca. 25 modified test files) -* semantic differences: comparison of recursive data structures, - more? +* DONE: semantic differences: comparison of recursive + data structures, more? -* new required C-level modules: 'sets', 'collections' +* new required C-level modules: + - MOSTLY DONE: 'sets' + - implement 'collections' module + - (probably) revert 'bisect' module to the 2.3 version (or 2.5) + - (probably) revert 'heapq' module to the 2.3 version (2.5) -* run tests (including compatibility lib-python tests) +* check that test results page still works (and fix) + Misc -------- @@ -145,36 +148,45 @@ Consider distributing the actual annotation to multiple hosts. * (medium) finish objspace/std/longobject.py. + - div implementation (christian, jacob) -* (hard) find a way to generate c_api calls with automated - conversions from ll-strings to c-like strings +* (hard, starting soon to be discussed) find a way + to generate c_api calls (including automated + conversions from ll-strings to c-like strings) * fix Windows-related issues * '%'-formatting rounding errors ( '%.3f' % (2.999999,)) -* add missing docstrings on app-level built-in types and functions, - etc. +* (progressing) add missing docstrings on app-level built-in types and functions, + etc. (Laura): there now is a program that generates the docstrings + into the appropriate places but it needs prettification. + +* (should start sunday) GC discussion in the middle of the sprint + (kickoff Carl Friedrich) -* GC discussion in the middle of the sprint (kickoff Carl Friedrich) - 3rd +* (should start sunday) _sre module reimplementation kickoff Rewriting important C functionality in Python -------------------------------------------------- -* parsing/compiling (Adrien, Gustavo) +* parsing/compiling (Adrien) - * translate to C (fix annotation problems by either + * (PROGRESS): translate to C (fix annotation problems by either tweaking the code or extending the annotator on - a case-by-case basis) - * move towards a rpython compliant (translatable) compiler - -* _sre module reimplementation kickoff + a case-by-case basis). + - (DONE) Parser is fully annotable + - not translated and run in C, yet. + + * (starting, Ludovic, Adrien) move towards a rpython + compliant (translatable) compiler * rewrite in Python a C module you are familiar with - (partial list of missing/incomplete modules: os, math, array, + (partial list of missing/incomplete modules: math, array, regular expressions, binascii...) +* (Jacob, progressing) finish binascii implementation + * implement Python 2.3's import hook extensions (zip-imports etc.) * (hard) weakrefs (but this requires discussion and planning on pypy-dev @@ -184,9 +196,17 @@ LLVM Backend ------------------- -- implement variable sized structs (Richard, Eric / Carl) +- (DONE, eric, bert) make llvm work on osx + +- (PROGRESS, cfbolz, rxe) implement variable + sized structs (Richard, Eric / Carl) + +- (Eric, Bert) more void transformations + +- there are problems with voids all around the flowgraph, + which is being reduced by a cfg transformation -- support function pointers +- DONE: support function pointers - implement exceptions (Carl, Ludovic) From ac at codespeak.net Sat Jul 2 18:30:07 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 2 Jul 2005 18:30:07 +0200 (CEST) Subject: [pypy-svn] r14106 - pypy/branch/dist-2.4.1/pypy/lib Message-ID: <20050702163007.9857127B4A@code1.codespeak.net> Author: ac Date: Sat Jul 2 18:30:07 2005 New Revision: 14106 Modified: pypy/branch/dist-2.4.1/pypy/lib/cmath.py Log: Support second argument to cmath.log(). Modified: pypy/branch/dist-2.4.1/pypy/lib/cmath.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/cmath.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/cmath.py Sat Jul 2 18:30:07 2005 @@ -115,11 +115,13 @@ return complex(real, imag) -def log(x): +def log(x, base=None): """log(x) Return the natural logarithm of x.""" + if base is not None: + return log(x) / log(base) x = complex(x, 0) l = math.hypot(x.real,x.imag) imag = math.atan2(x.imag, x.real) From cfbolz at codespeak.net Sat Jul 2 19:10:52 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 2 Jul 2005 19:10:52 +0200 (CEST) Subject: [pypy-svn] r14107 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702171052.6FFEF27B4E@code1.codespeak.net> Author: cfbolz Date: Sat Jul 2 19:10:51 2005 New Revision: 14107 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/structnode.py Log: Some refactoring of struct mess. (rxe/cfbolz) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jul 2 19:10:51 2005 @@ -71,9 +71,11 @@ elif isinstance(type_, lltype.Ptr): self.prepare_repr_arg_type(type_.TO) - elif isinstance(type_, lltype.Struct): - self.addpending(type_, StructTypeNode(self, type_)) - + elif isinstance(type_, lltype.Struct): + if type_._arrayfld: + self.addpending(type_, StructVarsizeTypeNode(self, type_)) + else: + self.addpending(type_, StructTypeNode(self, type_)) elif isinstance(type_, lltype.FuncType): self.addpending(type_, FuncTypeNode(self, type_)) @@ -103,49 +105,8 @@ for v in self.obj2node.values(): if subset_types is None or isinstance(v, subset_types): res.append(v) - res.reverse() return res - def get_typedecls(self): - return self.getobjects((StructTypeNode, ArrayTypeNode, FuncTypeNode)) - - def get_globaldata(self): - return self.getobjects((StructNode, ArrayNode)) - - def get_functions(self): - struct_nodes = [n for n in self.getobjects(StructTypeNode) if n.inline_struct] - return struct_nodes + self.getobjects(FuncNode) - - def dump(self): - - # get and reverse the order in which seen objs - all_objs = self.obj2node.items() - all_objs.reverse() - - log.dump_db("*** type declarations ***") - for k,v in all_objs: - if isinstance(v, (StructTypeNode, ArrayTypeNode)): - log.dump_db("%s ---> %s" % (k, v)) - - log.dump_db("*** global data ***") - for k,v in all_objs: - if isinstance(v, (StructNode)): - log.dump_db("%s ---> %s" % (k, v)) - - log.dump_db("*** function protos ***") - for k,v in all_objs: - if isinstance(v, (FuncNode)): - log.dump_db("%s ---> %s" % (k, v)) - - log.dump_db("*** function implementations ***") - for k,v in all_objs: - if isinstance(v, (FuncNode)): - log.dump_db("%s ---> %s" % (k, v)) - - log.dump_db("*** unknown ***") - for k,v in all_objs: - if isinstance(v, (FuncTypeNode)): - log.dump_db("%s ---> %s" % (k, v)) # __________________________________________________________ # Getters Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 2 19:10:51 2005 @@ -26,20 +26,20 @@ nl = codewriter.newline nl(); comment("Type Declarations"); nl() - for typ_decl in db.get_typedecls(): + for typ_decl in db.getobjects(): typ_decl.writedatatypedecl(codewriter) nl(); comment("Global Data") ; nl() - for typ_decl in db.get_globaldata(): + for typ_decl in db.getobjects(): typ_decl.writedata(codewriter) nl(); comment("Function Prototypes") ; nl() - for typ_decl in db.get_functions(): + for typ_decl in db.getobjects(): typ_decl.writedecl(codewriter) nl(); comment("Function Implementation") codewriter.startimpl() - for typ_decl in db.get_functions(): + for typ_decl in db.getobjects(): typ_decl.writeimpl(codewriter) comment("End of file") ; nl() Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Sat Jul 2 19:10:51 2005 @@ -7,3 +7,15 @@ (self._ref,)) self._ref = ref ref = property(_get_ref, _set_ref) + + def writedatatypedecl(self, codewriter): + pass + + def writedata(self, codewriter): + pass + + def writedecl(self, codewriter): + pass + + def writeimpl(self, codewriter): + pass Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 2 19:10:51 2005 @@ -1,23 +1,21 @@ import py from pypy.objspace.flow.model import Block, Constant, Variable, Link -from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.node import LLVMNode from pypy.rpython import lltype + log = log.structnode -class StructTypeNode(object): +class StructTypeNode(LLVMNode): _issetup = False struct_counter = 0 def __init__(self, db, struct): assert isinstance(struct, lltype.Struct) - self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name, StructTypeNode.struct_counter) self.ref = "%%st.%s" % self.name - self.inline_struct = self.struct._arrayfld - StructTypeNode.struct_counter += 1 def __str__(self): @@ -25,66 +23,64 @@ def setup(self): # Recurse - for fieldname in self.struct._names: - field_type = getattr(self.struct, fieldname) - self.db.prepare_repr_arg_type(field_type) + for field in self.struct._flds: + self.db.prepare_repr_arg_type(field) self._issetup = True - def get_decl_for_varsize(self): - self.new_var_name = "%%new.st.%s" % self.name - return "%s * %s(int %%len)" % (self.ref, self.new_var_name) - # ______________________________________________________________________ # main entry points from genllvm def writedatatypedecl(self, codewriter): assert self._issetup - struct = self.struct - l = [] - for fieldname in struct._names: - type_ = getattr(struct, fieldname) - l.append(self.db.repr_arg_type(type_)) - codewriter.structdef(self.ref, l) - + # cfbolz: XXX flds has no order + #l = [self.db.repr_arg_type(field) for field in self.struct._flds.values()] + fields = [getattr(self.struct, name) for name in self.struct._names] + l = [self.db.repr_arg_type(field) for field in fields] + codewriter.structdef(self.ref, l) + +class StructVarsizeTypeNode(StructTypeNode): + def __init__(self, type_): + super(self, StructVarsizeTypeNode).__init__(type_) + new_var_name = "%%new.st.var.%s" % self.name + self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + def writedecl(self, codewriter): # declaration for constructor - if self.inline_struct: - # XXX Not well thought out - hack / better to modify the graph - codewriter.declare(self.get_decl_for_varsize()) + codewriter.declare(self.constructor_name) def writeimpl(self, codewriter): - if self.inline_struct: - log.writeimpl(self.ref) - codewriter.openfunc(self.get_decl_for_varsize()) - codewriter.label("block0") - - # XXX TODO - arraytype = "sbyte" - indices_to_array = [("uint", 1)] - - # Into array and length - indices = indices_to_array + [("uint", 1), ("int", "%len")] - codewriter.getelementptr("%size", self.ref + "*", - "null", *indices) - - #XXX is this ok for 64bit? - codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") - codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") - - # remember the allocated length for later use. - indices = indices_to_array + [("uint", 0)] - codewriter.getelementptr("%size_ptr", self.ref + "*", - "%result", *indices) - - codewriter.cast("%signedsize", "uint", "%sizeu", "int") - codewriter.store("int", "%signedsize", "%size_ptr") + log.writeimpl(self.ref) + codewriter.openfunc(self.constructor_name) + codewriter.label("block0") + indices_to_array = [("int", 0)] + s = self.struct + while isintance(s, lltypes.Struct): + last_pos = len(self.struct._names) - 1 + indices_to_array.append(("uint", last_pos)) + s = s._flds.values()[-1] + + # Into array and length + indices = indices_to_array + [("uint", 1), ("int", "%len")] + codewriter.getelementptr("%size", self.ref + "*", + "null", *indices) + + #XXX is this ok for 64bit? + codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") + codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") + codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") + + # remember the allocated length for later use. + indices = indices_to_array + [("uint", 0)] + codewriter.getelementptr("%size_ptr", self.ref + "*", + "%result", *indices) - codewriter.ret(self.ref + "*", "%result") - codewriter.closefunc() + codewriter.cast("%signedsize", "uint", "%sizeu", "int") + codewriter.store("int", "%signedsize", "%size_ptr") + codewriter.ret(self.ref + "*", "%result") + codewriter.closefunc() -class StructNode(object): +class StructNode(LLVMNode): _issetup = False struct_counter = 0 From rxe at codespeak.net Sat Jul 2 19:19:35 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 2 Jul 2005 19:19:35 +0200 (CEST) Subject: [pypy-svn] r14108 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702171935.F314A27B4E@code1.codespeak.net> Author: rxe Date: Sat Jul 2 19:19:34 2005 New Revision: 14108 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/structnode.py Log: Fixes to the bugs the refactoring introduced. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jul 2 19:19:34 2005 @@ -1,6 +1,6 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode -from pypy.translator.llvm2.structnode import StructNode, StructTypeNode +from pypy.translator.llvm2.structnode import StructNode, StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 2 19:19:34 2005 @@ -39,8 +39,9 @@ codewriter.structdef(self.ref, l) class StructVarsizeTypeNode(StructTypeNode): - def __init__(self, type_): - super(self, StructVarsizeTypeNode).__init__(type_) + + def __init__(self, db, struct): + super(StructVarsizeTypeNode, self).__init__(db, struct) new_var_name = "%%new.st.var.%s" % self.name self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) From rxe at codespeak.net Sat Jul 2 19:25:58 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 2 Jul 2005 19:25:58 +0200 (CEST) Subject: [pypy-svn] r14109 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702172558.7754527B41@code1.codespeak.net> Author: rxe Date: Sat Jul 2 19:25:57 2005 New Revision: 14109 Modified: pypy/dist/pypy/translator/llvm2/structnode.py Log: Cosmetic. Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 2 19:25:57 2005 @@ -32,8 +32,6 @@ def writedatatypedecl(self, codewriter): assert self._issetup - # cfbolz: XXX flds has no order - #l = [self.db.repr_arg_type(field) for field in self.struct._flds.values()] fields = [getattr(self.struct, name) for name in self.struct._names] l = [self.db.repr_arg_type(field) for field in fields] codewriter.structdef(self.ref, l) From bert at codespeak.net Sat Jul 2 20:07:34 2005 From: bert at codespeak.net (bert at codespeak.net) Date: Sat, 2 Jul 2005 20:07:34 +0200 (CEST) Subject: [pypy-svn] r14110 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702180734.1D5EB27B45@code1.codespeak.net> Author: bert Date: Sat Jul 2 20:07:34 2005 New Revision: 14110 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py Log: (bert): - use distutil compiling instead of gcc for x86-64, too Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sat Jul 2 20:07:34 2005 @@ -20,6 +20,21 @@ OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline" +def compile_module(module, source_files, object_files): + open("%s_setup.py" % module, "w").write(str(py.code.Source( + ''' + from distutils.core import setup + from distutils.extension import Extension + setup(name="%(module)s", + ext_modules = [Extension( + name = "%(module)s", + sources = %(source_files)s, + extra_objects = %(object_files)s)]) + ''' % locals()))) + cmd = "python %s_setup.py build_ext --inplace" % module + if debug: print cmd + cmdexec(cmd) + def make_module_from_llvm(llvmfile, pyxfile, optimize=False): include_dir = py.magic.autopath().dirpath() dirpath = llvmfile.dirpath() @@ -27,36 +42,29 @@ os.chdir(str(dirpath)) modname = pyxfile.purebasename b = llvmfile.purebasename + source_files = [ "%s.c" % modname ] + object_files = [] if sys.maxint == 2147483647: #32 bit platform if optimize: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), - "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b), - "as %s.s -o %s.o" % (b, b)] + "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b)] else: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), - "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b), - "as %s.s -o %s.o" % (b, b)] - open("%s_setup.py" % b, "w").write(str(py.code.Source(''' - from distutils.core import setup - from distutils.extension import Extension - setup(name="%s_wrapper", - ext_modules = [Extension(name = "%s_wrapper", - sources = ["%s_wrapper.c"], - extra_objects = ["%s.o"])]) - ''' % (b, b, b, b)))) - ops2 = ["python %s_setup.py build_ext --inplace" % b] + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b)] + cmds.append("as %s.s -o %s.o" % (b, b)) + object_files.append("%s.o" % b) else: #assume 64 bit platform (x86-64?) #this special case for x86-64 (called ia64 in llvm) can go as soon as llc supports ia64 assembly output! if optimize: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), "llc -enable-correct-eh-support %s_optimized.bc -march=c -f -o %s.c" % (b, b)] else: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "llc -enable-correct-eh-support %s.bc -march=c -f -o %s.c" % (b, b)] - ops2 = ["gcc -shared -fPIC -I/usr/include/python2.3 %s.c %s.c -o %s.so" % (b, modname, modname)] + source_files.append("%s.c" % b) try: if debug: print "modname", modname @@ -64,13 +72,11 @@ if debug: print "working in", path.local() try: try: - for op in ops1: - if debug: print op - cmdexec(op) + for cmd in cmds: + if debug: print cmd + cmdexec(cmd) make_c_from_pyxfile(pyxfile) - for op in ops2: - if debug: print op - cmdexec(op) + compile_module(modname, source_files, object_files) finally: foutput, foutput = c.done() except: From ericvrp at codespeak.net Sat Jul 2 20:26:42 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 2 Jul 2005 20:26:42 +0200 (CEST) Subject: [pypy-svn] r14111 - pypy/dist/pypy/rpython Message-ID: <20050702182642.CF12A27B45@code1.codespeak.net> Author: ericvrp Date: Sat Jul 2 20:26:41 2005 New Revision: 14111 Modified: pypy/dist/pypy/rpython/lltype.py Log: Added helper function to get rid of Voids in struct (for llvm2 now) note: no testcase for this yet! Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sat Jul 2 20:26:41 2005 @@ -4,6 +4,8 @@ from pypy.tool.uid import Hashable from pypy.tool.tls import tlsobject +log = py.log.Producer('lltype') + TLS = tlsobject() def saferecursive(func, defl): @@ -141,6 +143,30 @@ raise AttributeError, 'struct %s has no field %r' % (self._name, name) + + + + def _names_without_voids(self, at_root=True): + if at_root: #XXX debug stuff + log('_names_without_voids: ' + self._str_without_voids()) + names_without_voids = [name for name in self._names if self._flds[name] is not Void] + if names_without_voids != list(self._names): + log('_names_without_voids: removed Void(s) _names=%s, return=%s' % (str(list(self._names)), str(names_without_voids))) + #return self._names + return names_without_voids + + def _str_fields_without_voids(self): + return ', '.join(['%s: %s' % (name, self._flds[name]) + for name in self._names_without_voids(False)]) + _str_fields_without_voids = saferecursive(_str_fields_without_voids, '...') + + def _str_without_voids(self): + return "%s %s { %s }" % (self.__class__.__name__, + self._name, self._str_fields_without_voids()) + + + + def _str_fields(self): return ', '.join(['%s: %s' % (name, self._flds[name]) for name in self._names]) From ericvrp at codespeak.net Sat Jul 2 20:28:01 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 2 Jul 2005 20:28:01 +0200 (CEST) Subject: [pypy-svn] r14112 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050702182801.7E96F27B45@code1.codespeak.net> Author: ericvrp Date: Sat Jul 2 20:28:00 2005 New Revision: 14112 Modified: pypy/dist/pypy/translator/llvm2/structnode.py Log: using helper to get rid of Voids in structs Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 2 20:28:00 2005 @@ -32,7 +32,7 @@ def writedatatypedecl(self, codewriter): assert self._issetup - fields = [getattr(self.struct, name) for name in self.struct._names] + fields = [getattr(self.struct, name) for name in self.struct._names_without_voids()] l = [self.db.repr_arg_type(field) for field in fields] codewriter.structdef(self.ref, l) @@ -54,7 +54,7 @@ indices_to_array = [("int", 0)] s = self.struct while isintance(s, lltypes.Struct): - last_pos = len(self.struct._names) - 1 + last_pos = len(self.struct._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) s = s._flds.values()[-1] @@ -94,8 +94,9 @@ return "" %(self.ref,) def setup(self): - for name in self.value._TYPE._names: + for name in self.value._TYPE._names_without_voids(): T = self.value._TYPE._flds[name] + assert T is not lltype.Void if not isinstance(T, lltype.Primitive): value = getattr(self.value, name) # Create a dummy constant hack XXX @@ -106,7 +107,7 @@ def get_values(self): res = [] - for name in self.value._TYPE._names: + for name in self.value._TYPE._names_without_voids(): T = self.value._TYPE._flds[name] value = getattr(self.value, name) if not isinstance(T, lltype.Primitive): From gintas at codespeak.net Sat Jul 2 20:33:15 2005 From: gintas at codespeak.net (gintas at codespeak.net) Date: Sat, 2 Jul 2005 20:33:15 +0200 (CEST) Subject: [pypy-svn] r14113 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050702183315.90D9E27B45@code1.codespeak.net> Author: gintas Date: Sat Jul 2 20:33:14 2005 New Revision: 14113 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_base64.py - copied, changed from r14110, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_base64.py Log: Overrode test_base64.py to work with py.test. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_base64.py (from r14110, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_base64.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_base64.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_base64.py Sat Jul 2 20:33:14 2005 @@ -189,4 +189,4 @@ if __name__ == '__main__': - unittest.main(defaultTest='suite') + test_main() From ericvrp at codespeak.net Sat Jul 2 20:33:45 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 2 Jul 2005 20:33:45 +0200 (CEST) Subject: [pypy-svn] r14114 - pypy/dist/pypy/translator/test Message-ID: <20050702183345.0EEC727B45@code1.codespeak.net> Author: ericvrp Date: Sat Jul 2 20:33:44 2005 New Revision: 14114 Modified: pypy/dist/pypy/translator/test/test_backendoptimization.py Log: (failed) attempt to create a structure with voids in it. Who wants/can improve this? Modified: pypy/dist/pypy/translator/test/test_backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/test/test_backendoptimization.py (original) +++ pypy/dist/pypy/translator/test/test_backendoptimization.py Sat Jul 2 20:33:44 2005 @@ -3,6 +3,11 @@ from pypy.rpython.lltype import Void from pypy.rpython.llinterp import LLInterpreter from pypy.objspace.flow.model import checkgraph +from pypy.translator.test.snippet import simple_method +from pypy.translator.llvm2.log import log + +import py +log = py.log.Producer('test_backendoptimization') def annotate_and_remove_void(f, annotate): t = Translator(f) @@ -22,3 +27,18 @@ interp = LLInterpreter(t.flowgraphs, t.rtyper) assert interp.eval_function(f, [0]) == 1 +def test_remove_void_in_struct(): + t = annotate_and_remove_void(simple_method, [int]) + #t.view() + log(t.flowgraphs.iteritems()) + for func, graph in t.flowgraphs.iteritems(): + log('func : ' + str(func)) + log('graph: ' + str(graph)) + assert checkgraph(graph) is None + #for fieldname in self.struct._names: #XXX helper (in lltype?) should remove these voids + # type_ = getattr(struct, fieldname) + # log('fieldname=%(fieldname)s , type_=%(type_)s' % locals()) + # assert _type is not Void + #interp = LLInterpreter(t.flowgraphs, t.rtyper) + #assert interp.eval_function(f, [0]) == 1 + From adim at codespeak.net Sun Jul 3 11:36:18 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 11:36:18 +0200 (CEST) Subject: [pypy-svn] r14115 - in pypy/dist/pypy/interpreter/pyparser: . data test test/samples Message-ID: <20050703093618.6537527B42@code1.codespeak.net> Author: adim Date: Sun Jul 3 11:36:11 2005 New Revision: 14115 Added: pypy/dist/pypy/interpreter/pyparser/ pypy/dist/pypy/interpreter/pyparser/automata.py - copied unchanged from r14092, pypy/dist/pypy/module/recparser/automata.py pypy/dist/pypy/interpreter/pyparser/data/ - copied from r14092, pypy/dist/pypy/module/recparser/data/ pypy/dist/pypy/interpreter/pyparser/data/Grammar2.3 - copied unchanged from r14114, pypy/dist/pypy/module/recparser/data/Grammar2.3 pypy/dist/pypy/interpreter/pyparser/data/Grammar2.4 - copied unchanged from r14114, pypy/dist/pypy/module/recparser/data/Grammar2.4 pypy/dist/pypy/interpreter/pyparser/ebnflexer.py - copied unchanged from r14092, pypy/dist/pypy/module/recparser/ebnflexer.py pypy/dist/pypy/interpreter/pyparser/ebnfparse.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py - copied unchanged from r14092, pypy/dist/pypy/module/recparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/pythonutil.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/pythonutil.py pypy/dist/pypy/interpreter/pyparser/pytokenize.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/pytokenize.py pypy/dist/pypy/interpreter/pyparser/syntaxtree.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/syntaxtree.py pypy/dist/pypy/interpreter/pyparser/test/ - copied from r14092, pypy/dist/pypy/module/recparser/test/ pypy/dist/pypy/interpreter/pyparser/test/samples/ - copied from r14114, pypy/dist/pypy/module/recparser/test/samples/ pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/test_lookahead.py pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py - copied, changed from r14114, pypy/dist/pypy/module/recparser/test/test_pytokenizer.py pypy/dist/pypy/interpreter/pyparser/test/test_samples.py - copied, changed from r14114, pypy/dist/pypy/module/recparser/test/test_samples.py pypy/dist/pypy/interpreter/pyparser/test/unittest_samples.py - copied, changed from r14114, pypy/dist/pypy/module/recparser/test/unittest_samples.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py - copied, changed from r14092, pypy/dist/pypy/module/recparser/tuplebuilder.py Log: moved recparser's core into interpreter/pyparser Copied: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (from r14092, pypy/dist/pypy/module/recparser/ebnfparse.py) ============================================================================== --- pypy/dist/pypy/module/recparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Sun Jul 3 11:36:11 2005 @@ -53,15 +53,7 @@ return 0 def match_token(self, other): - """convenience '==' implementation, this is *not* a *real* equality test - a Token instance can be compared to: - - another Token instance in which case all fields (name and value) - must be equal - - a tuple, such as those yielded by the Python lexer, in which case - the comparison algorithm is similar to the one in match() - XXX: - 1/ refactor match and __eq__ ? - 2/ make source.next and source.peek return a Token() instance + """special case of match token for tokens which are really keywords """ if not isinstance(other, Token): raise RuntimeError("Unexpected token type %r" % other) Copied: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (from r14092, pypy/dist/pypy/module/recparser/pythonlexer.py) ============================================================================== --- pypy/dist/pypy/module/recparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Sun Jul 3 11:36:11 2005 @@ -119,7 +119,8 @@ if contstr: # continued string if not line: - raise TokenError("EOF in multi-line string", strstart, token_list) + raise TokenError("EOF in multi-line string", strstart, + token_list) endmatch = endDFA.recognize(line) if -1 != endmatch: pos = end = endmatch @@ -166,8 +167,10 @@ else: tok = token_from_values(tokenmod.NL, line[pos:]) last_comment = '' - # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line)) - # token_list.append(((NL, COMMENT)[line[pos] == '#'], line[pos:], + # XXX Skip NL and COMMENT Tokens + # token_list.append((tok, line)) + # token_list.append(((NL, COMMENT)[line[pos] == '#'], + # line[pos:], # (lnum, pos), (lnum, len(line)), line)) continue @@ -176,13 +179,13 @@ tok = token_from_values(tokenmod.INDENT, line[:pos]) token_list.append((tok, line)) last_comment = '' - # token_list.append((INDENT, line[:pos], (lnum, 0), (lnum, pos), line)) + # token_list.append((INDENT, line[:pos],(lnum, 0),(lnum,pos),line)) while column < indents[-1]: indents = indents[:-1] tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line)) last_comment = '' - # token_list.append((DEDENT, '', (lnum, pos), (lnum, pos), line)) + # token_list.append((DEDENT, '', (lnum, pos),(lnum,pos),line)) else: # continued statement if not line: @@ -305,6 +308,7 @@ self.stack_pos = 0 def next(self): + """Returns the next parsed token""" if self.stack_pos >= len(self.token_stack): raise StopIteration("Remove me") tok, line = self.token_stack[self.stack_pos] @@ -313,12 +317,15 @@ return tok def current_line(self): + """Returns the current line being parsed""" return self._current_line def context(self): + """Returns an opaque context object for later restore""" return self.stack_pos def restore(self, ctx): + """Restores a context""" self.stack_pos = ctx def peek(self): Copied: pypy/dist/pypy/interpreter/pyparser/pythonparse.py (from r14092, pypy/dist/pypy/module/recparser/pythonparse.py) ============================================================================== --- pypy/dist/pypy/module/recparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Sun Jul 3 11:36:11 2005 @@ -34,6 +34,7 @@ builder.source_encoding = src.encoding # if not result: + raise SyntaxError("...") return None # raise SyntaxError("at %s" % src.debug() ) return builder Copied: pypy/dist/pypy/interpreter/pyparser/pythonutil.py (from r14092, pypy/dist/pypy/module/recparser/pythonutil.py) ============================================================================== --- pypy/dist/pypy/module/recparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Sun Jul 3 11:36:11 2005 @@ -1,7 +1,6 @@ -__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", +__all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", "ast_eval_input" ] -import grammar import pythonparse from compiler.transformer import Transformer from tuplebuilder import TupleBuilder @@ -33,8 +32,9 @@ pyf.close() builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) # make the annotator life easier - strings = [line+'\n' for line in text.split('\n')] - pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + strings = [line + '\n' for line in text.split('\n')] + pythonparse.parse_python_source(strings, PYTHON_PARSER, + 'file_input', builder) nested_tuples = builder.stack[-1] if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) Copied: pypy/dist/pypy/interpreter/pyparser/pytokenize.py (from r14092, pypy/dist/pypy/module/recparser/pytokenize.py) ============================================================================== --- pypy/dist/pypy/module/recparser/pytokenize.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pytokenize.py Sun Jul 3 11:36:11 2005 @@ -20,7 +20,6 @@ # ______________________________________________________________________ from __future__ import generators -import string import automata # ______________________________________________________________________ Copied: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (from r14092, pypy/dist/pypy/module/recparser/syntaxtree.py) ============================================================================== --- pypy/dist/pypy/module/recparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Sun Jul 3 11:36:11 2005 @@ -1,3 +1,4 @@ +"""SyntaxTree class definition""" import symbol import token @@ -65,7 +66,7 @@ SYMBOLS = {} # copies the numerical mapping between symbol name and symbol value # into SYMBOLS -for k,v in symbol.sym_name.items(): +for k, v in symbol.sym_name.items(): SYMBOLS[v] = k SYMBOLS['UNKNOWN'] = -1 @@ -78,6 +79,7 @@ self.lineno = source.current_line() def dumptree(self, treenodes, indent): + """helper function used to dump the syntax tree""" treenodes.append(self.name) if len(self.nodes) > 1: treenodes.append(" -> (\n") @@ -92,6 +94,7 @@ self.nodes[0].dumptree(treenodes, indent+" ") def dumpstr(self): + """turns the tree repr into a string""" treenodes = [] self.dumptree(treenodes, "") return "".join(treenodes) @@ -113,9 +116,13 @@ raise RuntimeError("Unknonw Visitor for %r" % self.name) def expand(self): + """expand the syntax node to its content, + do nothing here since we are a regular node and not + a TempSyntaxNode""" return [ self ] def totuple(self, lineno=False ): + """returns a tuple representation of the syntax tree""" symvalue = SYMBOLS.get( self.name, (0, self.name) ) l = [ symvalue ] l += [node.totuple(lineno) for node in self.nodes] @@ -125,6 +132,7 @@ class TempSyntaxNode(SyntaxNode): """A temporary syntax node to represent intermediate rules""" def expand(self): + """expand the syntax node to its content""" return self.nodes class TokenNode(SyntaxNode): @@ -134,8 +142,10 @@ self.value = value def dumptree(self, treenodes, indent): + """helper function used to dump the syntax tree""" if self.value: - treenodes.append("%s='%s' (%d) " % (self.name, self.value, self.lineno)) + treenodes.append("%s='%s' (%d) " % (self.name, self.value, + self.lineno)) else: treenodes.append("'%s' (%d) " % (self.name, self.lineno)) @@ -146,6 +156,7 @@ return "<%s!>" % (self.name,) def totuple(self, lineno=False): + """returns a tuple representation of the syntax tree""" num = TOKEN_MAP.get(self.name, -1) if num == -1: print "Unknown", self.name, self.value Copied: pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py (from r14092, pypy/dist/pypy/module/recparser/test_lookahead.py) ============================================================================== --- pypy/dist/pypy/module/recparser/test_lookahead.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py Sun Jul 3 11:36:11 2005 @@ -1,4 +1,4 @@ -from pypy.module.recparser.grammar import Alternative, Sequence, KleenStar, \ +from pypy.interpreter.pyparser.grammar import Alternative, Sequence, KleenStar, \ Token, EmptyToken, build_first_sets class TestLookAheadBasics: Copied: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py (from r14114, pypy/dist/pypy/module/recparser/test/test_pytokenizer.py) ============================================================================== --- pypy/dist/pypy/module/recparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Sun Jul 3 11:36:11 2005 @@ -1,6 +1,6 @@ -from pypy.module.recparser.pythonlexer import Source, TokenError, \ +from pypy.interpreter.pyparser.pythonlexer import Source, TokenError, \ match_encoding_declaration -from pypy.module.recparser.grammar import Token +from pypy.interpreter.pyparser.grammar import Token def parse_source(source): """returns list of parsed tokens""" Copied: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (from r14114, pypy/dist/pypy/module/recparser/test/test_samples.py) ============================================================================== --- pypy/dist/pypy/module/recparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Sun Jul 3 11:36:11 2005 @@ -1,9 +1,9 @@ """test module for CPython / PyPy nested tuples comparison""" import os, os.path as osp -from pypy.module.recparser.pythonutil import python_parse, pypy_parse +from pypy.interpreter.pyparser.pythonutil import python_parse, pypy_parse # from pypy.module.recparser.pythonparse import pypy_parse from pprint import pprint -from pypy.module.recparser import grammar +from pypy.interpreter.pyparser import grammar grammar.DEBUG = False from symbol import sym_name Copied: pypy/dist/pypy/interpreter/pyparser/test/unittest_samples.py (from r14114, pypy/dist/pypy/module/recparser/test/unittest_samples.py) ============================================================================== --- pypy/dist/pypy/module/recparser/test/unittest_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/unittest_samples.py Sun Jul 3 11:36:11 2005 @@ -2,9 +2,9 @@ import os, os.path as osp import sys -from pypy.module.recparser.pythonutil import python_parse, pypy_parse +from pypy.interpreter.pyparser.pythonutil import python_parse, pypy_parse from pprint import pprint -from pypy.module.recparser import grammar +from pypy.interpreter.pyparser import grammar grammar.DEBUG = False from symbol import sym_name Copied: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (from r14092, pypy/dist/pypy/module/recparser/tuplebuilder.py) ============================================================================== --- pypy/dist/pypy/module/recparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Sun Jul 3 11:36:11 2005 @@ -2,24 +2,6 @@ from grammar import BaseGrammarBuilder from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET -## -## def _expand_nodes(nodes): -## expanded = [] -## for n in nodes: -## if n[0] == -2: -## # expanded.extend(expand_nodes(n[1:])) -## expanded.extend(n[1:]) -## else: -## expanded.append(n) -## return tuple(expanded) -## -## def expand_nodes(nodes): -## r = _expand_nodes(nodes) -## for n in nodes: -## assert type(n[0]) == int -## return r -## - class StackElement: """wraps TupleBuilder's tuples""" From adim at codespeak.net Sun Jul 3 11:38:46 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 11:38:46 +0200 (CEST) Subject: [pypy-svn] r14116 - in pypy/dist/pypy/module/recparser: . data test Message-ID: <20050703093846.1CBB627B42@code1.codespeak.net> Author: adim Date: Sun Jul 3 11:38:44 2005 New Revision: 14116 Removed: pypy/dist/pypy/module/recparser/automata.py pypy/dist/pypy/module/recparser/data/ pypy/dist/pypy/module/recparser/ebnflexer.py pypy/dist/pypy/module/recparser/ebnfparse.py pypy/dist/pypy/module/recparser/grammar.py pypy/dist/pypy/module/recparser/pythonlexer.py pypy/dist/pypy/module/recparser/pythonparse.py pypy/dist/pypy/module/recparser/pythonutil.py pypy/dist/pypy/module/recparser/pytokenize.py pypy/dist/pypy/module/recparser/syntaxtree.py pypy/dist/pypy/module/recparser/test/ pypy/dist/pypy/module/recparser/test_lookahead.py pypy/dist/pypy/module/recparser/tuplebuilder.py Modified: pypy/dist/pypy/module/recparser/compat.py Log: these files have been moved to interpreter/pyparser Deleted: /pypy/dist/pypy/module/recparser/automata.py ============================================================================== --- /pypy/dist/pypy/module/recparser/automata.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,89 +0,0 @@ -#! /usr/bin/env python -# ______________________________________________________________________ -"""Module automata - -THIS FILE WAS COPIED FROM pypy/module/parser/pytokenize.py AND ADAPTED -TO BE ANNOTABLE (Mainly made the DFA's __init__ accept two lists -instead of a unique nested one) - -$Id: automata.py,v 1.2 2003/10/02 17:37:17 jriehl Exp $ -""" -# ______________________________________________________________________ -# Module level definitions - -# PYPY Modification: removed the EMPTY class as it's not needed here - - -# PYPY Modification: we don't need a particuliar DEFAULT class here -# a simple None works fine. -# (Having a DefaultClass inheriting from str makes -# the annotator crash) -DEFAULT = None -# PYPY Modification : removed all automata functions (any, maybe, -# newArcPair, etc.) - -class DFA: - # ____________________________________________________________ - def __init__(self, states, accepts, start = 0): - self.states = states - self.accepts = accepts - self.start = start - - # ____________________________________________________________ - def recognize (self, inVec, pos = 0, greedy = True): - crntState = self.start - i = pos - lastAccept = False - for item in inVec[pos:]: - # arcMap, accept = self.states[crntState] - arcMap = self.states[crntState] - accept = self.accepts[crntState] - if item in arcMap: - crntState = arcMap[item] - elif DEFAULT in arcMap: - crntState = arcMap[DEFAULT] - elif accept: - return i - elif lastAccept: - # This is now needed b/c of exception cases where there are - # transitions to dead states - return i - 1 - else: - return -1 - lastAccept = accept - i += 1 - # if self.states[crntState][1]: - if self.accepts[crntState]: - return i - elif lastAccept: - return i - 1 - else: - return -1 - -# ______________________________________________________________________ - -class NonGreedyDFA (DFA): - def recognize (self, inVec, pos = 0): - crntState = self.start - i = pos - for item in inVec[pos:]: - # arcMap, accept = self.states[crntState] - arcMap = self.states[crntState] - accept = self.accepts[crntState] - if accept: - return i - elif item in arcMap: - crntState = arcMap[item] - elif DEFAULT in arcMap: - crntState = arcMap[DEFAULT] - else: - return -1 - i += 1 - # if self.states[crntState][1]: - if self.accepts[crntState]: - return i - else: - return -1 - -# ______________________________________________________________________ -# End of automata.py Modified: pypy/dist/pypy/module/recparser/compat.py ============================================================================== --- pypy/dist/pypy/module/recparser/compat.py (original) +++ pypy/dist/pypy/module/recparser/compat.py Sun Jul 3 11:38:44 2005 @@ -3,14 +3,26 @@ from pythonparse import parse_python_source from pythonutil import PYTHON_PARSER from compiler import transformer, compile as pycompile - + def suite( source ): - builder = parse_python_source( source, PYTHON_PARSER, "file_input" ) - return builder.stack[-1] + strings = [line+'\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) + nested_tuples = builder.stack[-1].as_tuple() + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + return nested_tuples def expr( source ): - builder = parse_python_source( source, PYTHON_PARSER, "eval_input" ) - return builder.stack[-1] + strings = [line+'\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) + nested_tuples = builder.stack[-1].as_tuple() + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + return nested_tuples def ast2tuple(node, line_info=False): """Quick dummy implementation of parser.ast2tuple(tree) function""" Deleted: /pypy/dist/pypy/module/recparser/ebnflexer.py ============================================================================== --- /pypy/dist/pypy/module/recparser/ebnflexer.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,83 +0,0 @@ -"""This is a lexer for a Python recursive descent parser -it obeys the TokenSource interface defined for the grammar -analyser in grammar.py -""" - -import re -from grammar import TokenSource, Token - -DEBUG = False - -## Lexer for Python's grammar ######################################## -g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:",re.M) -g_symbol = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*",re.M) -g_string = re.compile(r"'[^']+'",re.M) -g_tok = re.compile(r"\[|\]|\(|\)|\*|\+|\|",re.M) -g_skip = re.compile(r"\s*(#.*$)?",re.M) - -class GrammarSource(TokenSource): - """The grammar tokenizer""" - def __init__(self, inpstring ): - TokenSource.__init__(self) - self.input = inpstring - self.pos = 0 - self._peeked = None - - def context(self): - return self.pos, self._peeked - - def offset(self, ctx=None): - if ctx is None: - return self.pos - else: - assert type(ctx)==int - return ctx - - def restore(self, ctx): - self.pos, self._peeked = ctx - - def next(self): - if self._peeked is not None: - peeked = self._peeked - self._peeked = None - return peeked - - pos = self.pos - inp = self.input - m = g_skip.match(inp, pos) - while m and pos!=m.end(): - pos = m.end() - if pos==len(inp): - self.pos = pos - return Token("EOF", None) - m = g_skip.match(inp, pos) - m = g_symdef.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return Token('SYMDEF',tk[:-1]) - m = g_tok.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return Token(tk,tk) - m = g_string.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return Token('STRING',tk[1:-1]) - m = g_symbol.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return Token('SYMBOL',tk) - raise ValueError("Unknown token at pos=%d context='%s'" % (pos,inp[pos:pos+20]) ) - - def peek(self): - if self._peeked is not None: - return self._peeked - self._peeked = self.next() - return self._peeked - - def debug(self): - return self.input[self.pos:self.pos+20] Deleted: /pypy/dist/pypy/module/recparser/ebnfparse.py ============================================================================== --- /pypy/dist/pypy/module/recparser/ebnfparse.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,277 +0,0 @@ -#!/usr/bin/env python -from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ - KleenStar, GrammarElement, build_first_sets, EmptyToken -from ebnflexer import GrammarSource - -import re -py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) - -punct=['>=', '<>', '!=', '<', '>', '<=', '==', '\\*=', - '//=', '%=', '^=', '<<=', '\\*\\*=', '\\', '=', - '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', '@', '\\[', '\\]', '`', '\\{', '\\}'] - -py_punct = re.compile(r""" ->=|<>|!=|<|>|<=|==|~| -\*=|//=|%=|\^=|<<=|\*\*=|\|=|\+=|>>=|=|&=|/=|-=| -,|\^|>>|&|\+|\*|-|/|\.|\*\*|%|<<|//|\|| -\)|\(|;|:|@|\[|\]|`|\{|\} -""", re.M | re.X) - - -TERMINALS = [ - 'NAME', 'NUMBER', 'STRING', 'NEWLINE', 'ENDMARKER', - 'INDENT', 'DEDENT' ] - - -## Grammar Visitors ################################################## -# FIXME: parsertools.py ? parser/__init__.py ? - -class NameToken(Token): - """A token that is not a keyword""" - def __init__(self, keywords=None ): - Token.__init__(self, "NAME") - self.keywords = keywords - - def match(self, source, builder, level=0): - """Matches a token. - the default implementation is to match any token whose type - corresponds to the object's name. You can extend Token - to match anything returned from the lexer. for exemple - type, value = source.next() - if type=="integer" and int(value)>=0: - # found - else: - # error unknown or negative integer - """ - ctx = source.context() - tk = source.next() - if tk.name==self.name: - if tk.value not in self.keywords: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name, tk.value ) - source.restore( ctx ) - return 0 - - def match_token(self, other): - """convenience '==' implementation, this is *not* a *real* equality test - a Token instance can be compared to: - - another Token instance in which case all fields (name and value) - must be equal - - a tuple, such as those yielded by the Python lexer, in which case - the comparison algorithm is similar to the one in match() - XXX: - 1/ refactor match and __eq__ ? - 2/ make source.next and source.peek return a Token() instance - """ - if not isinstance(other, Token): - raise RuntimeError("Unexpected token type %r" % other) - if other is EmptyToken: - return False - if other.name != self.name: - return False - if other.value in self.keywords: - return False - return True - - -class EBNFVisitor(object): - - def __init__(self): - self.rules = {} - self.terminals = {} - self.current_rule = None - self.current_subrule = 0 - self.tokens = {} - self.items = [] - self.terminals['NAME'] = NameToken() - - def new_name( self ): - rule_name = ":%s_%s" % (self.current_rule, self.current_subrule) - self.current_subrule += 1 - return rule_name - - def new_item( self, itm ): - self.items.append( itm ) - return itm - - def visit_grammar( self, node ): - # print "Grammar:" - for rule in node.nodes: - rule.visit(self) - # the rules are registered already - # we do a pass through the variables to detect - # terminal symbols from non terminals - for r in self.items: - for i,a in enumerate(r.args): - if a.name in self.rules: - assert isinstance(a,Token) - r.args[i] = self.rules[a.name] - if a.name in self.terminals: - del self.terminals[a.name] - # XXX .keywords also contains punctuations - self.terminals['NAME'].keywords = self.tokens.keys() - - def visit_rule( self, node ): - symdef = node.nodes[0].value - self.current_rule = symdef - self.current_subrule = 0 - alt = node.nodes[1] - rule = alt.visit(self) - if not isinstance( rule, Token ): - rule.name = symdef - self.rules[symdef] = rule - - def visit_alternative( self, node ): - items = [ node.nodes[0].visit(self) ] - items += node.nodes[1].visit(self) - if len(items) == 1 and items[0].name.startswith(':'): - return items[0] - alt = Alternative( self.new_name(), items ) - return self.new_item( alt ) - - def visit_sequence( self, node ): - """ """ - items = [] - for n in node.nodes: - items.append( n.visit(self) ) - if len(items)==1: - return items[0] - elif len(items)>1: - return self.new_item( Sequence( self.new_name(), items) ) - raise SyntaxError("Found empty sequence") - - def visit_sequence_cont( self, node ): - """Returns a list of sequences (possibly empty)""" - return [n.visit(self) for n in node.nodes] - - def visit_seq_cont_list(self, node): - return node.nodes[1].visit(self) - - - def visit_symbol(self, node): - star_opt = node.nodes[1] - sym = node.nodes[0].value - terminal = self.terminals.get( sym ) - if not terminal: - terminal = Token( sym ) - self.terminals[sym] = terminal - - return self.repeat( star_opt, terminal ) - - def visit_option( self, node ): - rule = node.nodes[1].visit(self) - return self.new_item( KleenStar( self.new_name(), 0, 1, rule ) ) - - def visit_group( self, node ): - rule = node.nodes[1].visit(self) - return self.repeat( node.nodes[3], rule ) - - def visit_STRING( self, node ): - value = node.value - tok = self.tokens.get(value) - if not tok: - if py_punct.match( value ): - tok = Token( value ) - elif py_name.match( value ): - tok = Token('NAME', value) - else: - raise SyntaxError("Unknown STRING value ('%s')" % value ) - self.tokens[value] = tok - return tok - - def visit_sequence_alt( self, node ): - res = node.nodes[0].visit(self) - assert isinstance( res, GrammarElement ) - return res - - def repeat( self, star_opt, myrule ): - if star_opt.nodes: - rule_name = self.new_name() - tok = star_opt.nodes[0].nodes[0] - if tok.value == '+': - return self.new_item( KleenStar( rule_name, _min=1, rule = myrule ) ) - elif tok.value == '*': - return self.new_item( KleenStar( rule_name, _min=0, rule = myrule ) ) - else: - raise SyntaxError("Got symbol star_opt with value='%s'" % tok.value ) - return myrule - -rules = None - -def grammar_grammar(): - """Builds the grammar for the grammar file - - Here's the description of the grammar's grammar :: - - grammar: rule+ - rule: SYMDEF alternative - - alternative: sequence ( '|' sequence )+ - star: '*' | '+' - sequence: (SYMBOL star? | STRING | option | group star? )+ - option: '[' alternative ']' - group: '(' alternative ')' star? - """ - global rules - # star: '*' | '+' - star = Alternative( "star", [Token('*'), Token('+')] ) - star_opt = KleenStar ( "star_opt", 0, 1, rule=star ) - - # rule: SYMBOL ':' alternative - symbol = Sequence( "symbol", [Token('SYMBOL'), star_opt] ) - symboldef = Token( "SYMDEF" ) - alternative = Sequence( "alternative", []) - rule = Sequence( "rule", [symboldef, alternative] ) - - # grammar: rule+ - grammar = KleenStar( "grammar", _min=1, rule=rule ) - - # alternative: sequence ( '|' sequence )* - sequence = KleenStar( "sequence", 1 ) - seq_cont_list = Sequence( "seq_cont_list", [Token('|'), sequence] ) - sequence_cont = KleenStar( "sequence_cont",0, rule=seq_cont_list ) - - alternative.args = [ sequence, sequence_cont ] - - # option: '[' alternative ']' - option = Sequence( "option", [Token('['), alternative, Token(']')] ) - - # group: '(' alternative ')' - group = Sequence( "group", [Token('('), alternative, Token(')'), star_opt] ) - - # sequence: (SYMBOL | STRING | option | group )+ - string = Token('STRING') - alt = Alternative( "sequence_alt", [symbol, string, option, group] ) - sequence.args = [ alt ] - - - rules = [ star, star_opt, symbol, alternative, rule, grammar, sequence, - seq_cont_list, sequence_cont, option, group, alt ] - build_first_sets( rules ) - return grammar - - -def parse_grammar(stream): - """parses the grammar file - - stream : file-like object representing the grammar to parse - """ - source = GrammarSource(stream.read()) - rule = grammar_grammar() - builder = BaseGrammarBuilder() - result = rule.match(source, builder) - node = builder.stack[-1] - vis = EBNFVisitor() - node.visit(vis) - return vis - - -from pprint import pprint -if __name__ == "__main__": - grambuild = parse_grammar(file('data/Grammar2.3')) - for i,r in enumerate(grambuild.items): - print "% 3d : %s" % (i, r) - pprint(grambuild.terminals.keys()) - pprint(grambuild.tokens) - print "|".join(grambuild.tokens.keys() ) - Deleted: /pypy/dist/pypy/module/recparser/grammar.py ============================================================================== --- /pypy/dist/pypy/module/recparser/grammar.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,559 +0,0 @@ -""" -a generic recursive descent parser -the grammar is defined as a composition of objects -the objects of the grammar are : -Alternative : as in S -> A | B | C -Sequence : as in S -> A B C -KleenStar : as in S -> A* or S -> A+ -Token : a lexer token -""" - -DEBUG = 0 -USE_LOOKAHEAD = True - -#### Abstract interface for a lexer/tokenizer -class TokenSource(object): - """Abstract base class for a source tokenizer""" - def context(self): - """Returns a context to restore the state of the object later""" - - def restore(self, ctx): - """Restore the context""" - - def next(self): - """Returns the next token from the source - a token is a tuple : (type,value) or (None,None) if the end of the - source has been found - """ - - def offset(self, ctx=None): - """Returns the position we're at so far in the source - optionnally provide a context and you'll get the offset - of the context""" - return -1 - - def current_line(self): - """Returns the current line number""" - return 0 - - def get_pos(self): - """Returns the current source position of the scanner""" - return 0 - - def get_source_text(self, pos1, pos2 ): - """Returns the source text between two scanner positions""" - return "" - - -###################################################################### - - -def build_first_sets(rules): - """builds the real first tokens set for each rule in - - Because a rule can be recursive (directly or indirectly), the - *simplest* algorithm to build each first set is to recompute them - until Computation(N) = Computation(N-1), N being the number of rounds. - As an example, on Python2.3's grammar, we need 19 cycles to compute - full first sets. - """ - changed = True - while changed: - # loop while one first set is changed - changed = False - for rule in rules: - # For each rule, recompute first set - size = len(rule.first_set) - rule.calc_first_set() - new_size = len(rule.first_set) - if new_size != size: - changed = True - for r in rules: - assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r - r.reorder_rule() - - -from syntaxtree import SyntaxNode, TempSyntaxNode, TokenNode - -class BaseGrammarBuilder(object): - """Base/default class for a builder""" - def __init__(self, rules=None, debug=0): - self.rules = rules or {} # a dictionary of grammar rules for debug/reference - # XXX This attribute is here for convenience - self.source_encoding = None - self.debug = debug - self.stack = [] - - def context(self): - """Returns the state of the builder to be restored later""" - #print "Save Stack:", self.stack - return len(self.stack) - - def restore(self, ctx): - del self.stack[ctx:] - #print "Restore Stack:", self.stack - - def alternative(self, rule, source): - # Do nothing, keep rule on top of the stack - if rule.is_root(): - elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.name, source, elems) - if self.debug: - self.stack[-1].dumpstr() - return True - - def sequence(self, rule, source, elts_number): - """ """ - items = [] - for node in self.stack[-elts_number:]: - items += node.expand() - if rule.is_root(): - node_type = SyntaxNode - else: - node_type = TempSyntaxNode - # replace N elements with 1 element regrouping them - if elts_number >= 1: - elem = node_type(rule.name, source, items) - del self.stack[-elts_number:] - self.stack.append(elem) - elif elts_number == 0: - self.stack.append(node_type(rule.name, source, [])) - if self.debug: - self.stack[-1].dumpstr() - return True - - def token(self, name, value, source): - self.stack.append(TokenNode(name, source, value)) - if self.debug: - self.stack[-1].dumpstr() - return True - - -###################################################################### -# Grammar Elements Classes (Alternative, Sequence, KleenStar, Token) # -###################################################################### -class GrammarElement(object): - """Base parser class""" - def __init__(self, name): - # the rule name - self.name = name - self.args = [] - self._is_root = False - self.first_set = [] - self.first_set_complete = False - # self._processing = False - self._trace = False - - def is_root(self): - """This is a root node of the grammar, that is one that will - be included in the syntax tree""" - if self.name != ":" and self.name.startswith(":"): - return False - return True - - - def match(self, source, builder, level=0): - """Try to match a grammar rule - - If next set of tokens matches this grammar element, use - to build an appropriate object, otherwise returns None. - - /!\ If the sets of element didn't match the current grammar - element, then the is restored as it was before the - call to the match() method - - returns None if no match or an object build by builder - """ - if not USE_LOOKAHEAD: - return self._match(source, builder, level) - pos1 = -1 # XXX make the annotator happy - pos2 = -1 # XXX make the annotator happy - token = source.peek() - if self._trace: - pos1 = source.get_pos() - in_first_set = self.match_first_set(token) - if not in_first_set: # and not EmptyToken in self.first_set: - if EmptyToken in self.first_set: - ret = builder.sequence(self, source, 0 ) - if self._trace: - self._debug_display(token, level, 'eee') - return self.debug_return( ret, 0 ) - if self._trace: - self._debug_display(token, level, 'rrr') - return 0 - elif self._trace: - self._debug_display(token, level, '>>>') - - res = self._match(source, builder, level) - if self._trace: - pos2 = source.get_pos() - if res: - prefix = '+++' - else: - prefix = '---' - self._debug_display(token, level, prefix) - print ' '*level, prefix, " TEXT ='%s'" % ( - source.get_source_text(pos1,pos2)) - if res: - print "*" * 50 - return res - - def _debug_display(self, token, level, prefix): - """prints context debug informations""" - prefix = '%s%s' % (' ' * level, prefix) - print prefix, " RULE =", self - print prefix, " TOKEN =", token - print prefix, " FIRST SET =", self.first_set - - - def _match(self, source, builder, level=0): - """Try to match a grammar rule - - If next set of tokens matches this grammar element, use - to build an appropriate object, otherwise returns 0. - - /!\ If the sets of element didn't match the current grammar - element, then the is restored as it was before the - call to the match() method - - returns None if no match or an object build by builder - """ - return 0 - - def parse(self, source): - """Returns a simplified grammar if the rule matched at the source - current context or None""" - # **NOT USED** **NOT IMPLEMENTED** - # To consider if we need to improve speed in parsing - pass - - def __str__(self): - return self.display(0) - - def __repr__(self): - return self.display(0) - - def display(self, level): - """Helper function used to represent the grammar. - mostly used for debugging the grammar itself""" - return "GrammarElement" - - - def debug_return(self, ret, *args ): - # FIXME: use a wrapper of match() methods instead of debug_return() - # to prevent additional indirection - if ret and DEBUG>0: - sargs = ",".join( [ str(i) for i in args ] ) - print "matched %s (%s): %s" % (self.__class__.__name__, sargs, self.display() ) - return ret - - - def calc_first_set(self): - """returns the list of possible next tokens - *must* be implemented in subclasses - """ - # XXX: first_set could probably be implemented with sets - return [] - - def match_first_set(self, other): - """matching is not equality: - token('NAME','x') matches token('NAME',None) - """ - for tk in self.first_set: - if tk.match_token( other ): - return True - return False - - def in_first_set(self, other): - return other in self.first_set - - def reorder_rule(self): - """Called after the computation of first set to allow rules to be reordered - to avoid ambiguities""" - pass - -class Alternative(GrammarElement): - """Represents an alternative in a grammar rule (as in S -> A | B | C)""" - def __init__(self, name, args): - GrammarElement.__init__(self, name ) - self.args = args - self._reordered = False - for i in self.args: - assert isinstance( i, GrammarElement ) - - def _match(self, source, builder, level=0): - """If any of the rules in self.args matches - returns the object built from the first rules that matches - """ - if DEBUG>1: - print "try alt:", self.display() - tok = source.peek() - # Here we stop at the first match we should - # try instead to get the longest alternative - # to see if this solve our problems with infinite recursion - for rule in self.args: - if USE_LOOKAHEAD: - if not rule.match_first_set(tok) and EmptyToken not in rule.first_set: - if self._trace: - print "Skipping impossible rule: %s" % (rule,) - continue - m = rule.match(source, builder, level+1) - if m: - ret = builder.alternative( self, source ) - return self.debug_return( ret ) - return 0 - - def display(self, level=0): - if level==0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - items = [ a.display(1) for a in self.args ] - return name+"(" + "|".join( items ) + ")" - - def calc_first_set(self): - """returns the list of possible next tokens - if S -> (A | B | C): - LAH(S) = Union( LAH(A), LAH(B), LAH(C) ) - """ - # do this to avoid problems on indirect recursive rules - for rule in self.args: - for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 - - def reorder_rule(self): - # take the opportunity to reorder rules in alternatives - # so that rules with Empty in their first set come last - # warn if two rules have empty in their first set - empty_set = [] - not_empty_set = [] - # is only needed for warning / debugging purposes - tokens_set = [] - for rule in self.args: - if EmptyToken in rule.first_set: - empty_set.append(rule) - else: - not_empty_set.append(rule) - if DEBUG: - # This loop is only neede dfor warning / debugging purposes - # It will check if a token is part of several first sets of - # a same alternative - for token in rule.first_set: - if token is not EmptyToken and token in tokens_set: - print "Warning, token %s in\n\t%s's first set is part " \ - "of a previous rule's first set in alternative\n\t" \ - "%s" % (token, rule, self) - tokens_set.append(token) - if len(empty_set) > 1 and not self._reordered: - print "Warning: alternative %s has more than one rule matching Empty" % self - self._reordered = True - self.args[:] = not_empty_set - self.args.extend( empty_set ) - - -class Sequence(GrammarElement): - """Reprensents a Sequence in a grammar rule (as in S -> A B C)""" - def __init__(self, name, args): - GrammarElement.__init__(self, name ) - self.args = args - for i in self.args: - assert isinstance( i, GrammarElement ) - - def _match(self, source, builder, level=0): - """matches all of the symbols in order""" - if DEBUG>1: - print "try seq:", self.display() - ctx = source.context() - bctx = builder.context() - for rule in self.args: - m = rule.match(source, builder, level+1) - if not m: - # Restore needed because some rules may have been matched - # before the one that failed - source.restore(ctx) - builder.restore(bctx) - return 0 - ret = builder.sequence(self, source, len(self.args)) - return self.debug_return( ret ) - - def display(self, level=0): - if level == 0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - items = [a.display(1) for a in self.args] - return name + "(" + " ".join( items ) + ")" - - def calc_first_set(self): - """returns the list of possible next tokens - if S -> A* B C: - LAH(S) = Union( LAH(A), LAH(B) ) - if S -> A+ B C: - LAH(S) = LAH(A) - if S -> A B C: - LAH(S) = LAH(A) - """ - for rule in self.args: - if not rule.first_set: - break - if EmptyToken in self.first_set: - self.first_set.remove( EmptyToken ) - - # del self.first_set[EmptyToken] - # while we're in this loop, keep agregating possible tokens - for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 - if EmptyToken not in rule.first_set: - break - - - -class KleenStar(GrammarElement): - """Represents a KleenStar in a grammar rule as in (S -> A+) or (S -> A*)""" - def __init__(self, name, _min = 0, _max = -1, rule=None): - GrammarElement.__init__( self, name ) - self.args = [rule] - self.min = _min - if _max == 0: - raise ValueError("KleenStar needs max==-1 or max>1") - self.max = _max - self.star = "x" - if self.min == 0: - self.first_set.append( EmptyToken ) - # self.first_set[EmptyToken] = 1 - - def _match(self, source, builder, level=0): - """matches a number of times self.args[0]. the number must be comprised - between self._min and self._max inclusive. -1 is used to represent infinity""" - if DEBUG>1: - print "try kle:", self.display() - ctx = source.context() - bctx = builder.context() - rules = 0 - rule = self.args[0] - while True: - m = rule.match(source, builder, level+1) - if not m: - # Rule should be matched at least 'min' times - if rules0 and rules == self.max: - ret = builder.sequence(self, source, rules) - return self.debug_return( ret, rules ) - - def display(self, level=0): - if level==0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - star = "{%d,%d}" % (self.min,self.max) - if self.min==0 and self.max==1: - star = "?" - elif self.min==0 and self.max==-1: - star = "*" - elif self.min==1 and self.max==-1: - star = "+" - s = self.args[0].display(1) - return name + "%s%s" % (s, star) - - - def calc_first_set(self): - """returns the list of possible next tokens - if S -> A*: - LAH(S) = Union( LAH(A), EmptyToken ) - if S -> A+: - LAH(S) = LAH(A) - """ - rule = self.args[0] - self.first_set = rule.first_set[:] - # self.first_set = dict(rule.first_set) - if self.min == 0 and EmptyToken not in self.first_set: - self.first_set.append(EmptyToken) - # self.first_set[EmptyToken] = 1 - -class Token(GrammarElement): - """Represents a Token in a grammar rule (a lexer token)""" - def __init__( self, name, value = None): - GrammarElement.__init__( self, name ) - self.value = value - self.first_set = [self] - # self.first_set = {self: 1} - - def match(self, source, builder, level=0): - """Matches a token. - the default implementation is to match any token whose type - corresponds to the object's name. You can extend Token - to match anything returned from the lexer. for exemple - type, value = source.next() - if type=="integer" and int(value)>=0: - # found - else: - # error unknown or negative integer - """ - ctx = source.context() - tk = source.next() - # XXX: match_token - if tk.name == self.name: - if self.value is None: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name ) - elif self.value == tk.value: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name, tk.value ) - if DEBUG>1: - print "tried tok:", self.display() - source.restore( ctx ) - return 0 - - def display(self, level=0): - if self.value is None: - return "<%s>" % self.name - else: - return "<%s>=='%s'" % (self.name, self.value) - - - def match_token(self, other): - """convenience '==' implementation, this is *not* a *real* equality test - a Token instance can be compared to: - - another Token instance in which case all fields (name and value) - must be equal - - a tuple, such as those yielded by the Python lexer, in which case - the comparison algorithm is similar to the one in match() - XXX: - 1/ refactor match and __eq__ ? - 2/ make source.next and source.peek return a Token() instance - """ - if not isinstance(other, Token): - raise RuntimeError("Unexpected token type %r" % other) - if other is EmptyToken: - return False - res = other.name == self.name and self.value in (None, other.value) - #print "matching", self, other, res - return res - - def __eq__(self, other): - return self.name == other.name and self.value == other.value - - - - def calc_first_set(self): - """computes the list of possible next tokens - """ - pass - -EmptyToken = Token(None) Deleted: /pypy/dist/pypy/module/recparser/pythonlexer.py ============================================================================== --- /pypy/dist/pypy/module/recparser/pythonlexer.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,378 +0,0 @@ -"""This is a lexer for a Python recursive descent parser -it obeys the TokenSource interface defined for the grammar -analyser in grammar.py -""" - -from grammar import TokenSource, Token -# Don't import string for that ... -NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' -NUMCHARS = '0123456789' -ALNUMCHARS = NAMECHARS + NUMCHARS -EXTENDED_ALNUMCHARS = ALNUMCHARS + '-.' -WHITESPACES = ' \t\n\r\v\f' - -def match_encoding_declaration(comment): - """returns the declared encoding or None - - This function is a replacement for : - >>> py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") - >>> py_encoding.search(comment) - """ - index = comment.find('coding') - if index == -1: - return None - next_char = comment[index + 6] - if next_char not in ':=': - return None - end_of_decl = comment[index + 7:] - index = 0 - for char in end_of_decl: - if char not in WHITESPACES: - break - index += 1 - else: - return None - encoding = '' - for char in end_of_decl[index:]: - if char in EXTENDED_ALNUMCHARS: - encoding += char - else: - break - if encoding != '': - return encoding - return None - -def _normalize_encoding(encoding): - """returns normalized name for - - see dist/src/Parser/tokenizer.c 'get_normal_name()' - for implementation details / reference - - NOTE: for now, parser.suite() raises a MemoryError when - a bad encoding is used. (SF bug #979739) - """ - # lower() + '_' / '-' conversion - encoding = encoding.replace('_', '-').lower() - if encoding.startswith('utf-8'): - return 'utf-8' - for variant in ('latin-1', 'iso-latin-1', 'iso-8859-1'): - if encoding.startswith(variant): - return 'iso-8859-1' - return encoding - -################################################################################ -import token as tokenmod -from pytokenize import tabsize, whiteSpaceDFA, triple_quoted, endDFAs, \ - single_quoted, pseudoDFA -import automata - -# adopt pytokenize notations / values -tokenmod.COMMENT = tokenmod.N_TOKENS -tokenmod.NL = tokenmod.N_TOKENS + 1 - -class TokenError(Exception): - """Raised when EOF is found prematuerly""" - def __init__(self, msg, strstart, token_stack): - # Exception.__init__(self, msg) - self.strstart = strstart - self.token_stack = token_stack - - -def generate_tokens(lines): - """ - This is a rewrite of pypy.module.parser.pytokenize.generate_tokens since - the original function is not RPYTHON (uses yield) - It was also slightly modified to generate Token instances instead - of the original 5-tuples - - Original docstring :: - - The generate_tokens() generator requires one argment, readline, which - must be a callable object which provides the same interface as the - readline() method of built-in file objects. Each call to the function - should return one line of input as a string. - - The generator produces 5-tuples with these members: the token type; the - token string; a 2-tuple (srow, scol) of ints specifying the row and - column where the token begins in the source; a 2-tuple (erow, ecol) of - ints specifying the row and column where the token ends in the source; - and the line on which the token was found. The line passed is the - logical line; continuation lines are included. - """ - token_list = [] - lnum = parenlev = continued = 0 - namechars = NAMECHARS - numchars = NUMCHARS - contstr, needcont = '', 0 - contline = None - indents = [0] - last_comment = '' - encoding = None - strstart = (0, 0) - - lines.append('') # XXX HACK probably not needed - endDFA = automata.DFA([], []) # XXX Make the translator happy - line = '' # XXX Make the translator happy - for line in lines: - lnum = lnum + 1 - pos, max = 0, len(line) - - if contstr: # continued string - if not line: - raise TokenError("EOF in multi-line string", strstart, token_list) - endmatch = endDFA.recognize(line) - if -1 != endmatch: - pos = end = endmatch - tok = token_from_values(tokenmod.STRING, contstr + line[:end]) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((STRING, contstr + line[:end], - # strstart, (lnum, end), contline + line)) - contstr, needcont = '', 0 - contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': - tok = token_from_values(tokenmod.ERRORTOKEN, contstr + line) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((ERRORTOKEN, contstr + line, - # strstart, (lnum, len(line)), contline)) - contstr = '' - contline = None - continue - else: - contstr = contstr + line - contline = contline + line - continue - - elif parenlev == 0 and not continued: # new statement - if not line: break - column = 0 - while pos < max: # measure leading whitespace - if line[pos] == ' ': column = column + 1 - elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize - elif line[pos] == '\f': column = 0 - else: break - pos = pos + 1 - if pos == max: break - - if line[pos] in '#\r\n': # skip comments or blank lines - if line[pos] == '#': - tok = token_from_values(tokenmod.COMMENT, line[pos:]) - last_comment = line[pos:] - if lnum <= 2 and encoding is None: - encoding = match_encoding_declaration(last_comment) - if encoding is not None: - encoding = _normalize_encoding(encoding) - else: - tok = token_from_values(tokenmod.NL, line[pos:]) - last_comment = '' - # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line)) - # token_list.append(((NL, COMMENT)[line[pos] == '#'], line[pos:], - # (lnum, pos), (lnum, len(line)), line)) - continue - - if column > indents[-1]: # count indents or dedents - indents.append(column) - tok = token_from_values(tokenmod.INDENT, line[:pos]) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((INDENT, line[:pos], (lnum, 0), (lnum, pos), line)) - while column < indents[-1]: - indents = indents[:-1] - tok = token_from_values(tokenmod.DEDENT, '') - token_list.append((tok, line)) - last_comment = '' - # token_list.append((DEDENT, '', (lnum, pos), (lnum, pos), line)) - - else: # continued statement - if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0), token_list) - continued = 0 - - while pos < max: - pseudomatch = pseudoDFA.recognize(line, pos) - if -1 != pseudomatch: # scan for tokens - # JDR: Modified - start = whiteSpaceDFA.recognize(line, pos) - if -1 == start: - start = pos - end = pseudomatch - - spos, epos, pos = (lnum, start), (lnum, end), end - token, initial = line[start:end], line[start] - - if initial in numchars or \ - (initial == '.' and token != '.'): # ordinary number - tok = token_from_values(tokenmod.NUMBER, token) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((NUMBER, token, spos, epos, line)) - elif initial in '\r\n': - if parenlev > 0: - tok = token_from_values(tokenmod.NL, token) - last_comment = '' - # XXX Skip NL - else: - tok = token_from_values(tokenmod.NEWLINE, token) - # XXX YUCK ! - tok.value = last_comment - token_list.append((tok, line)) - last_comment = '' - # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) - elif initial == '#': - tok = token_from_values(tokenmod.COMMENT, token) - last_comment = token - if lnum <= 2 and encoding is None: - encoding = match_encoding_declaration(last_comment) - if encoding is not None: - encoding = _normalize_encoding(encoding) - # XXX Skip # token_list.append((tok, line)) - # token_list.append((COMMENT, token, spos, epos, line)) - elif token in triple_quoted: - endDFA = endDFAs[token] - endmatch = endDFA.recognize(line, pos) - if -1 != endmatch: # all on one line - pos = endmatch - token = line[start:pos] - tok = token_from_values(tokenmod.STRING, token) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((STRING, token, spos, (lnum, pos), line)) - else: - strstart = (lnum, start) # multiple lines - contstr = line[start:] - contline = line - break - elif initial in single_quoted or \ - token[:2] in single_quoted or \ - token[:3] in single_quoted: - if token[-1] == '\n': # continued string - strstart = (lnum, start) - endDFA = (endDFAs[initial] or endDFAs[token[1]] or - endDFAs[token[2]]) - contstr, needcont = line[start:], 1 - contline = line - break - else: # ordinary string - tok = token_from_values(tokenmod.STRING, token) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((STRING, token, spos, epos, line)) - elif initial in namechars: # ordinary name - tok = token_from_values(tokenmod.NAME, token) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((NAME, token, spos, epos, line)) - elif initial == '\\': # continued stmt - continued = 1 - else: - if initial in '([{': parenlev = parenlev + 1 - elif initial in ')]}': parenlev = parenlev - 1 - tok = token_from_values(tokenmod.OP, token) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((OP, token, spos, epos, line)) - else: - tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) - token_list.append((tok, line)) - last_comment = '' - # token_list.append((ERRORTOKEN, line[pos], - # (lnum, pos), (lnum, pos+1), line)) - pos = pos + 1 - - last_comment = '' - for indent in indents[1:]: # pop remaining indent levels - tok = token_from_values(tokenmod.DEDENT, '') - token_list.append((tok, line)) - # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) - - ## adim - token_list.append((Token('NEWLINE', ''), line)) - ## - tok = token_from_values(tokenmod.ENDMARKER, '',) - token_list.append((tok, line)) - # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) - return token_list, encoding - -class PythonSource(TokenSource): - """This source uses Jonathan's tokenizer""" - def __init__(self, strings): - # TokenSource.__init__(self) - tokens, encoding = generate_tokens(strings) - self.token_stack = tokens - self.encoding = encoding - self._current_line = '' # the current line (as a string) - self.stack_pos = 0 - - def next(self): - if self.stack_pos >= len(self.token_stack): - raise StopIteration("Remove me") - tok, line = self.token_stack[self.stack_pos] - self.stack_pos += 1 - self._current_line = line - return tok - - def current_line(self): - return self._current_line - - def context(self): - return self.stack_pos - - def restore(self, ctx): - self.stack_pos = ctx - - def peek(self): - """returns next token without consuming it""" - ctx = self.context() - token = self.next() - self.restore(ctx) - return token - - #### methods below have to be translated - def offset(self, ctx=None): - if ctx is None: - return self.stack_pos - else: - assert type(ctx)==int - return ctx - - def get_pos(self): - if self.stack_pos >= len(self.stack): - return self.pos - else: - token, line, pos = self.stack[self.stack_pos] - return pos - - def get_source_text(self, pos0, pos1 ): - return self.input[pos0:pos1] - - def debug(self): - """return context for debug information""" - return 'line %s : %s' % ('XXX', self._current_line) - -NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] -NAMED_LIST = [tokenmod.OP, ] - -def token_from_values(tok_type, tok_string): - """XXX Compatibility layer between both parsers""" - if tok_type in NONE_LIST: - return Token(tokenmod.tok_name[tok_type], None) - if tok_type in NAMED_LIST: - return Token(tok_string, None) - if tok_type == tokenmod.NEWLINE: - return Token('NEWLINE', '') # XXX pending comment ? - return Token(tokenmod.tok_name[tok_type], tok_string) - -Source = PythonSource - -def tokenize_file(filename): - f = file(filename).read() - src = Source(f) - token = src.next() - while token != ("ENDMARKER", None) and token != (None, None): - print token - token = src.next() - -if __name__ == '__main__': - import sys - tokenize_file(sys.argv[1]) Deleted: /pypy/dist/pypy/module/recparser/pythonparse.py ============================================================================== --- /pypy/dist/pypy/module/recparser/pythonparse.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,51 +0,0 @@ -#!/usr/bin/env python -from pythonlexer import Source -from ebnfparse import parse_grammar -import sys -import os -import symbol -import grammar - -# parse the python grammar corresponding to our CPython version -_ver = ".".join([str(i) for i in sys.version_info[:2]]) -PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) - -def python_grammar(): - """returns a """ - level = grammar.DEBUG - grammar.DEBUG = 0 - gram = parse_grammar( file(PYTHON_GRAMMAR) ) - grammar.DEBUG = level - # Build first sets for each rule (including anonymous ones) - grammar.build_first_sets(gram.items) - return gram - -PYTHON_PARSER = python_grammar() - - -def parse_python_source( textsrc, gram, goal, builder=None ): - """Parse a python source according to goal""" - target = gram.rules[goal] - src = Source(textsrc) - if builder is None: - builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) - result = target.match(src, builder) - # XXX find a clean way to process encoding declarations - builder.source_encoding = src.encoding - # - if not result: - return None - # raise SyntaxError("at %s" % src.debug() ) - return builder - -def parse_file_input(pyf, gram, builder=None): - """Parse a python file""" - return parse_python_source( pyf.read(), gram, "file_input", builder ) - -def parse_single_input(textsrc, gram, builder=None): - """Parse a python single statement""" - return parse_python_source( textsrc, gram, "single_input", builder ) - -def parse_eval_input(textsrc, gram, builder=None): - """Parse a python expression""" - return parse_python_source( textsrc, gram, "eval_input", builder ) Deleted: /pypy/dist/pypy/module/recparser/pythonutil.py ============================================================================== --- /pypy/dist/pypy/module/recparser/pythonutil.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,98 +0,0 @@ -__all__ = ["python_parse", "pypy_parse","ast_single_input", "ast_file_input", - "ast_eval_input" ] - -import grammar -import pythonparse -from compiler.transformer import Transformer -from tuplebuilder import TupleBuilder - -PYTHON_PARSER = pythonparse.PYTHON_PARSER - -def python_parse(filename): - """parse using CPython's parser module and return nested tuples - """ - pyf = file(filename) - import parser - tp2 = parser.suite(pyf.read()) - return tp2.totuple() - -import symbol -def pypy_parse(filename): - """parse using PyPy's parser module and return - a tuple of three elements : - - The encoding declaration symbol or None if there were no encoding - statement - - The TupleBuilder's stack top element (instance of - tuplebuilder.StackElement which is a wrapper of some nested tuples - like those returned by the CPython's parser) - - The encoding string or None if there were no encoding statement - nested tuples - """ - pyf = file(filename) - text = pyf.read() - pyf.close() - builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - # make the annotator life easier - strings = [line+'\n' for line in text.split('\n')] - pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) - nested_tuples = builder.stack[-1] - if builder.source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, builder.source_encoding) - else: - return (None, nested_tuples, None) - -def annotateme(strings): - builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) - nested_tuples = builder.stack[-1] - if builder.source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, builder.source_encoding) - else: - return (None, nested_tuples, None) - -def ast_single_input( text ): - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( text, PYTHON_PARSER, "single_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - -def ast_file_input( filename ): - pyf = file(filename,"r") - text = pyf.read() - return ast_srcfile_input( text, filename ) - -def ast_srcfile_input( srctext, filename ): - # TODO do something with the filename - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( srctext, PYTHON_PARSER, "file_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - -def ast_eval_input( textsrc ): - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( textsrc, PYTHON_PARSER, "eval_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - - - -if __name__ == "__main__": - import sys - if len(sys.argv) < 2: - print "python parse.py [-d N] test_file.py" - sys.exit(1) - if sys.argv[1] == "-d": - debug_level = int(sys.argv[2]) - test_file = sys.argv[3] - else: - test_file = sys.argv[1] - print "-"*20 - print - print "pyparse \n", pypy_parse(test_file) - print "parser \n", python_parse(test_file) Deleted: /pypy/dist/pypy/module/recparser/pytokenize.py ============================================================================== --- /pypy/dist/pypy/module/recparser/pytokenize.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,334 +0,0 @@ -#! /usr/bin/env python -# ______________________________________________________________________ -"""Module pytokenize - -THIS FILE WAS COPIED FROM pypy/module/parser/pytokenize.py AND ADAPTED -TO BE ANNOTABLE (Mainly made lists homogeneous) - -This is a modified version of Ka-Ping Yee's tokenize module found in the -Python standard library. - -The primary modification is the removal of the tokenizer's dependence on the -standard Python regular expression module, which is written in C. The regular -expressions have been replaced with hand built DFA's using the -basil.util.automata module. - -XXX This now assumes that the automata module is in the Python path. - -$Id: pytokenize.py,v 1.3 2003/10/03 16:31:53 jriehl Exp $ -""" -# ______________________________________________________________________ - -from __future__ import generators -import string -import automata - -# ______________________________________________________________________ -# COPIED: -from token import * - -import token -__all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", - "generate_tokens", "NL"] -del x -del token - -COMMENT = N_TOKENS -tok_name[COMMENT] = 'COMMENT' -NL = N_TOKENS + 1 -tok_name[NL] = 'NL' -N_TOKENS += 2 - -# ______________________________________________________________________ -# Automatically generated DFA's (with one or two hand tweeks): -pseudoStatesAccepts = [True, True, True, True, True, True, True, True, - True, True, False, True, True, True, False, False, - False, False, True, False, False, True, True, False, - True, False, True, False, True, False, True, False, - False, False, True, False, False, False, True] - -pseudoStates = [ - {'\t': 0, '\n': 13, '\x0c': 0, '\r': 14, ' ': 0, '!': 10, - '"': 16, '#': 18, '%': 12, '&': 12, - "'": 15, '(': 13, ')': 13, '*': 7, - '+': 12, ',': 13, '-': 12, '.': 6, - '/': 11, '0': 4, '1': 5, '2': 5, - '3': 5, '4': 5, '5': 5, '6': 5, - '7': 5, '8': 5, '9': 5, ':': 13, - ';': 13, '<': 9, '=': 12, '>': 8, 'A': 1, - 'B': 1, 'C': 1, 'D': 1, 'E': 1, - 'F': 1, 'G': 1, 'H': 1, 'I': 1, - 'J': 1, 'K': 1, 'L': 1, 'M': 1, - 'N': 1, 'O': 1, 'P': 1, 'Q': 1, - 'R': 2, 'S': 1, 'T': 1, 'U': 3, - 'V': 1, 'W': 1, 'X': 1, 'Y': 1, - 'Z': 1, '[': 13, '\\': 17, ']': 13, - '^': 12, '_': 1, '`': 13, 'a': 1, - 'b': 1, 'c': 1, 'd': 1, 'e': 1, - 'f': 1, 'g': 1, 'h': 1, 'i': 1, - 'j': 1, 'k': 1, 'l': 1, 'm': 1, - 'n': 1, 'o': 1, 'p': 1, 'q': 1, - 'r': 2, 's': 1, 't': 1, 'u': 3, - 'v': 1, 'w': 1, 'x': 1, 'y': 1, - 'z': 1, '{': 13, '|': 12, '}': 13, - '~': 13}, - - {'0': 1, '1': 1, '2': 1, '3': 1, - '4': 1, '5': 1, '6': 1, '7': 1, - '8': 1, '9': 1, 'A': 1, 'B': 1, - 'C': 1, 'D': 1, 'E': 1, 'F': 1, - 'G': 1, 'H': 1, 'I': 1, 'J': 1, - 'K': 1, 'L': 1, 'M': 1, 'N': 1, - 'O': 1, 'P': 1, 'Q': 1, 'R': 1, - 'S': 1, 'T': 1, 'U': 1, 'V': 1, - 'W': 1, 'X': 1, 'Y': 1, 'Z': 1, - '_': 1, 'a': 1, 'b': 1, 'c': 1, - 'd': 1, 'e': 1, 'f': 1, 'g': 1, - 'h': 1, 'i': 1, 'j': 1, 'k': 1, - 'l': 1, 'm': 1, 'n': 1, 'o': 1, - 'p': 1, 'q': 1, 'r': 1, 's': 1, - 't': 1, 'u': 1, 'v': 1, 'w': 1, - 'x': 1, 'y': 1, 'z': 1}, - - {'"': 20, "'": 19, '0': 1, '1': 1, - '2': 1, '3': 1, '4': 1, '5': 1, - '6': 1, '7': 1, '8': 1, '9': 1, - 'A': 1, 'B': 1, 'C': 1, 'D': 1, - 'E': 1, 'F': 1, 'G': 1, 'H': 1, - 'I': 1, 'J': 1, 'K': 1, 'L': 1, - 'M': 1, 'N': 1, 'O': 1, 'P': 1, - 'Q': 1, 'R': 1, 'S': 1, 'T': 1, - 'U': 1, 'V': 1, 'W': 1, 'X': 1, - 'Y': 1, 'Z': 1, '_': 1, 'a': 1, - 'b': 1, 'c': 1, 'd': 1, 'e': 1, - 'f': 1, 'g': 1, 'h': 1, 'i': 1, - 'j': 1, 'k': 1, 'l': 1, 'm': 1, - 'n': 1, 'o': 1, 'p': 1, 'q': 1, - 'r': 1, 's': 1, 't': 1, 'u': 1, - 'v': 1, 'w': 1, 'x': 1, 'y': 1, - 'z': 1}, - - {'"': 20, "'": 19, '0': 1, '1': 1, - '2': 1, '3': 1, '4': 1, '5': 1, - '6': 1, '7': 1, '8': 1, '9': 1, - 'A': 1, 'B': 1, 'C': 1, 'D': 1, - 'E': 1, 'F': 1, 'G': 1, 'H': 1, - 'I': 1, 'J': 1, 'K': 1, 'L': 1, - 'M': 1, 'N': 1, 'O': 1, 'P': 1, - 'Q': 1, 'R': 2, 'S': 1, 'T': 1, - 'U': 1, 'V': 1, 'W': 1, 'X': 1, - 'Y': 1, 'Z': 1, '_': 1, 'a': 1, - 'b': 1, 'c': 1, 'd': 1, 'e': 1, - 'f': 1, 'g': 1, 'h': 1, 'i': 1, - 'j': 1, 'k': 1, 'l': 1, 'm': 1, - 'n': 1, 'o': 1, 'p': 1, 'q': 1, - 'r': 2, 's': 1, 't': 1, 'u': 1, - 'v': 1, 'w': 1, 'x': 1, 'y': 1, - 'z': 1}, - - {'.': 24, '0': 22, '1': 22, '2': 22, - '3': 22, '4': 22, '5': 22, '6': 22, - '7': 22, '8': 23, '9': 23, 'E': 25, - 'J': 13, 'L': 13, 'X': 21, 'e': 25, - 'j': 13, 'l': 13, 'x': 21}, - - {'.': 24, '0': 5, '1': 5, '2': 5, - '3': 5, '4': 5, '5': 5, '6': 5, - '7': 5, '8': 5, '9': 5, 'E': 25, - 'J': 13, 'L': 13, 'e': 25, 'j': 13, - 'l': 13}, - - {'0': 26, '1': 26, '2': 26, '3': 26, - '4': 26, '5': 26, '6': 26, '7': 26, - '8': 26, '9': 26}, - - {'*': 12, '=': 13}, - - {'=': 13, '>': 12}, - - {'=': 13, '<': 12, '>': 13}, - - {'=': 13}, - - {'=': 13, '/': 12}, - - {'=': 13}, - - {}, - - {'\n': 13}, - - {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 28}, - - {automata.DEFAULT: 20, '"': 30, '\n': 27, '\\': 31}, - - {'\n': 13, '\r': 14}, - - {automata.DEFAULT: 18, '\n': 27, '\r': 27}, - - {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 13}, - - {automata.DEFAULT: 20, '"': 13, '\n': 27, '\\': 31}, - - {'0': 21, '1': 21, '2': 21, '3': 21, - '4': 21, '5': 21, '6': 21, '7': 21, - '8': 21, '9': 21, 'A': 21, 'B': 21, - 'C': 21, 'D': 21, 'E': 21, 'F': 21, - 'L': 13, 'a': 21, 'b': 21, 'c': 21, - 'd': 21, 'e': 21, 'f': 21, 'l': 13}, - - {'.': 24, '0': 22, '1': 22, '2': 22, - '3': 22, '4': 22, '5': 22, '6': 22, - '7': 22, '8': 23, '9': 23, 'E': 25, - 'J': 13, 'L': 13, 'e': 25, 'j': 13, - 'l': 13}, - - {'.': 24, '0': 23, '1': 23, '2': 23, - '3': 23, '4': 23, '5': 23, '6': 23, - '7': 23, '8': 23, '9': 23, 'E': 25, - 'J': 13, 'e': 25, 'j': 13}, - - {'0': 24, '1': 24, '2': 24, '3': 24, - '4': 24, '5': 24, '6': 24, '7': 24, - '8': 24, '9': 24, 'E': 32, 'J': 13, - 'e': 32, 'j': 13}, - - {'+': 33, '-': 33, '0': 34, '1': 34, - '2': 34, '3': 34, '4': 34, '5': 34, - '6': 34, '7': 34, '8': 34, '9': 34}, - - {'0': 26, '1': 26, '2': 26, '3': 26, - '4': 26, '5': 26, '6': 26, '7': 26, - '8': 26, '9': 26, 'E': 32, 'J': 13, - 'e': 32, 'j': 13}, - - {}, - - {"'": 13}, - - {automata.DEFAULT: 35, '\n': 13, '\r': 14}, - - {'"': 13}, - - {automata.DEFAULT: 36, '\n': 13, '\r': 14}, - - {'+': 37, '-': 37, '0': 38, '1': 38, - '2': 38, '3': 38, '4': 38, '5': 38, - '6': 38, '7': 38, '8': 38, '9': 38}, - - - {'0': 34, '1': 34, '2': 34, '3': 34, - '4': 34, '5': 34, '6': 34, '7': 34, - '8': 34, '9': 34}, - - {'0': 34, '1': 34, '2': 34, '3': 34, - '4': 34, '5': 34, '6': 34, '7': 34, - '8': 34, '9': 34, 'J': 13, 'j': 13}, - - {automata.DEFAULT: 35, '\n': 27, '\\': 29, "'": 13}, - - {automata.DEFAULT: 36, '"': 13, '\n': 27, '\\': 31}, - - {'0': 38, '1': 38, '2': 38, '3': 38, - '4': 38, '5': 38, '6': 38, '7': 38, - '8': 38, '9': 38}, - - {'0': 38, '1': 38, '2': 38, '3': 38, - '4': 38, '5': 38, '6': 38, '7': 38, - '8': 38, '9': 38, 'J': 13, 'j': 13}, - ] - -pseudoDFA = automata.DFA(pseudoStates, pseudoStatesAccepts) - -double3StatesAccepts = [False, False, False, False, False, True] -double3States = [ - {automata.DEFAULT: 0, '"': 1, '\\': 2}, - {automata.DEFAULT: 4, '"': 3, '\\': 2}, - {automata.DEFAULT: 4}, - {automata.DEFAULT: 4, '"': 5, '\\': 2}, - {automata.DEFAULT: 4, '"': 1, '\\': 2}, - {automata.DEFAULT: 4, '"': 5, '\\': 2}, - ] -double3DFA = automata.NonGreedyDFA(double3States, double3StatesAccepts) - -single3StatesAccepts = [False, False, False, False, False, True] -single3States = [ - {automata.DEFAULT: 0, '\\': 2, "'": 1}, - {automata.DEFAULT: 4, '\\': 2, "'": 3}, - {automata.DEFAULT: 4}, - {automata.DEFAULT: 4, '\\': 2, "'": 5}, - {automata.DEFAULT: 4, '\\': 2, "'": 1}, - {automata.DEFAULT: 4, '\\': 2, "'": 5}, - ] -single3DFA = automata.NonGreedyDFA(single3States, single3StatesAccepts) - -singleStatesAccepts = [False, True, False] -singleStates = [ - {automata.DEFAULT: 0, '\\': 2, "'": 1}, - {}, - {automata.DEFAULT: 0}, - ] -singleDFA = automata.DFA(singleStates, singleStatesAccepts) - -doubleStatesAccepts = [False, True, False] -doubleStates = [ - {automata.DEFAULT: 0, '"': 1, '\\': 2}, - {}, - {automata.DEFAULT: 0}, - ] -doubleDFA = automata.DFA(doubleStates, doubleStatesAccepts) - -endDFAs = {"'" : singleDFA, - '"' : doubleDFA, - "r" : None, - "R" : None, - "u" : None, - "U" : None} - -for uniPrefix in ("", "u", "U"): - for rawPrefix in ("", "r", "R"): - prefix = uniPrefix + rawPrefix - endDFAs[prefix + "'''"] = single3DFA - endDFAs[prefix + '"""'] = double3DFA - -whiteSpaceStatesAccepts = [True] -whiteSpaceStates = [{'\t': 0, ' ': 0, '\x0c': 0}] -whiteSpaceDFA = automata.DFA(whiteSpaceStates, whiteSpaceStatesAccepts) - -# ______________________________________________________________________ -# COPIED: - -triple_quoted = {} -for t in ("'''", '"""', - "r'''", 'r"""', "R'''", 'R"""', - "u'''", 'u"""', "U'''", 'U"""', - "ur'''", 'ur"""', "Ur'''", 'Ur"""', - "uR'''", 'uR"""', "UR'''", 'UR"""'): - triple_quoted[t] = t -single_quoted = {} -for t in ("'", '"', - "r'", 'r"', "R'", 'R"', - "u'", 'u"', "U'", 'U"', - "ur'", 'ur"', "Ur'", 'Ur"', - "uR'", 'uR"', "UR'", 'UR"' ): - single_quoted[t] = t - -tabsize = 8 - -# PYPY MODIFICATION: removed TokenError class as it's not needed here - -# PYPY MODIFICATION: removed StopTokenizing class as it's not needed here - -# PYPY MODIFICATION: removed printtoken() as it's not needed here - -# PYPY MODIFICATION: removed tokenize() as it's not needed here - -# PYPY MODIFICATION: removed tokenize_loop() as it's not needed here - -# PYPY MODIFICATION: removed generate_tokens() as it was copied / modified -# in pythonlexer.py - -# PYPY MODIFICATION: removed main() as it's not needed here - -# ______________________________________________________________________ -# End of pytokenize.py Deleted: /pypy/dist/pypy/module/recparser/syntaxtree.py ============================================================================== --- /pypy/dist/pypy/module/recparser/syntaxtree.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,162 +0,0 @@ -import symbol -import token - -TOKEN_MAP = { - "STRING" : token.STRING, - "NUMBER" : token.NUMBER, - "NAME" : token.NAME, - "NEWLINE" : token.NEWLINE, - "DEDENT" : token.DEDENT, - "ENDMARKER" : token.ENDMARKER, - "INDENT" : token.INDENT, - "NEWLINE" : token.NEWLINE, - "NT_OFFSET" : token.NT_OFFSET, - "N_TOKENS" : token.N_TOKENS, - "OP" : token.OP, - "?ERRORTOKEN" : token.ERRORTOKEN, - "&" : token.AMPER, - "&=" : token.AMPEREQUAL, - "`" : token.BACKQUOTE, - "^" : token.CIRCUMFLEX, - "^=" : token.CIRCUMFLEXEQUAL, - ":" : token.COLON, - "," : token.COMMA, - "." : token.DOT, - "//" : token.DOUBLESLASH, - "//=" : token.DOUBLESLASHEQUAL, - "**" : token.DOUBLESTAR, - "**=" : token.DOUBLESTAREQUAL, - "==" : token.EQEQUAL, - "=" : token.EQUAL, - ">" : token.GREATER, - ">=" : token.GREATEREQUAL, - "{" : token.LBRACE, - "}" : token.RBRACE, - "<<" : token.LEFTSHIFT, - "<<=" : token.LEFTSHIFTEQUAL, - "<" : token.LESS, - "<=" : token.LESSEQUAL, - "(" : token.LPAR, - "[" : token.LSQB, - "-=" : token.MINEQUAL, - "-" : token.MINUS, - "!=" : token.NOTEQUAL, - "<>" : token.NOTEQUAL, - "%" : token.PERCENT, - "%=" : token.PERCENTEQUAL, - "+" : token.PLUS, - "+=" : token.PLUSEQUAL, - ")" : token.RBRACE, - ">>" : token.RIGHTSHIFT, - ">>=" : token.RIGHTSHIFTEQUAL, - ")" : token.RPAR, - "]" : token.RSQB, - ";" : token.SEMI, - "/" : token.SLASH, - "/=" : token.SLASHEQUAL, - "*" : token.STAR, - "*=" : token.STAREQUAL, - "~" : token.TILDE, - "|" : token.VBAR, - "|=" : token.VBAREQUAL, - } -NT_OFFSET = token.NT_OFFSET - -SYMBOLS = {} -# copies the numerical mapping between symbol name and symbol value -# into SYMBOLS -for k,v in symbol.sym_name.items(): - SYMBOLS[v] = k -SYMBOLS['UNKNOWN'] = -1 - - -class SyntaxNode(object): - """A syntax node""" - def __init__(self, name, source, args): - self.name = name - self.nodes = args - self.lineno = source.current_line() - - def dumptree(self, treenodes, indent): - treenodes.append(self.name) - if len(self.nodes) > 1: - treenodes.append(" -> (\n") - treenodes.append(indent+" ") - for node in self.nodes: - node.dumptree(treenodes, indent+" ") - treenodes.append(")\n") - treenodes.append(indent) - elif len(self.nodes) == 1: - treenodes.append(" ->\n") - treenodes.append(indent+" ") - self.nodes[0].dumptree(treenodes, indent+" ") - - def dumpstr(self): - treenodes = [] - self.dumptree(treenodes, "") - return "".join(treenodes) - - def __repr__(self): - return "" % (self.name, id(self)) - - def __str__(self): - return "(%s)" % self.name - - def visit(self, visitor): - """NOT RPYTHON, used only at bootstrap time anyway""" - visit_meth = getattr(visitor, "visit_%s" % self.name, None) - if visit_meth: - return visit_meth(self) - # helper function for nodes that have only one subnode: - if len(self.nodes) == 1: - return self.nodes[0].visit(visitor) - raise RuntimeError("Unknonw Visitor for %r" % self.name) - - def expand(self): - return [ self ] - - def totuple(self, lineno=False ): - symvalue = SYMBOLS.get( self.name, (0, self.name) ) - l = [ symvalue ] - l += [node.totuple(lineno) for node in self.nodes] - return tuple(l) - - -class TempSyntaxNode(SyntaxNode): - """A temporary syntax node to represent intermediate rules""" - def expand(self): - return self.nodes - -class TokenNode(SyntaxNode): - """A token node""" - def __init__(self, name, source, value): - SyntaxNode.__init__(self, name, source, []) - self.value = value - - def dumptree(self, treenodes, indent): - if self.value: - treenodes.append("%s='%s' (%d) " % (self.name, self.value, self.lineno)) - else: - treenodes.append("'%s' (%d) " % (self.name, self.lineno)) - - def __repr__(self): - if self.value is not None: - return "<%s=%s>" % ( self.name, repr(self.value)) - else: - return "<%s!>" % (self.name,) - - def totuple(self, lineno=False): - num = TOKEN_MAP.get(self.name, -1) - if num == -1: - print "Unknown", self.name, self.value - if self.value is not None: - val = self.value - else: - if self.name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): - val = self.name - else: - val = self.value or '' - if lineno: - return (num, val, self.lineno) - else: - return (num, val) Deleted: /pypy/dist/pypy/module/recparser/test_lookahead.py ============================================================================== --- /pypy/dist/pypy/module/recparser/test_lookahead.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,84 +0,0 @@ -from pypy.module.recparser.grammar import Alternative, Sequence, KleenStar, \ - Token, EmptyToken, build_first_sets - -class TestLookAheadBasics: - - def setup_method(self, method): - self.tok1 = Token('t1', 'foo') - self.tok2 = Token('t2', 'bar') - self.tok3 = Token('t3', 'foobar') - self.tokens = [self.tok1, self.tok2, self.tok3] - build_first_sets(self.tokens) - - def test_basic_token(self): - assert self.tok1.first_set == [self.tok1] - - - def test_basic_alternative(self): - alt = Alternative('alt', self.tokens) - build_first_sets([alt]) - assert alt.first_set == self.tokens - - - def test_basic_sequence(self): - seq = Sequence('seq', self.tokens) - build_first_sets([seq]) - assert seq.first_set == [self.tokens[0]] - - def test_basic_kleenstar(self): - tok1, tok2, tok3 = self.tokens - kstar = KleenStar('kstar', 1, 3, tok1) - build_first_sets([kstar]) - assert kstar.first_set == [tok1] - kstar = KleenStar('kstar', 0, 3, tok1) - build_first_sets([kstar]) - assert kstar.first_set == [tok1, EmptyToken] - - - def test_maybe_empty_sequence(self): - """S -> tok1{0,2} tok2{0,2} - ==> S.first_set = [tok1, tok2, EmptyToken] - """ - tok1, tok2, tok3 = self.tokens - k1 = KleenStar('k1', 0, 2, tok1) - k2 = KleenStar('k1', 0, 2, tok2) - seq = Sequence('seq', [k1, k2]) - build_first_sets([k1, k2, seq]) - assert seq.first_set == [tok1, tok2, EmptyToken] - - - def test_not_empty_sequence(self): - """S -> tok1{0,2} tok2{1,2} - ==> S.first_set = [tok1, tok2] - """ - tok1, tok2, tok3 = self.tokens - k1 = KleenStar('k1', 0, 2, tok1) - k2 = KleenStar('k1', 1, 2, tok2) - seq = Sequence('seq', [k1, k2]) - build_first_sets([k1, k2, seq]) - assert seq.first_set == [tok1, tok2] - -def test_token_comparison(): - assert Token('t1', 'foo') == Token('t1', 'foo') - assert Token('t1', 'foo') != Token('t2', 'foo') - assert Token('t2', 'foo') != Token('t1', None) - - -class TestLookAhead: - - def setup_method(self, method): - self.LOW = Token('LOW', 'low') - self.CAP = Token('CAP' ,'cap') - self.A = Alternative('A', []) - k1 = KleenStar('k1', 0, rule=self.LOW) - k2 = KleenStar('k2', 0, rule=self.CAP) - self.B = Sequence('B', [k1, self.A]) - self.C = Sequence('C', [k2, self.A]) - self.A.args = [self.B, self.C] - build_first_sets([self.A, self.B, self.C, self.LOW, self.CAP, k1, k2]) - - def test_S_first_set(self): - for s in [Token('LOW', 'low'), EmptyToken, Token('CAP', 'cap')]: - assert s in self.A.first_set - assert s in self.B.first_set - assert s in self.C.first_set Deleted: /pypy/dist/pypy/module/recparser/tuplebuilder.py ============================================================================== --- /pypy/dist/pypy/module/recparser/tuplebuilder.py Sun Jul 3 11:38:44 2005 +++ (empty file) @@ -1,118 +0,0 @@ - -from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET - -## -## def _expand_nodes(nodes): -## expanded = [] -## for n in nodes: -## if n[0] == -2: -## # expanded.extend(expand_nodes(n[1:])) -## expanded.extend(n[1:]) -## else: -## expanded.append(n) -## return tuple(expanded) -## -## def expand_nodes(nodes): -## r = _expand_nodes(nodes) -## for n in nodes: -## assert type(n[0]) == int -## return r -## - -class StackElement: - """wraps TupleBuilder's tuples""" - -class Terminal(StackElement): - def __init__(self, num, value, lineno=-1): - self.nodes = [(num, value, lineno)] - self.num = num - - def as_tuple(self, lineno=None): - if lineno is not None: - return self.nodes[0] - else: - return self.nodes[0][:-1] - -class NonTerminal(StackElement): - def __init__(self, num, nodes, rulename=None): - """rulename should always be None with regular Python grammar""" - self.nodes = nodes - self.num = num - - def as_tuple(self, lineno=None): - l = [self.num] + [node.as_tuple(lineno) for node in self.nodes] - return tuple(l) - - -def expand_nodes(stack_elements): - """generate a nested tuples from a list of stack elements""" - expanded = [] - for element in stack_elements: - if isinstance(element, NonTerminal) and element.num == -2: - expanded.extend(element.nodes) - else: - expanded.append(element) - return expanded - -class TupleBuilder(BaseGrammarBuilder): - """A builder that directly produce the AST""" - - def __init__(self, rules=None, debug=0, lineno=True): - BaseGrammarBuilder.__init__(self, rules, debug) - # This attribute is here for convenience - self.source_encoding = None - self.lineno = lineno - self._unknown = -10 - - def _add_rule(self, rulename): - SYMBOLS[rulename] = self._unknown - self._unknown -= 1 - - def alternative(self, rule, source): - # Do nothing, keep rule on top of the stack - if rule.is_root(): - nodes = expand_nodes( [self.stack[-1]] ) - if rule.name in SYMBOLS: - self.stack[-1] = NonTerminal(SYMBOLS[rule.name], nodes) - else: - # Using regular CPython's Grammar should not lead here - # XXX find how self._unknown is meant to be used - self.stack[-1] = NonTerminal(self._unknown, nodes, rule.name) - self._add_rule(rule.name) - return True - - def sequence(self, rule, source, elts_number): - """ """ - if rule.is_root(): - if rule.name in SYMBOLS: - num = SYMBOLS[rule.name] - node = [num] - else: - num = self._unknown - node = [num] - self._add_rule(rule.name) - else: - num = -2 - node = [num] - if elts_number > 0: - sequence_elements = self.stack[-elts_number:] - nodes = expand_nodes( sequence_elements ) - self.stack[-elts_number:] = [NonTerminal(num, nodes)] - else: - self.stack.append( NonTerminal(num, []) ) - return True - - def token(self, name, value, source): - num = TOKEN_MAP.get(name, -1) - lineno = source.current_line() - if value is None: - if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): - value = name - else: - value = '' - if self.lineno: - self.stack.append( Terminal(num, value, lineno) ) - else: - self.stack.append( Terminal(num, value, -1) ) - return True From adim at codespeak.net Sun Jul 3 11:45:51 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 11:45:51 +0200 (CEST) Subject: [pypy-svn] r14117 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050703094551.6426B27B42@code1.codespeak.net> Author: adim Date: Sun Jul 3 11:45:48 2005 New Revision: 14117 Added: pypy/dist/pypy/interpreter/pyparser/__init__.py Log: added missing __init__ file Added: pypy/dist/pypy/interpreter/pyparser/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/__init__.py Sun Jul 3 11:45:48 2005 @@ -0,0 +1 @@ +# empty From ludal at codespeak.net Sun Jul 3 11:52:44 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 11:52:44 +0200 (CEST) Subject: [pypy-svn] r14118 - pypy/dist/pypy/interpreter/test Message-ID: <20050703095244.AF69627B42@code1.codespeak.net> Author: ludal Date: Sun Jul 3 11:52:42 2005 New Revision: 14118 Modified: pypy/dist/pypy/interpreter/test/test_compiler.py Log: fixed test_compiler broken after compiler->pycompiler renaming Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Sun Jul 3 11:52:42 2005 @@ -1,7 +1,7 @@ import __future__ import autopath import py -from pypy.interpreter.compiler import CPythonCompiler, Compiler +from pypy.interpreter.pycompiler import CPythonCompiler, Compiler from pypy.interpreter.pycode import PyCode From nik at codespeak.net Sun Jul 3 12:04:04 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Sun, 3 Jul 2005 12:04:04 +0200 (CEST) Subject: [pypy-svn] r14120 - in pypy/branch/dist-2.4.1: lib-python lib-python/modified-2.4.1/test pypy/module/__builtin__ Message-ID: <20050703100404.91A3C27B40@code1.codespeak.net> Author: nik Date: Sun Jul 3 12:04:02 2005 New Revision: 14120 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_set.py - copied, changed from r14069, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_set.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_sets.py Removed: pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py Log: (tic, nik) Implemented set/frozenset builtin types based on the sets module. Modified: pypy/branch/dist-2.4.1/lib-python/conftest.py ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/conftest.py (original) +++ pypy/branch/dist-2.4.1/lib-python/conftest.py Sun Jul 3 12:04:02 2005 @@ -632,6 +632,7 @@ RegrTest('test_select.py', enabled=False, dumbtest=1), RegrTest('test_set.py', enabled=True, core=True), RegrTest('test_sets.py', enabled=True, core=True), + RegrTest('test_set.py', enabled=True, core=True), RegrTest('test_sgmllib.py', enabled=True, core=True), RegrTest('test_sha.py', enabled=True), # one test is taken out (too_slow_test_case_3), rest passses Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_set.py (from r14069, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_set.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_set.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_set.py Sun Jul 3 12:04:02 2005 @@ -1,6 +1,6 @@ import unittest from test import test_support -from weakref import proxy +#from weakref import proxy import operator import copy import pickle @@ -359,7 +359,8 @@ else: self.assert_(c not in self.s) - def test_weakref(self): + # XXX disabled until weakref works + def XXXtest_weakref(self): s = self.thetype('gallahad') p = proxy(s) self.assertEqual(str(p), str(s)) @@ -407,7 +408,8 @@ f = self.thetype('abcdcda') self.assertEqual(hash(f), hash(f)) - def test_hash_effectiveness(self): + # disabled since it depends on CPython specific hash algorithm + def _test_hash_effectiveness(self): n = 13 hashvalues = set() addhashvalue = hashvalues.add @@ -1270,7 +1272,7 @@ def test_constructor(self): for cons in (set, frozenset): - for s in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5)): + for s in ("123", "", range(100), ('do', 1.2), xrange(2000,2200,5)): for g in (G, I, Ig, S, L, R): self.assertEqual(sorted(cons(g(s))), sorted(g(s))) self.assertRaises(TypeError, cons , X(s)) @@ -1279,7 +1281,7 @@ def test_inline_methods(self): s = set('november') - for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'): + for data in ("123", "", range(100), ('do', 1.2), xrange(2000,2200,5), 'december'): for meth in (s.union, s.intersection, s.difference, s.symmetric_difference): for g in (G, I, Ig, L, R): expected = meth(data) @@ -1290,7 +1292,7 @@ self.assertRaises(ZeroDivisionError, meth, E(s)) def test_inplace_methods(self): - for data in ("123", "", range(1000), ('do', 1.2), xrange(2000,2200,5), 'december'): + for data in ("123", "", range(100), ('do', 1.2), xrange(2000,2200,5), 'december'): for methname in ('update', 'intersection_update', 'difference_update', 'symmetric_difference_update'): for g in (G, I, Ig, S, L, R): Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/__init__.py Sun Jul 3 12:04:02 2005 @@ -49,6 +49,9 @@ 'intern' : 'app_misc.intern', 'buffer' : 'app_buffer.buffer', 'reload' : 'app_misc.reload', + + 'set' : 'app_sets.set', + 'frozenset' : 'app_sets.frozenset', } interpleveldefs = { @@ -64,8 +67,6 @@ 'file' : '(space.wrap(file))', 'open' : '(space.wrap(file))', 'unicode' : '(space.w_unicode)', - 'set' : '(settype.mk_set(space))', - 'frozenset' : '(settype.mk_frozenset(space))', # old-style classes dummy support '_classobj' : 'space.w_classobj', Added: pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_sets.py ============================================================================== --- (empty file) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_sets.py Sun Jul 3 12:04:02 2005 @@ -0,0 +1,607 @@ +# NOT_RPYTHON +""" +This emulates CPython's set and frozenset types based on the current sets +module. Diff against the sets module to find specific changes. Here's some +pointers: + +- __slots__ as well as __setstate__/__getstate__ were removed from the set + classes to support pickling in conjunction with __reduce__. +- non-operator methods like (update, issubset, issuperset - see the set type + documentation for a full list) now accept iterables in addition to just other + sets. +- copy semantics for frozensets according to the frozenset type from CPython +- the hash algorithm for CPython's frozenset was not implemented because it + relies on integer overflows. + +This whole module should probably be converted to RPython at some point in the +future. + +The following is the original docstring from sets.py: + +Classes to represent arbitrary sets (including sets of sets). + +This module implements sets using dictionaries whose values are +ignored. The usual operations (union, intersection, deletion, etc.) +are provided as both methods and operators. + +Important: sets are not sequences! While they support 'x in s', +'len(s)', and 'for x in s', none of those operations are unique for +sequences; for example, mappings support all three as well. The +characteristic operation for sequences is subscripting with small +integers: s[i], for i in range(len(s)). Sets don't support +subscripting at all. Also, sequences allow multiple occurrences and +their elements have a definite order; sets on the other hand don't +record multiple occurrences and don't remember the order of element +insertion (which is why they don't support s[i]). + +The following classes are provided: + +BaseSet -- All the operations common to both mutable and immutable + sets. This is an abstract class, not meant to be directly + instantiated. + +set -- Mutable sets, subclass of BaseSet; not hashable. + +frozenset -- Immutable sets, subclass of BaseSet; hashable. + An iterable argument is mandatory to create an frozenset. + +_TemporarilyImmutableSet -- A wrapper around a Set, hashable, + giving the same hash value as the immutable set equivalent + would have. Do not use this class directly. + +Only hashable objects can be added to a set. In particular, you cannot +really add a set as an element to another set; if you try, what is +actually added is an frozenset built from it (it compares equal to +the one you tried adding). + +When you ask if `x in y' where x is a Set and y is a Set or +frozenset, x is wrapped into a _TemporarilyImmutableSet z, and +what's tested is actually `z in y'. + +""" + +# Code history: +# +# - Greg V. Wilson wrote the first version, using a different approach +# to the mutable/immutable problem, and inheriting from dict. +# +# - Alex Martelli modified Greg's version to implement the current +# Set/frozenset approach, and make the data an attribute. +# +# - Guido van Rossum rewrote much of the code, made some API changes, +# and cleaned up the docstrings. +# +# - Raymond Hettinger added a number of speedups and other +# improvements. + +from __future__ import generators +try: + from itertools import ifilter, ifilterfalse +except ImportError: + # Code to make the module run under Py2.2 + def ifilter(predicate, iterable): + if predicate is None: + def predicate(x): + return x + for x in iterable: + if predicate(x): + yield x + def ifilterfalse(predicate, iterable): + if predicate is None: + def predicate(x): + return x + for x in iterable: + if not predicate(x): + yield x + try: + True, False + except NameError: + True, False = (0==0, 0!=0) + +__all__ = ['set', 'frozenset'] + +class BaseSet(object): + """Common base class for mutable and immutable sets.""" + + # Constructor + + def __init__(self): + """This is an abstract class.""" + # Don't call this from a concrete subclass! + if self.__class__ is BaseSet: + raise TypeError, ("BaseSet is an abstract class. " + "Use set or frozenset.") + + # Standard protocols: __len__, __repr__, __str__, __iter__, __reduce__ + + def __len__(self): + """Return the number of elements of a set.""" + return len(self._data) + + def __repr__(self): + """Return string representation of a set. + + This looks like 'set([])'. + """ + return self._repr() + + # __str__ is the same as __repr__ + __str__ = __repr__ + + def _repr(self, sorted=False): + elements = self._data.keys() + if sorted: + elements.sort() + return '%s(%r)' % (self.__class__.__name__, elements) + + def __iter__(self): + """Return an iterator over the elements or a set. + + This is the keys iterator for the underlying dict. + """ + return self._data.iterkeys() + + def __reduce__(self): + return (self.__class__, (self._data.keys(),), self.__dict__) + + # Three-way comparison is not supported. However, because __eq__ is + # tried before __cmp__, if set x == set y, x.__eq__(y) returns True and + # then cmp(x, y) returns 0 (Python doesn't actually call __cmp__ in this + # case). + + def __cmp__(self, other): + raise TypeError, "can't compare sets using cmp()" + + # Equality comparisons using the underlying dicts. Mixed-type comparisons + # are allowed here, where set == z for non-set z always returns False, + # and set != z always True. This allows expressions like "x in y" to + # give the expected result when y is a sequence of mixed types, not + # raising a pointless TypeError just because y contains a set, or x is + # a set and y contain's a non-set ("in" invokes only __eq__). + # Subtle: it would be nicer if __eq__ and __ne__ could return + # NotImplemented instead of True or False. Then the other comparand + # would get a chance to determine the result, and if the other comparand + # also returned NotImplemented then it would fall back to object address + # comparison (which would always return False for __eq__ and always + # True for __ne__). However, that doesn't work, because this type + # *also* implements __cmp__: if, e.g., __eq__ returns NotImplemented, + # Python tries __cmp__ next, and the __cmp__ here then raises TypeError. + + def __eq__(self, other): + if isinstance(other, BaseSet): + return self._data == other._data + else: + return False + + def __ne__(self, other): + if isinstance(other, BaseSet): + return self._data != other._data + else: + return True + + # Copying operations + + def copy(self): + """Return a shallow copy of a set.""" + result = self.__class__() + result._data.update(self._data) + return result + + __copy__ = copy # For the copy module + + def __deepcopy__(self, memo): + """Return a deep copy of a set; used by copy module.""" + # This pre-creates the result and inserts it in the memo + # early, in case the deep copy recurses into another reference + # to this same set. A set can't be an element of itself, but + # it can certainly contain an object that has a reference to + # itself. + from copy import deepcopy + result = self.__class__() + memo[id(self)] = result + data = result._data + value = True + for elt in self: + data[deepcopy(elt, memo)] = value + return result + + # Standard set operations: union, intersection, both differences. + # Each has an operator version (e.g. __or__, invoked with |) and a + # method version (e.g. union). + # Subtle: Each pair requires distinct code so that the outcome is + # correct when the type of other isn't suitable. For example, if + # we did "union = __or__" instead, then set().union(3) would return + # NotImplemented instead of raising TypeError (albeit that *why* it + # raises TypeError as-is is also a bit subtle). + + def __or__(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.union(other) + + def union(self, other): + """Return the union of two sets as a new set. + + (I.e. all elements that are in either set.) + """ + result = self.__class__(self) + result._update(other) + return result + + def __and__(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.intersection(other) + + def intersection(self, other): + """Return the intersection of two sets as a new set. + + (I.e. all elements that are in both sets.) + """ + if not isinstance(other, BaseSet): + other = set(other) + if len(self) <= len(other): + little, big = self, other + else: + little, big = other, self + common = ifilter(big._data.has_key, little) + return self.__class__(common) + + def __xor__(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.symmetric_difference(other) + + def symmetric_difference(self, other): + """Return the symmetric difference of two sets as a new set. + + (I.e. all elements that are in exactly one of the sets.) + """ + result = self.__class__() + data = result._data + value = True + selfdata = self._data + try: + otherdata = other._data + except AttributeError: + otherdata = set(other)._data + for elt in ifilterfalse(otherdata.has_key, selfdata): + data[elt] = value + for elt in ifilterfalse(selfdata.has_key, otherdata): + data[elt] = value + return result + + def __sub__(self, other): + """Return the difference of two sets as a new set. + + (I.e. all elements that are in this set and not in the other.) + """ + if not isinstance(other, BaseSet): + return NotImplemented + return self.difference(other) + + def difference(self, other): + """Return the difference of two sets as a new set. + + (I.e. all elements that are in this set and not in the other.) + """ + result = self.__class__() + data = result._data + try: + otherdata = other._data + except AttributeError: + otherdata = set(other)._data + value = True + for elt in ifilterfalse(otherdata.has_key, self): + data[elt] = value + return result + + # Membership test + + def __contains__(self, element): + """Report whether an element is a member of a set. + + (Called in response to the expression `element in self'.) + """ + try: + return element in self._data + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + return transform() in self._data + + # Subset and superset test + + def issubset(self, other): + """Report whether another set contains this set.""" + if not isinstance(other, BaseSet): + # other is an iterable + other = self.__class__(other) + if len(self) > len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(other._data.has_key, self): + return False + return True + + def issuperset(self, other): + """Report whether this set contains another set.""" + if not isinstance(other, BaseSet): + # other is an iterable + other = self.__class__(other) + if len(self) < len(other): # Fast check for obvious cases + return False + for elt in ifilterfalse(self._data.has_key, other): + return False + return True + + # Inequality comparisons using the is-subset relation. + def __le__(self, other): + self._binary_sanity_check(other) + return self.issubset(other) + + def __ge__(self, other): + self._binary_sanity_check(other) + return self.issuperset(other) + + def __lt__(self, other): + self._binary_sanity_check(other) + return len(self) < len(other) and self.issubset(other) + + def __gt__(self, other): + self._binary_sanity_check(other) + return len(self) > len(other) and self.issuperset(other) + + # Assorted helpers + + def _binary_sanity_check(self, other): + # Check that the other argument to a binary operation is also + # a set, raising a TypeError otherwise. + if not isinstance(other, BaseSet): + raise TypeError, "Binary operation only permitted between sets" + + def _compute_hash(self): + # Calculate hash code for a set by xor'ing the hash codes of + # the elements. This ensures that the hash code does not depend + # on the order in which elements are added to the set. This is + # not called __hash__ because a BaseSet should not be hashable; + # only an frozenset is hashable. + result = 0 + for elt in self: + result ^= hash(elt) + return result + + def _update(self, iterable): + # The main loop for update() and the subclass __init__() methods. + data = self._data + + # Use the fast update() method when a dictionary is available. + if isinstance(iterable, BaseSet): + data.update(iterable._data) + return + + value = True + + if type(iterable) in (list, tuple, xrange): + # Optimized: we know that __iter__() and next() can't + # raise TypeError, so we can move 'try:' out of the loop. + it = iter(iterable) + while True: + try: + for element in it: + data[element] = value + return + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + else: + # Safe: only catch TypeError where intended + for element in iterable: + try: + data[element] = value + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + data[transform()] = value + + +class frozenset(BaseSet): + """Immutable set class.""" + + # BaseSet + hashing + + def __new__(cls, iterable=None): + if type(iterable) is frozenset: + return iterable + instance = BaseSet.__new__(cls) + frozenset._init(instance, iterable) + return instance + + def __init__(self, iterable=None): + pass + + def _init(self, iterable=None): + """Construct an immutable set from an optional iterable.""" + self._hashcode = None + self._data = {} + if iterable is not None: + self._update(iterable) + + def __hash__(self): + if self._hashcode is None: + self._hashcode = self._compute_hash() + return self._hashcode + + def union(self, other): + return BaseSet.union(BaseSet.copy(self), other) + + def copy(self): + if type(self) is frozenset: + return self + else: + return self.__class__(self) + + __copy__ = copy + +class set(BaseSet): + """ Mutable set class.""" + + # BaseSet + operations requiring mutability; no hashing + + def __init__(self, iterable=None): + """Construct a set from an optional iterable.""" + self._data = {} + if iterable is not None: + self._update(iterable) + + def __hash__(self): + """A set cannot be hashed.""" + # We inherit object.__hash__, so we must deny this explicitly + raise TypeError, "Can't hash a set, only an frozenset." + + # In-place union, intersection, differences. + # Subtle: The xyz_update() functions deliberately return None, + # as do all mutating operations on built-in container types. + # The __xyz__ spellings have to return self, though. + + def __ior__(self, other): + """Update a set with the union of itself and another.""" + self._binary_sanity_check(other) + self._data.update(other._data) + return self + + def union_update(self, other): + """Update a set with the union of itself and another.""" + self._update(other) + + def __iand__(self, other): + """Update a set with the intersection of itself and another.""" + self._binary_sanity_check(other) + self._data = (self & other)._data + return self + + def intersection_update(self, other): + """Update a set with the intersection of itself and another.""" + if isinstance(other, BaseSet): + self &= other + else: + self._data = (self.intersection(other))._data + + def __ixor__(self, other): + """Update a set with the symmetric difference of itself and another.""" + self._binary_sanity_check(other) + self.symmetric_difference_update(other) + return self + + def symmetric_difference_update(self, other): + """Update a set with the symmetric difference of itself and another.""" + data = self._data + value = True + if not isinstance(other, BaseSet): + other = set(other) + for elt in other: + if elt in data: + del data[elt] + else: + data[elt] = value + + def __isub__(self, other): + """Remove all elements of another set from this set.""" + self._binary_sanity_check(other) + self.difference_update(other) + return self + + def difference_update(self, other): + """Remove all elements of another set from this set.""" + data = self._data + if not isinstance(other, BaseSet): + other = set(other) + for elt in ifilter(data.has_key, other): + del data[elt] + + # Python dict-like mass mutations: update, clear + + def update(self, iterable): + """Add all values from an iterable (such as a list or file).""" + self._update(iterable) + + def clear(self): + """Remove all elements from this set.""" + self._data.clear() + + # Single-element mutations: add, remove, discard + + def add(self, element): + """Add an element to a set. + + This has no effect if the element is already present. + """ + try: + self._data[element] = True + except TypeError: + transform = getattr(element, "__as_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + self._data[transform()] = True + + def remove(self, element): + """Remove an element from a set; it must be a member. + + If the element is not a member, raise a KeyError. + """ + try: + del self._data[element] + except TypeError: + transform = getattr(element, "__as_temporarily_immutable__", None) + if transform is None: + raise # re-raise the TypeError exception we caught + del self._data[transform()] + + def discard(self, element): + """Remove an element from a set if it is a member. + + If the element is not a member, do nothing. + """ + try: + self.remove(element) + except KeyError: + pass + + def pop(self): + """Remove and return an arbitrary set element.""" + return self._data.popitem()[0] + + def __as_immutable__(self): + # Return a copy of self as an immutable set + return frozenset(self) + + def __as_temporarily_immutable__(self): + # Return self wrapped in a temporarily immutable set + return _TemporarilyImmutableSet(self) + + +class _TemporarilyImmutableSet(BaseSet): + # Wrap a mutable set as if it was temporarily immutable. + # This only supplies hashing and equality comparisons. + + def __init__(self, set): + self._set = set + self._data = set._data # Needed by frozenset.__eq__() + + def __hash__(self): + return self._set._compute_hash() Deleted: /pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/__builtin__/settype.py Sun Jul 3 12:04:02 2005 +++ (empty file) @@ -1,13 +0,0 @@ -from pypy.interpreter import gateway - -applevel = gateway.applevel(''' -def mk_set(): - import sets - return sets.Set - -def mk_frozenset(): - import sets - return sets.ImmutableSet -''') -mk_set = applevel.interphook('mk_set') -mk_frozenset = applevel.interphook('mk_frozenset') From cfbolz at codespeak.net Sun Jul 3 12:23:55 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 3 Jul 2005 12:23:55 +0200 (CEST) Subject: [pypy-svn] r14121 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050703102355.5D22027B40@code1.codespeak.net> Author: cfbolz Date: Sun Jul 3 12:23:54 2005 New Revision: 14121 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: added support for functions returning void. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 12:23:54 2005 @@ -1,9 +1,10 @@ import py from pypy.rpython import lltype -from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.node import LLVMNode log = log.structnode -class ArrayTypeNode(object): +class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): self.db = db @@ -28,7 +29,7 @@ # Each ArrayNode is a global constant. This needs to have a specific type of # a certain type. -class ArrayNode(object): +class ArrayNode(LLVMNode): _issetup = False array_counter = 0 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 3 12:23:54 2005 @@ -61,7 +61,10 @@ self.append("}") def ret(self, type_, ref): - self.indent("ret %s %s" % (type_, ref)) + self.indent("ret %s %s" % (type_, ref)) + + def ret_void(self): + self.indent("ret void") def phi(self, targetvar, type_, refs, blocknames): assert targetvar.startswith('%') @@ -79,6 +82,10 @@ self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref, ", ".join(arglist))) + def call_void(self, functionref, argrefs, argtypes): + arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] + self.indent("call void %s(%s)" % (functionref, ", ".join(arglist))) + def cast(self, targetvar, fromtype, fromvar, targettype): self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 3 12:23:54 2005 @@ -11,7 +11,8 @@ lltype.Char: "sbyte", lltype.Unsigned: "uint", lltype.Bool: "bool", - lltype.Float: "double" } + lltype.Float: "double", + lltype.Void: "void"} class Database(object): def __init__(self, translator): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 12:23:54 2005 @@ -115,7 +115,8 @@ names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] - codewriter.phi(arg, type_, names, blocknames) + if type_ != "void": + codewriter.phi(arg, type_, names, blocknames) def write_block_branches(self, codewriter, block): if len(block.exits) == 1: @@ -138,7 +139,10 @@ self.write_block_phi_nodes(codewriter, block) inputargtype = self.db.repr_arg_type(block.inputargs[0]) inputarg = self.db.repr_arg(block.inputargs[0]) - codewriter.ret(inputargtype, inputarg) + if inputargtype != "void": + codewriter.ret(inputargtype, inputarg) + else: + codewriter.ret_void() class OpWriter(object): binary_operations = {'int_mul': 'mul', @@ -233,8 +237,11 @@ functionref = self.db.repr_arg(op.args[0]) argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - self.codewriter.call(targetvar, returntype, functionref, argrefs, - argtypes) + if returntype != "void": + self.codewriter.call(targetvar, returntype, functionref, argrefs, + argtypes) + else: + self.codewriter.call_void(functionref, argrefs, argtypes) def malloc(self, op): targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 12:23:54 2005 @@ -89,6 +89,15 @@ 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 @@ -209,7 +218,7 @@ f = compile_function(char_constant, []) assert f() == 7 -def DONOT_test_list_getitem(): +def Xtest_list_getitem(): def list_getitem(i): l = [1,2,i] return l[i] @@ -218,11 +227,11 @@ assert f(1) == 2 assert f(3) == 3 -def DONOT_test_string_getitem1(): +def Xtest_string_getitem1(): l = "Hello, World" def string_test(i): return l[i] - f = compile_function(string_test, [int], view=True) + f = compile_function(string_test, [int], view=False) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From adim at codespeak.net Sun Jul 3 12:24:39 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 12:24:39 +0200 (CEST) Subject: [pypy-svn] r14122 - in pypy/dist/pypy: interpreter interpreter/test tool Message-ID: <20050703102439.BCE0927B40@code1.codespeak.net> Author: adim Date: Sun Jul 3 12:24:37 2005 New Revision: 14122 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/executioncontext.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/interpreter/test/test_compiler.py pypy/dist/pypy/tool/option.py Log: added options fields to choose which compiler / parser should be used. (For now, only the cpython parser/compiler can be run) Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Jul 3 12:24:37 2005 @@ -1,9 +1,12 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments +from pypy.interpreter.pycompiler import CPythonCompiler +from pypy.interpreter.pycompiler import PythonCompiler, PyPyCompiler from pypy.interpreter.miscutils import ThreadLocals from pypy.tool.cache import Cache from pypy.rpython.rarithmetic import r_uint +import pypy.tool.option __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'BaseWrappable', 'W_Root'] @@ -92,12 +95,17 @@ full_exceptions = True # full support for exceptions (normalization & more) - def __init__(self): + def __init__(self, options=None): "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() # set recursion limit # sets all the internal descriptors + + # XXX: Options in option.py is replaced by a function so + # it's not really clean to do a from option import Options + # since changing import order can change the Options object + self.options = options or pypy.tool.option.Options() self.initialize() def __repr__(self): @@ -134,9 +142,11 @@ #self.setbuiltinmodule('_codecs') # XXX we need to resolve unwrapping issues to # make this the default _sre module - #self.setbuiltinmodule("_sre", "_sre_pypy") - - # XXX disabled: self.setbuiltinmodule('parser') + #self.setbuiltinmodule("_sre", "_sre_pypy") + if self.options.parser == "recparser": + self.setbuiltinmodule('parser', 'recparser') + elif self.options.parser == "parser": + self.setbuiltinmodule('parser') # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): @@ -177,6 +187,20 @@ "Factory function for execution contexts." return ExecutionContext(self) + def createcompiler(self): + "Factory function creating a compiler object." + if self.options.parser == 'recparser': + if self.options.compiler == 'cpython': + return PythonCompiler(self) + else: + return PyPyCompiler(self) + elif self.options.compiler == 'recparser': + # <=> options.parser == 'cpython' + return PythonCompiler(self) + else: + # <=> options.compiler == 'cpython' and options.parser == 'cpython' + return CPythonCompiler(self) + # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses # may also override specific functions for performance. Modified: pypy/dist/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/dist/pypy/interpreter/executioncontext.py (original) +++ pypy/dist/pypy/interpreter/executioncontext.py Sun Jul 3 12:24:37 2005 @@ -1,7 +1,6 @@ import sys from pypy.interpreter.miscutils import Stack from pypy.interpreter.error import OperationError -from pypy.interpreter.pycompiler import CPythonCompiler class ExecutionContext: """An ExecutionContext holds the state of an execution thread @@ -14,7 +13,7 @@ self.w_tracefunc = None self.w_profilefunc = None self.is_tracing = 0 - self.compiler = CPythonCompiler(space) + self.compiler = space.createcompiler() def enter(self, frame): if self.framestack.depth() > self.space.sys.recursionlimit: Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Sun Jul 3 12:24:37 2005 @@ -6,7 +6,7 @@ from pypy.interpreter.error import OperationError -class Compiler: +class AbstractCompiler: """Abstract base class for a bytecode compiler.""" # The idea is to grow more methods here over the time, @@ -80,11 +80,14 @@ import warnings import __future__ compiler_flags = 0 +compiler_features = {} for fname in __future__.all_feature_names: - compiler_flags |= getattr(__future__, fname).compiler_flag + flag = getattr(__future__, fname).compiler_flag + compiler_flags |= flag + compiler_features[fname] = flag -class CPythonCompiler(Compiler): +class CPythonCompiler(AbstractCompiler): """Faked implementation of a compiler, using the underlying compile().""" def compile(self, source, filename, mode, flags): @@ -163,3 +166,75 @@ def restore_warn_explicit(self, warnings, old_warn_explicit): warnings.warn_explicit = old_warn_explicit + + +######## +import symbol +from compiler.transformer import Transformer +from compiler.pycodegen import ModuleCodeGenerator +from compiler.pycodegen import InteractiveCodeGenerator +from compiler.pycodegen import ExpressionCodeGenerator +from pyparser.pythonparse import parse_python_source, PYTHON_PARSER +from pyparser.tuplebuilder import TupleBuilder + +def pycompile(source, mode): + strings = [line+'\n' for line in source.split('\n')] + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) + if mode == 'exec': + target = 'file_input' + elif mode == 'single': + target = 'single_input' + else: # target == 'eval': + target = 'eval_input' + parse_python_source(strings, PYTHON_PARSER, target, builder) + # Note: The annotator can't follow the as_tuple() method call + nested_tuples = builder.stack[-1].as_tuple() + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return nested_tuples + +class PythonCompiler(CPythonCompiler): + """Uses the stdlib's python implementation of compiler""" + + def compile(self, source, filename, mode, flags): + flags |= __future__.generators.compiler_flag # always on (2.2 compat) + space = self.space + try: + transformer = Transformer() + tuples = pycompile(source, mode) + tree = transformer.compile_node(tuples) + compiler.misc.set_filename(filename, tree) + if mode == 'exec': + codegenerator = ModuleCodeGenerator(tree) + elif mode == 'single': + codegenerator = InteractiveCodeGenerator(tree) + else: # mode == 'eval': + codegenerator = ExpressionCodeGenerator(tree) + c = codegenerator.getCode() + # It would be nice to propagate all exceptions to app level, + # but here we only propagate the 'usual' ones, until we figure + # out how to do it generically. + except SyntaxError, e: + w_synerr = space.newtuple([space.wrap(e.msg), + space.newtuple([space.wrap(e.filename), + space.wrap(e.lineno), + space.wrap(e.offset), + space.wrap(e.text)])]) + raise OperationError(space.w_SyntaxError, w_synerr) + except ValueError,e: + raise OperationError(space.w_ValueError,space.wrap(str(e))) + except TypeError,e: + raise OperationError(space.w_TypeError,space.wrap(str(e))) + from pypy.interpreter.pycode import PyCode + return space.wrap(PyCode(space)._from_code(c)) + +# This doesn't work for now +class PyPyCompiler(CPythonCompiler): + """Uses the PyPy implementation of Compiler + + WRITEME + """ +# PyPyCompiler = PythonCompiler = CPythonCompiler +# PyPyCompiler = CPythonCompiler +# PythonCompiler = CPythonCompiler Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Sun Jul 3 12:24:37 2005 @@ -53,7 +53,7 @@ oparg = self.nextarg() fn(self, oparg) else: - fn = self.dispatch_table_no_arg[opcode] + fn = self.dispatch_table_no_arg[opcode] fn(self) def nextop(self): Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Sun Jul 3 12:24:37 2005 @@ -1,13 +1,13 @@ import __future__ import autopath import py -from pypy.interpreter.pycompiler import CPythonCompiler, Compiler +from pypy.interpreter.pycompiler import CPythonCompiler, PythonCompiler from pypy.interpreter.pycode import PyCode -class TestCompiler: +class BaseTestCompiler: def setup_method(self, method): - self.compiler = CPythonCompiler(self.space) + self.compiler = self.space.createcompiler() def test_compile(self): code = self.compiler.compile('6*7', '', 'eval', 0) @@ -48,6 +48,20 @@ assert flags == flags2 -class TestECCompiler(TestCompiler): +class TestECCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = self.space.getexecutioncontext().compiler + +class TestPyCCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = CPythonCompiler(self.space) + + +class SkippedForNowTestPurePythonCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = PythonCompiler(self.space) + + +class SkippedForNowTestPyPyCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = PyPyCompiler(self.space) Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Sun Jul 3 12:24:37 2005 @@ -10,6 +10,8 @@ spaces = [] oldstyle = 0 uselibfile = 0 + parser = "cpython" + compiler = "cpython" def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server @@ -67,7 +69,7 @@ except KeyError: module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) Space = module.Space - space = Space() + space = Space( Options() ) if name == 'std' and Options.oldstyle: space.enable_old_style_classes_as_default_metaclass() if Options.uselibfile: From niemeyer at codespeak.net Sun Jul 3 12:34:27 2005 From: niemeyer at codespeak.net (niemeyer at codespeak.net) Date: Sun, 3 Jul 2005 12:34:27 +0200 (CEST) Subject: [pypy-svn] r14123 - pypy/dist/pypy/translator/tool/pygame Message-ID: <20050703103427.6C88A27B41@code1.codespeak.net> Author: niemeyer Date: Sun Jul 3 12:34:26 2005 New Revision: 14123 Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py Log: - Implementing caching of bezier curve/arrow head/limit points on edges. - Implementing detection of visible nodes and edges, and now acting on those rather than on every node and edge whenever rendering and detecting objects under the cursor. Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/dist/pypy/translator/tool/pygame/drawgraph.py Sun Jul 3 12:34:26 2005 @@ -116,56 +116,77 @@ rest = rest[3:] self.style, self.color = rest self.highlight = False + self.cachedbezierpoints = None + self.cachedarrowhead = None + self.cachedlimits = None def sethighlight(self, which): self.highlight = bool(which) - def bezierpoints(self, resolution=8): - result = [] - pts = self.points - for i in range(0, len(pts)-3, 3): - result += beziercurve(pts[i], pts[i+1], - pts[i+2], pts[i+3], resolution) + def limits(self): + result = self.cachedlimits + if result is None: + points = self.bezierpoints() + xs = [point[0] for point in points] + ys = [point[1] for point in points] + self.cachedlimits = result = (min(xs), max(ys), max(xs), min(ys)) + return result + + def bezierpoints(self): + result = self.cachedbezierpoints + if result is None: + result = [] + pts = self.points + for i in range(0, len(pts)-3, 3): + result += beziercurve(pts[i], pts[i+1], pts[i+2], pts[i+3]) + self.cachedbezierpoints = result return result def arrowhead(self): - bottom_up = self.points[0][1] > self.points[-1][1] - if (self.tail.y > self.head.y) != bottom_up: # reversed edge - head = 0 - dir = 1 - else: - head = -1 - dir = -1 - n = 1 - while True: - try: - x0, y0 = self.points[head] - x1, y1 = self.points[head+n*dir] - except IndexError: - return [] - vx = x0-x1 - vy = y0-y1 - try: - f = 0.12 / math.sqrt(vx*vx + vy*vy) - vx *= f - vy *= f - return [(x0 + 0.9*vx, y0 + 0.9*vy), - (x0 + 0.4*vy, y0 - 0.4*vx), - (x0 - 0.4*vy, y0 + 0.4*vx)] - except (ZeroDivisionError, ValueError): - n += 1 + result = self.cachedarrowhead + if result is None: + bottom_up = self.points[0][1] > self.points[-1][1] + if (self.tail.y > self.head.y) != bottom_up: # reversed edge + head = 0 + dir = 1 + else: + head = -1 + dir = -1 + n = 1 + while True: + try: + x0, y0 = self.points[head] + x1, y1 = self.points[head+n*dir] + except IndexError: + result = [] + break + vx = x0-x1 + vy = y0-y1 + try: + f = 0.12 / math.sqrt(vx*vx + vy*vy) + vx *= f + vy *= f + result = [(x0 + 0.9*vx, y0 + 0.9*vy), + (x0 + 0.4*vy, y0 - 0.4*vx), + (x0 - 0.4*vy, y0 + 0.4*vx)] + break + except (ZeroDivisionError, ValueError): + n += 1 + self.cachedarrowhead = result + return result def beziercurve((x0,y0), (x1,y1), (x2,y2), (x3,y3), resolution=8): result = [] f = 1.0/(resolution-1) + append = result.append for i in range(resolution): t = f*i t0 = (1-t)*(1-t)*(1-t) t1 = t *(1-t)*(1-t) * 3.0 t2 = t * t *(1-t) * 3.0 t3 = t * t * t - result.append((x0*t0 + x1*t1 + x2*t2 + x3*t3, - y0*t0 + y1*t1 + y2*t2 + y3*t3)) + append((x0*t0 + x1*t1 + x2*t2 + x3*t3, + y0*t0 + y1*t1 + y2*t2 + y3*t3)) return result def segmentdistance((x0,y0), (x1,y1), (x,y)): @@ -173,16 +194,16 @@ vx = x1-x0 vy = y1-y0 try: - l = math.sqrt(vx*vx+vy*vy) + l = math.hypot(vx, vy) vx /= l vy /= l dlong = vx*(x-x0) + vy*(y-y0) except (ZeroDivisionError, ValueError): dlong = -1 if dlong < 0.0: - return math.sqrt((x-x0)*(x-x0) + (y-y0)*(y-y0)) + return math.hypot(x-x0, y-y0) elif dlong > l: - return math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1)) + return math.hypot(x-x1, y-y1) else: return abs(vy*(x-x0) - vx*(y-y0)) @@ -209,6 +230,8 @@ self.textzones = [] self.highlightwords = graphlayout.links self.highlight_word = None + self.visiblenodes = [] + self.visibleedges = [] def wordcolor(self, word): if word == self.highlight_word: @@ -298,8 +321,26 @@ coordinates may sometimes become longs and cause OverflowErrors within pygame. """ - return (x1 < self.width-self.ofsx and x2 > -self.ofsx and - y1 < self.height-self.ofsy and y2 > -self.ofsy) + w, h = self.screen.get_size() + return x1 < w and x2 > 0 and y1 < h and y2 > 0 + + def computevisible(self): + del self.visiblenodes[:] + del self.visibleedges[:] + w, h = self.screen.get_size() + for node in self.graphlayout.nodes.values(): + x, y = self.map(node.x, node.y) + nw2 = int(node.w * self.scale)//2 + nh2 = int(node.h * self.scale)//2 + if x-nw2 < w and x+nw2 > 0 and y-nh2 < h and y+nh2 > 0: + self.visiblenodes.append(node) + for edge in self.graphlayout.edges: + x1, y1, x2, y2 = edge.limits() + x1, y1 = self.map(x1, y1) + if x1 < w and y1 < h: + x2, y2 = self.map(x2, y2) + if x2 > 0 and y2 > 0: + self.visibleedges.append(edge) def map(self, x, y): return (int(x*self.scale) - (self.ofsx - self.margin), @@ -382,6 +423,14 @@ def cmd(): pygame.draw.rect(self.screen, fgcolor, rect, 1) commands.append(cmd) + elif node.shape == 'ellipse': + rect = (x-1, y-1, boxwidth+2, boxheight+2) + def cmd(): + pygame.draw.ellipse(self.screen, bgcolor, rect, 0) + bkgndcommands.append(cmd) + def cmd(): + pygame.draw.ellipse(self.screen, fgcolor, rect, 1) + commands.append(cmd) elif node.shape == 'octagon': step = 1-math.sqrt(2)/2 points = [(int(x+boxwidth*fx), int(y+boxheight*fy)) @@ -400,14 +449,15 @@ def draw_commands(self): nodebkgndcmd = [] nodecmd = [] - for node in self.graphlayout.nodes.values(): + for node in self.visiblenodes: cmd1, cmd2 = self.draw_node_commands(node) nodebkgndcmd += cmd1 nodecmd += cmd2 edgebodycmd = [] edgeheadcmd = [] - for edge in self.graphlayout.edges: + for edge in self.visibleedges: + fgcolor = getcolor(edge.color, (0,0,0)) if edge.highlight: fgcolor = highlight_color(fgcolor) @@ -435,6 +485,8 @@ return edgebodycmd + nodebkgndcmd + edgeheadcmd + nodecmd def render(self): + self.computevisible() + bbox = self.getboundingbox() self.screen.fill((224, 255, 224), bbox) @@ -478,7 +530,7 @@ def node_at_position(self, (x, y)): """Return the Node under the cursor.""" x, y = self.revmap(x, y) - for node in self.graphlayout.nodes.itervalues(): + for node in self.visiblenodes: if 2.0*abs(x-node.x) <= node.w and 2.0*abs(y-node.y) <= node.h: return node return None @@ -489,7 +541,7 @@ distmax /= self.scale xy = self.revmap(x, y) closest_edge = None - for edge in self.graphlayout.edges: + for edge in self.visibleedges: pts = edge.bezierpoints() for i in range(1, len(pts)): d = segmentdistance(pts[i-1], pts[i], xy) From hpk at codespeak.net Sun Jul 3 12:50:37 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 12:50:37 +0200 (CEST) Subject: [pypy-svn] r14124 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703105037.87B0E27B46@code1.codespeak.net> Author: hpk Date: Sun Jul 3 12:50:36 2005 New Revision: 14124 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/structnode.py Log: small renaming and a bit of docstrings Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 12:50:36 2005 @@ -70,7 +70,7 @@ return ", ".join(["%s %s" % (t, v) for t, v in res]) - def writedata(self, codewriter): + def writeglobalconstants(self, codewriter): lenitems = len(self.value.items) lenstr = ".%s" % lenitems codewriter.globalinstance(self.ref, Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jul 3 12:50:36 2005 @@ -31,7 +31,7 @@ nl(); comment("Global Data") ; nl() for typ_decl in db.getobjects(): - typ_decl.writedata(codewriter) + typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() for typ_decl in db.getobjects(): Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Sun Jul 3 12:50:36 2005 @@ -8,14 +8,18 @@ self._ref = ref ref = property(_get_ref, _set_ref) + # __________________ before "implementation" ____________________ def writedatatypedecl(self, codewriter): - pass + """ write out declare names of data types + (structs/arrays/function pointers) + """ - def writedata(self, codewriter): - pass + def writeglobalconstants(self, codewriter): + """ write out global values. """ def writedecl(self, codewriter): - pass + """ write function forward declarations. """ + # __________________ after "implementation" ____________________ def writeimpl(self, codewriter): - pass + """ write function implementations. """ Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sun Jul 3 12:50:36 2005 @@ -118,7 +118,7 @@ res.append((self.db.repr_arg_type(T), value)) return ", ".join(["%s %s" % (t, v) for t, v in res]) - def writedata(self, codewriter): + def writeglobalconstants(self, codewriter): codewriter.globalinstance(self.ref, self.db.repr_arg_type(self.value._TYPE), self.get_values()) From hpk at codespeak.net Sun Jul 3 12:53:24 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 12:53:24 +0200 (CEST) Subject: [pypy-svn] r14125 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703105324.23E5727B46@code1.codespeak.net> Author: hpk Date: Sun Jul 3 12:53:18 2005 New Revision: 14125 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: some assertions Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 12:53:18 2005 @@ -8,6 +8,7 @@ _issetup = False def __init__(self, db, array): self.db = db + assert isinstance(array, lltype.ArrayType) self.array = array self.ref_template = "%%array.%s" % array.OF self.ref = self.ref_template + ".0" Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 12:53:18 2005 @@ -13,6 +13,7 @@ def __init__(self, db, type_): self.db = db + assert isinstance(type_, lltype.FuncType) self.type_ = type_ ref = '"ft.%s.%s"' % (type_, FuncTypeNode.func_type_node_counter) self.ref = ref.replace(" ", "") From ludal at codespeak.net Sun Jul 3 13:09:15 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 13:09:15 +0200 (CEST) Subject: [pypy-svn] r14126 - in pypy/dist/pypy: interpreter interpreter/pyparser module/recparser tool translator/goal Message-ID: <20050703110915.3269327B46@code1.codespeak.net> Author: ludal Date: Sun Jul 3 13:09:12 2005 New Revision: 14126 Added: pypy/dist/pypy/module/recparser/astbuilder.py - copied unchanged from r14092, pypy/branch/pycompiler/module/recparser/astbuilder.py pypy/dist/pypy/module/recparser/codegen.py - copied unchanged from r14092, pypy/branch/pycompiler/module/recparser/codegen.py pypy/dist/pypy/translator/goal/targetparser.py - copied unchanged from r14092, pypy/branch/pycompiler/translator/goal/targetparser.py Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/module/recparser/__init__.py pypy/dist/pypy/tool/option.py Log: * added option to use pyparser from command line * misc cleanup Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Jul 3 13:09:12 2005 @@ -143,9 +143,9 @@ # XXX we need to resolve unwrapping issues to # make this the default _sre module #self.setbuiltinmodule("_sre", "_sre_pypy") - if self.options.parser == "recparser": - self.setbuiltinmodule('parser', 'recparser') - elif self.options.parser == "parser": + if self.options.useparsermodule == "recparser": + self.setbuiltinmodule('parser', 'recparser') + elif self.options.parsermodule == "parser": self.setbuiltinmodule('parser') # initialize with "bootstrap types" from objspace (e.g. w_None) @@ -194,7 +194,7 @@ return PythonCompiler(self) else: return PyPyCompiler(self) - elif self.options.compiler == 'recparser': + elif self.options.compiler == 'pyparse': # <=> options.parser == 'cpython' return PythonCompiler(self) else: Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Sun Jul 3 13:09:12 2005 @@ -177,7 +177,7 @@ from pyparser.pythonparse import parse_python_source, PYTHON_PARSER from pyparser.tuplebuilder import TupleBuilder -def pycompile(source, mode): +def _parse_source(source, mode): strings = [line+'\n' for line in source.split('\n')] builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) if mode == 'exec': @@ -202,7 +202,7 @@ space = self.space try: transformer = Transformer() - tuples = pycompile(source, mode) + tuples = _parse_source(source, mode) tree = transformer.compile_node(tuples) compiler.misc.set_filename(filename, tree) if mode == 'exec': Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Sun Jul 3 13:09:12 2005 @@ -1,9 +1,16 @@ #!/usr/bin/env python +"""This module loads the python Grammar (2.3 or 2.4) and builds +the parser for this grammar in the global PYTHON_PARSER + +helper functions are provided that use the grammar to parse +using file_input, single_input and eval_input targets +""" +from pypy.interpreter.error import OperationError, debug_print + from pythonlexer import Source -from ebnfparse import parse_grammar +import ebnfparse import sys import os -import symbol import grammar # parse the python grammar corresponding to our CPython version @@ -14,12 +21,13 @@ """returns a """ level = grammar.DEBUG grammar.DEBUG = 0 - gram = parse_grammar( file(PYTHON_GRAMMAR) ) + gram = ebnfparse.parse_grammar( file(PYTHON_GRAMMAR) ) grammar.DEBUG = level # Build first sets for each rule (including anonymous ones) grammar.build_first_sets(gram.items) return gram +debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar() Modified: pypy/dist/pypy/module/recparser/__init__.py ============================================================================== --- pypy/dist/pypy/module/recparser/__init__.py (original) +++ pypy/dist/pypy/module/recparser/__init__.py Sun Jul 3 13:09:12 2005 @@ -4,8 +4,7 @@ -import pythonparse -debug_print( "Loading grammar %s" % pythonparse.PYTHON_GRAMMAR ) +import pypy.interpreter.pyparser.pythonparse from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Sun Jul 3 13:09:12 2005 @@ -10,8 +10,11 @@ spaces = [] oldstyle = 0 uselibfile = 0 - parser = "cpython" - compiler = "cpython" + useparsermodule = "recparser" # "cpython" / "recparser" / "parser" + parser = "cpython" # "cpython" / "pyparse" + compiler = "cpython" # "cpython" + # "pyparse" pypy parser, cpython compiler + # "pycomp" pypy parser and compiler (TBD) def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server @@ -41,6 +44,9 @@ '-H', action="callback", callback=run_tb_server, help="use web browser for traceback info")) + options.append(make_option( + '--pyparse', action="store_const", dest="compiler", const="pyparse", + help="enable the internal pypy parser with CPython compiler")) return options From nik at codespeak.net Sun Jul 3 13:35:01 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Sun, 3 Jul 2005 13:35:01 +0200 (CEST) Subject: [pypy-svn] r14127 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703113501.6BECC27B46@code1.codespeak.net> Author: nik Date: Sun Jul 3 13:35:00 2005 New Revision: 14127 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_tempfile.py - copied, changed from r14118, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tempfile.py Log: Applied 2.3.4 modifications to tempfile tests. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_tempfile.py (from r14118, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tempfile.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_tempfile.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_tempfile.py Sun Jul 3 13:35:00 2005 @@ -32,6 +32,9 @@ else: TEST_FILES = 100 +# Reduced for PyPy +TEST_FILES = 10 + # This is organized as one test for each chunk of code in tempfile.py, # in order of their appearance in the file. Testing which requires # threads is not done here. @@ -504,8 +507,9 @@ self.dir = tempfile.mkdtemp() def tearDown(self): + import shutil if self.dir: - os.rmdir(self.dir) + shutil.rmtree(self.dir) self.dir = None class mktemped: From hpk at codespeak.net Sun Jul 3 13:42:41 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 13:42:41 +0200 (CEST) Subject: [pypy-svn] r14128 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703114241.1B3E527B46@code1.codespeak.net> Author: hpk Date: Sun Jul 3 13:42:40 2005 New Revision: 14128 Modified: pypy/dist/pypy/translator/llvm2/database.py Log: better docstring Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 3 13:42:40 2005 @@ -110,7 +110,7 @@ # __________________________________________________________ - # Getters + # Representing variables and constants in LLVM source code def repr_arg(self, arg): if (isinstance(arg, Constant) and From nik at codespeak.net Sun Jul 3 13:50:23 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Sun, 3 Jul 2005 13:50:23 +0200 (CEST) Subject: [pypy-svn] r14129 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703115023.90A6627B46@code1.codespeak.net> Author: nik Date: Sun Jul 3 13:50:21 2005 New Revision: 14129 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_sha.py - copied, changed from r14118, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sha.py Log: fixed too time-consuming sha test case. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_sha.py (from r14118, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sha.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_sha.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_sha.py Sun Jul 3 13:50:21 2005 @@ -22,7 +22,8 @@ self.check("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "84983e441c3bd26ebaae4aa1f95129e5e54670f1") - def test_case_3(self): + # Disabled for PyPy + def too_slow_test_case_3(self): self.check("a" * 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f") From ludal at codespeak.net Sun Jul 3 13:57:35 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 13:57:35 +0200 (CEST) Subject: [pypy-svn] r14130 - in pypy/dist/pypy: interpreter/pyparser translator/goal Message-ID: <20050703115735.14AA427B46@code1.codespeak.net> Author: ludal Date: Sun Jul 3 13:57:33 2005 New Revision: 14130 Modified: pypy/dist/pypy/interpreter/pyparser/ebnflexer.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/translator/goal/targetparser.py Log: * comments and cleanup of ebnflexer Modified: pypy/dist/pypy/interpreter/pyparser/ebnflexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnflexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnflexer.py Sun Jul 3 13:57:33 2005 @@ -6,8 +6,6 @@ import re from grammar import TokenSource, Token -DEBUG = False - ## Lexer for Python's grammar ######################################## g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:",re.M) g_symbol = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*",re.M) @@ -16,7 +14,14 @@ g_skip = re.compile(r"\s*(#.*$)?",re.M) class GrammarSource(TokenSource): - """The grammar tokenizer""" + """The grammar tokenizer + It knows only 5 types of tokens: + EOF: end of file + SYMDEF: a symbol definition e.g. "file_input:" + STRING: a simple string "'xxx'" + SYMBOL: a rule symbol usually appeary right of a SYMDEF + tokens: '[', ']', '(' ,')', '*', '+', '|' + """ def __init__(self, inpstring ): TokenSource.__init__(self) self.input = inpstring @@ -24,9 +29,13 @@ self._peeked = None def context(self): + """returns an opaque context object, used to backtrack + to a well known position in the parser""" return self.pos, self._peeked def offset(self, ctx=None): + """Returns the current parsing position from the start + of the parsed text""" if ctx is None: return self.pos else: @@ -34,9 +43,15 @@ return ctx def restore(self, ctx): + """restore the context provided by context()""" self.pos, self._peeked = ctx def next(self): + """returns the next token""" + # We only support 1-lookahead which + # means backtracking more than one token + # will re-tokenize the stream (but this is the + # grammar lexer so we don't care really!) if self._peeked is not None: peeked = self._peeked self._peeked = None @@ -71,13 +86,17 @@ tk = m.group(0) self.pos = m.end() return Token('SYMBOL',tk) - raise ValueError("Unknown token at pos=%d context='%s'" % (pos,inp[pos:pos+20]) ) + raise ValueError("Unknown token at pos=%d context='%s'" % + (pos,inp[pos:pos+20]) ) def peek(self): + """take a peek at the next token""" if self._peeked is not None: return self._peeked self._peeked = self.next() return self._peeked - def debug(self): - return self.input[self.pos:self.pos+20] + def debug(self, N=20): + """A simple helper function returning the stream at the last + parsed position""" + return self.input[self.pos:self.pos+N] Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Sun Jul 3 13:57:33 2005 @@ -42,7 +42,7 @@ builder.source_encoding = src.encoding # if not result: - raise SyntaxError("...") + #raise SyntaxError("...") return None # raise SyntaxError("at %s" % src.debug() ) return builder Modified: pypy/dist/pypy/translator/goal/targetparser.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetparser.py (original) +++ pypy/dist/pypy/translator/goal/targetparser.py Sun Jul 3 13:57:33 2005 @@ -8,7 +8,7 @@ this_dir = os.path.dirname(sys.argv[0]) -from pypy.module.recparser.pythonutil import annotateme +from pypy.interpreter.pyparser.pythonutil import annotateme # __________ Entry point __________ entry_point = annotateme From cfbolz at codespeak.net Sun Jul 3 13:59:20 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 3 Jul 2005 13:59:20 +0200 (CEST) Subject: [pypy-svn] r14132 - in pypy/dist/pypy/rpython: . test Message-ID: <20050703115920.A7BE927B46@code1.codespeak.net> Author: cfbolz Date: Sun Jul 3 13:59:20 2005 New Revision: 14132 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: (cfbolz,hpk) implement helper for getting only non-void args from a Function Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sun Jul 3 13:59:20 2005 @@ -266,6 +266,10 @@ return self.RESULT._defl() return _func(self, _callable=ex) + def _trueargs(self): + return [arg for arg in self.ARGS if arg is not Void] + + class OpaqueType(ContainerType): def __init__(self, tag): Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Sun Jul 3 13:59:20 2005 @@ -261,6 +261,10 @@ py.test.raises(TypeError, pf, 0, 0) py.test.raises(TypeError, pf, 'a') +def test_truargs(): + F = FuncType((Void, Signed, Void, Unsigned), Float) + assert Void not in F._trueargs() + def test_inconsistent_gc_containers(): A = GcArray(('y', Signed)) S = GcStruct('b', ('y', Signed)) From cfbolz at codespeak.net Sun Jul 3 14:01:01 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 3 Jul 2005 14:01:01 +0200 (CEST) Subject: [pypy-svn] r14133 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050703120101.C683127B46@code1.codespeak.net> Author: cfbolz Date: Sun Jul 3 14:01:01 2005 New Revision: 14133 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: intermediate checkin Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 14:01:01 2005 @@ -1,12 +1,12 @@ import py -from pypy.rpython import lltype +from pypy.rpython import lltype from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode -log = log.structnode +log = log.structnode class ArrayTypeNode(LLVMNode): - _issetup = False - def __init__(self, db, array): + _issetup = False + def __init__(self, db, array): self.db = db assert isinstance(array, lltype.ArrayType) self.array = array @@ -14,14 +14,14 @@ self.ref = self.ref_template + ".0" def __str__(self): - return "" % self.ref + return "" % self.ref def setup(self): self.db.prepare_repr_arg_type(self.array.OF) self._issetup = True # ______________________________________________________________________ - # entry points from genllvm + # entry points from genllvm # def writedatatypedecl(self, codewriter): codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 14:01:01 2005 @@ -8,6 +8,7 @@ from pypy.translator.llvm2.log import log log = log.funcnode + class FuncTypeNode(LLVMNode): func_type_node_counter = 0 @@ -24,11 +25,12 @@ def setup(self): self.db.prepare_repr_arg_type(self.type_.RESULT) - self.db.prepare_repr_arg_type(self.type_.ARGS) + self.db.prepare_repr_arg_type(args_without_void(self.type_.ARGS)) def writedatatypedecl(self, codewriter): returntype = self.db.repr_arg_type(self.type_.RESULT) - inputargtypes = self.db.repr_arg_type_multi(self.type_.ARGS) + inputargtypes = self.db.repr_arg_type_multi( + args_without_void(self.type_.ARGS)) decl = "%s type %s (%s)*" % (self.ref, returntype, ", ".join(inputargtypes)) codewriter.funcdef(self.ref, returntype, inputargtypes) @@ -254,16 +256,17 @@ self.codewriter.malloc(targetvar, type) def malloc_varsize(self, op): + XXXXXXXXXXXXXXXXXXXXXX targetvar = self.db.repr_arg(op.result) arg_type = op.args[0] assert (isinstance(arg_type, Constant) and - isinstance(arg_type.value, lltype.Struct)) - struct_type = self.db.obj2node[arg_type.value].ref - struct_cons = self.db.obj2node[arg_type.value].new_var_name + isinstance(arg_type.value, lltype.Array)) +## struct_type = self.db.obj2node[arg_type.value].ref +## struct_cons = self.db.obj2node[arg_type.value].new_var_name argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - self.codewriter.call(targetvar, struct_type + " *", - struct_cons, argrefs, argtypes) + self.codewriter.call("%example", "type*", "constructor", + argrefs, argtypes) def getfield(self, op): tmpvar = self.db.repr_tmpvar() Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 14:01:01 2005 @@ -218,7 +218,7 @@ f = compile_function(char_constant, []) assert f() == 7 -def Xtest_list_getitem(): +def test_list_getitem(): def list_getitem(i): l = [1,2,i] return l[i] From hpk at codespeak.net Sun Jul 3 14:10:51 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 14:10:51 +0200 (CEST) Subject: [pypy-svn] r14134 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703121051.ED3B227B46@code1.codespeak.net> Author: hpk Date: Sun Jul 3 14:10:51 2005 New Revision: 14134 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py Log: (cfbolz,hpk) use new trueargs helper Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 14:10:51 2005 @@ -25,12 +25,11 @@ def setup(self): self.db.prepare_repr_arg_type(self.type_.RESULT) - self.db.prepare_repr_arg_type(args_without_void(self.type_.ARGS)) + self.db.prepare_repr_arg_type_multi(self.type_._trueargs()) def writedatatypedecl(self, codewriter): returntype = self.db.repr_arg_type(self.type_.RESULT) - inputargtypes = self.db.repr_arg_type_multi( - args_without_void(self.type_.ARGS)) + inputargtypes = self.db.repr_arg_type_multi(self.type_._trueargs()) decl = "%s type %s (%s)*" % (self.ref, returntype, ", ".join(inputargtypes)) codewriter.funcdef(self.ref, returntype, inputargtypes) From ac at codespeak.net Sun Jul 3 14:37:03 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 3 Jul 2005 14:37:03 +0200 (CEST) Subject: [pypy-svn] r14135 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703123703.123A327B46@code1.codespeak.net> Author: ac Date: Sun Jul 3 14:37:02 2005 New Revision: 14135 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_module.py - copied, changed from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_module.py Log: An uninitialized modules __dict__ can be an empty dict in PyPy. Change the test acordingly. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_module.py (from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_module.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_module.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_module.py Sun Jul 3 14:37:02 2005 @@ -7,7 +7,7 @@ # An uninitialized module has no __dict__ or __name__, and __doc__ is None foo = module.__new__(module) -verify(foo.__dict__ is None) +verify(not foo.__dict__) try: s = foo.__name__ except AttributeError: From nik at codespeak.net Sun Jul 3 14:40:15 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Sun, 3 Jul 2005 14:40:15 +0200 (CEST) Subject: [pypy-svn] r14136 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703124015.CB8B227B46@code1.codespeak.net> Author: nik Date: Sun Jul 3 14:40:15 2005 New Revision: 14136 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_operations.py - copied unchanged from r14118, pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/test/test_operations.py Log: Modifictations from 2.3.4 applied to 2.4.1 tests. From adim at codespeak.net Sun Jul 3 14:50:00 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 14:50:00 +0200 (CEST) Subject: [pypy-svn] r14137 - in pypy/dist/pypy/interpreter: . pyparser pyparser/test Message-ID: <20050703125000.153EE27B46@code1.codespeak.net> Author: adim Date: Sun Jul 3 14:49:56 2005 New Revision: 14137 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: - various tidy machinery - added some small tests for 'eval' and 'exec' modes - removed pycompile() function from pycompiler.py since this functionnality is now provided by pyparser.pythonutil module Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Sun Jul 3 14:49:56 2005 @@ -169,30 +169,13 @@ ######## -import symbol -from compiler.transformer import Transformer +# from compiler.transformer import Transformer from compiler.pycodegen import ModuleCodeGenerator from compiler.pycodegen import InteractiveCodeGenerator from compiler.pycodegen import ExpressionCodeGenerator from pyparser.pythonparse import parse_python_source, PYTHON_PARSER from pyparser.tuplebuilder import TupleBuilder - -def _parse_source(source, mode): - strings = [line+'\n' for line in source.split('\n')] - builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - if mode == 'exec': - target = 'file_input' - elif mode == 'single': - target = 'single_input' - else: # target == 'eval': - target = 'eval_input' - parse_python_source(strings, PYTHON_PARSER, target, builder) - # Note: The annotator can't follow the as_tuple() method call - nested_tuples = builder.stack[-1].as_tuple() - if builder.source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, builder.source_encoding) - else: - return nested_tuples +from pyparser.pythonutil import ast_from_input class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler""" @@ -201,9 +184,7 @@ flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: - transformer = Transformer() - tuples = _parse_source(source, mode) - tree = transformer.compile_node(tuples) + ast = ast_from_input(source, mode) compiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Sun Jul 3 14:49:56 2005 @@ -42,9 +42,10 @@ builder.source_encoding = src.encoding # if not result: - #raise SyntaxError("...") + # raising a SyntaxError here is not annotable, and it can + # probably be handled in an other way + # raise SyntaxError("at %s" % src.debug() ) return None - # raise SyntaxError("at %s" % src.debug() ) return builder def parse_file_input(pyf, gram, builder=None): Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Sun Jul 3 14:49:56 2005 @@ -1,22 +1,41 @@ __all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", "ast_eval_input" ] -import pythonparse from compiler.transformer import Transformer +import parser +import symbol + +import pythonparse from tuplebuilder import TupleBuilder PYTHON_PARSER = pythonparse.PYTHON_PARSER +TARGET_DICT = { + 'exec' : "file_input", + 'eval' : "eval_input", + 'single' : "single_input", + } -def python_parse(filename): +## convenience functions around CPython's parser functions +def python_parsefile(filename): """parse using CPython's parser module and return nested tuples """ pyf = file(filename) - import parser - tp2 = parser.suite(pyf.read()) - return tp2.totuple() + source = pyf.read() + pyf.close() + return python_parse(source) -import symbol -def pypy_parse(filename): +def python_parse(source, mode='exec'): + """parse python source using CPython's parser module and return + nested tuples + """ + if mode == 'exec': + tp = parser.suite(source) + else: + tp = parser.expr(source) + return tp.totuple() + +## convenience functions around recparser functions +def pypy_parsefile(filename): """parse using PyPy's parser module and return a tuple of three elements : - The encoding declaration symbol or None if there were no encoding @@ -28,20 +47,63 @@ nested tuples """ pyf = file(filename) - text = pyf.read() + source = pyf.read() pyf.close() + return pypy_parse(source) + +def pypy_parse(source, mode='exec'): + """parse using PyPy's parser module and return + a tuple of three elements : + - The encoding declaration symbol or None if there were no encoding + statement + - The TupleBuilder's stack top element (instance of + tuplebuilder.StackElement which is a wrapper of some nested tuples + like those returned by the CPython's parser) + - The encoding string or None if there were no encoding statement + nested tuples + """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - # make the annotator life easier - strings = [line + '\n' for line in text.split('\n')] + # make the annotator life easier (don't use str.splitlines()) + strings = [line + '\n' for line in source.split('\n')] + # finalize the last line + if not source.endswith('\n'): + last_line = strings[-1] + strings[-1] = last_line[:-1] + else: + strings.pop() + target_rule = TARGET_DICT[mode] pythonparse.parse_python_source(strings, PYTHON_PARSER, - 'file_input', builder) - nested_tuples = builder.stack[-1] + target_rule, builder) + # stack_element is a tuplerbuilder.StackElement's instance + stack_element = builder.stack[-1] + # convert the stack element into nested tuples + # XXX : the annotator can't follow this call + nested_tuples = stack_element.as_tuple() if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) else: - return (None, nested_tuples, None) + return nested_tuples +## convenience functions for computing AST objects based on recparser +def ast_from_input(input, mode): + tuples = pypy_parse(input, mode) + transformer = Transformer() + ast = transformer.transform(tuples) + return ast + +## TARGET FOR ANNOTATORS ############################################# def annotateme(strings): + """This function has no other role than testing the parser's annotation + + annotateme() is basically the same code that pypy_parse(), but with the + following differences : + - directly take a list of strings rather than a filename in input + in order to avoid using file() (which is faked for now) + + - returns a tuplebuilder.StackElement instead of the *real* nested + tuples (StackElement is only a wrapper class around these tuples) + + """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) nested_tuples = builder.stack[-1] @@ -50,37 +112,6 @@ else: return (None, nested_tuples, None) -def ast_single_input( text ): - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( text, PYTHON_PARSER, "single_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - -def ast_file_input( filename ): - pyf = file(filename,"r") - text = pyf.read() - return ast_srcfile_input( text, filename ) - -def ast_srcfile_input( srctext, filename ): - # TODO do something with the filename - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( srctext, PYTHON_PARSER, "file_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - -def ast_eval_input( textsrc ): - builder = TupleBuilder( PYTHON_PARSER.rules ) - pythonparse.parse_python_source( textsrc, PYTHON_PARSER, "eval_input", builder ) - tree = builder.stack[-1] - trans = Transformer() - ast = trans.transform( tree ) - return ast - - if __name__ == "__main__": import sys @@ -94,5 +125,5 @@ test_file = sys.argv[1] print "-"*20 print - print "pyparse \n", pypy_parse(test_file) - print "parser \n", python_parse(test_file) + print "pyparse \n", pypy_parsefile(test_file) + print "parser \n", python_parsefile(test_file) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Sun Jul 3 14:49:56 2005 @@ -1,7 +1,7 @@ """test module for CPython / PyPy nested tuples comparison""" import os, os.path as osp -from pypy.interpreter.pyparser.pythonutil import python_parse, pypy_parse -# from pypy.module.recparser.pythonparse import pypy_parse +from pypy.interpreter.pyparser.pythonutil import python_parsefile, \ + pypy_parsefile, python_parse, pypy_parse from pprint import pprint from pypy.interpreter.pyparser import grammar grammar.DEBUG = False @@ -54,27 +54,46 @@ continue abspath = osp.join(samples_dir, fname) yield check_parse, abspath - -def check_parse(filepath): - # pypy_tuples = pypy_parse(filepath) - encoding_decl, stack_element, encoding = pypy_parse(filepath) - nested_tuples = stack_element.as_tuple() - if encoding is None: - pypy_tuples = nested_tuples - else: - pypy_tuples = (encoding_decl, nested_tuples, encoding) - python_tuples = python_parse(filepath) + +def _check_tuples_equality(pypy_tuples, python_tuples, testname): + """XXX FIXME: refactor with assert_tuples_equal()""" try: assert_tuples_equal(pypy_tuples, python_tuples) except AssertionError, e: error_path = e.args[-1] print "ERROR PATH =", error_path - print "="*80 - print file(filepath).read() - print "="*80 print "-"*10, "PyPy parse results", "-"*10 print ''.join(print_sym_tuple(pypy_tuples, names=True, trace=error_path)) print "-"*10, "CPython parse results", "-"*10 print ''.join(print_sym_tuple(python_tuples, names=True, trace=error_path)) - assert False, filepath - + assert False, testname + +def check_parse(filepath): + pypy_tuples = pypy_parsefile(filepath) + python_tuples = python_parsefile(filepath) + _check_tuples_equality(pypy_tuples, python_tuples, filepath) + + +def check_parse_input(snippet, mode): + pypy_tuples = pypy_parse(snippet, mode) + python_tuples = python_parse(snippet, mode) + _check_tuples_equality(pypy_tuples, python_tuples, snippet) + +def test_eval_inputs(): + snippets = [ + '6*7', + 'a+b*c/d', + 'True and False', + ] + for snippet in snippets: + yield check_parse_input, snippet, 'eval' + +def test_exec_inputs(): + snippets = [ + # '\t # hello\n ', + 'print 6*7', 'if 1:\n x\n', + # 'if 1:\n x', 'x = (', 'x = (\n', # 'x = (\n\n', + ] + for snippet in snippets: + print "snippet =", repr(snippet) + yield check_parse_input, snippet, 'exec' From quest at codespeak.net Sun Jul 3 15:06:29 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Sun, 3 Jul 2005 15:06:29 +0200 (CEST) Subject: [pypy-svn] r14138 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703130629.01D0F27B46@code1.codespeak.net> Author: quest Date: Sun Jul 3 15:06:29 2005 New Revision: 14138 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_file.py - copied, changed from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_file.py Log: Modified test for files. Removed weakref tests and tests using UserList, which crashes interpreter when used with writelines Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_file.py (from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_file.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_file.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_file.py Sun Jul 3 15:06:29 2005 @@ -1,24 +1,24 @@ import sys import os from array import array -from weakref import proxy +#from weakref import proxy from test.test_support import verify, TESTFN, TestFailed from UserList import UserList -# verify weak references -f = file(TESTFN, 'w') -p = proxy(f) -p.write('teststring') -verify(f.tell(), p.tell()) -f.close() -f = None -try: - p.tell() -except ReferenceError: - pass -else: - raise TestFailed('file proxy still exists when the file is gone') +# # verify weak references +# f = file(TESTFN, 'w') +# p = proxy(f) +# p.write('teststring') +# verify(f.tell(), p.tell()) +# f.close() +# f = None +# try: +# p.tell() +# except ReferenceError: +# pass +# else: +# raise TestFailed('file proxy still exists when the file is gone') # verify expected attributes exist f = file(TESTFN, 'w') @@ -34,14 +34,17 @@ for attr in 'name', 'mode', 'closed': try: setattr(f, attr, 'oops') - except TypeError: + except (AttributeError, TypeError), x: + print x pass else: raise TestFailed('expected TypeError setting file attr %r' % attr) f.close() # verify writelines with instance sequence -l = UserList(['1', '2']) +# XXX writeslines on UserList crashes interpreter +#l = UserList(['1', '2']) +l = ['1', '2'] f = open(TESTFN, 'wb') f.writelines(l) f.close() @@ -69,7 +72,9 @@ # verify writelines with integers in UserList f = open(TESTFN, 'wb') -l = UserList([1,2,3]) +# XXX writeslines on UserList crashes interpreter +#l = UserList([1,2,3]) +l = [1,2,3] try: f.writelines(l) except TypeError: @@ -81,14 +86,14 @@ # verify writelines with non-string object class NonString: pass -f = open(TESTFN, 'wb') -try: - f.writelines([NonString(), NonString()]) -except TypeError: - pass -else: - print "writelines accepted sequence of non-string objects" -f.close() +# f = open(TESTFN, 'wb') +# try: +# f.writelines([NonString(), NonString()]) +# except TypeError: +# pass +# else: +# print "writelines accepted sequence of non-string objects" +# f.close() # verify that we get a sensible error message for bad mode argument bad_mode = "qwerty" @@ -141,28 +146,23 @@ if d != s: raise TestFailed, 'readback failure using buffer size %d' -methods = ['fileno', 'flush', 'isatty', 'next', 'read', 'readinto', - 'readline', 'readlines', 'seek', 'tell', 'truncate', 'write', - 'xreadlines', '__iter__'] +a = array('c', 'x'*10) +methods = {'fileno': (), 'flush': (), 'isatty': (), 'next': (), + 'read': (), 'readinto': (a,), 'readline': (), 'readlines': (), + 'seek': (0,), 'tell': (), 'truncate': (), 'write': ('',), + 'writelines': ([],), 'xreadlines': (), '__iter__': () } if sys.platform.startswith('atheos'): - methods.remove('truncate') + del methods['truncate'] -for methodname in methods: +for methodname, args in methods.items(): method = getattr(f, methodname) try: - method() + method(*args) except ValueError: pass else: raise TestFailed, 'file.%s() on a closed file should raise a ValueError' % methodname -try: - f.writelines([]) -except ValueError: - pass -else: - raise TestFailed, 'file.writelines([]) on a closed file should raise a ValueError' - os.unlink(TESTFN) def bug801631(): From ericvrp at codespeak.net Sun Jul 3 15:27:54 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 3 Jul 2005 15:27:54 +0200 (CEST) Subject: [pypy-svn] r14139 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703132754.EB28327B46@code1.codespeak.net> Author: ericvrp Date: Sun Jul 3 15:27:54 2005 New Revision: 14139 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py Log: rewrote llvm malloc code-generation to be able to plug in the Boehm collected quietly Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 3 15:27:54 2005 @@ -1,8 +1,15 @@ import py +from itertools import count from pypy.translator.llvm2.log import log log = log.codewriter show_line_numbers = True +count = count().next + +#hack +from os import getenv +use_boehm_gc = getenv('USER','') in ('eric',) +#/hack class CodeWriter(object): def __init__(self): @@ -90,12 +97,15 @@ self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) - def malloc(self, targetvar, type, sizetype=None, size=None): - if size is None: - assert sizetype is None - self.indent("%(targetvar)s = malloc %(type)s" % locals()) + def malloc(self, targetvar, type_, size=1): + if use_boehm_gc: + cnt = count() + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)d" % locals()) + self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = malloc sbyte, uint %%malloc.SizeU.%(cnt)d" % locals()) + self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) else: - self.indent("%(targetvar)s = malloc %(type)s, %(sizetype)s %(size)s" % locals()) + self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)d" % locals()) def getelementptr(self, targetvar, type, typevar, *indices): res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals() From jacob at codespeak.net Sun Jul 3 15:35:18 2005 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sun, 3 Jul 2005 15:35:18 +0200 (CEST) Subject: [pypy-svn] r14140 - pypy/dist/pypy/lib Message-ID: <20050703133518.7272E27B46@code1.codespeak.net> Author: jacob Date: Sun Jul 3 15:35:17 2005 New Revision: 14140 Modified: pypy/dist/pypy/lib/inprogress_binascii.py Log: Complete implementation of binascii, which passes the CPython tests. Modified: pypy/dist/pypy/lib/inprogress_binascii.py ============================================================================== --- pypy/dist/pypy/lib/inprogress_binascii.py (original) +++ pypy/dist/pypy/lib/inprogress_binascii.py Sun Jul 3 15:35:17 2005 @@ -297,3 +297,281 @@ for c in s: i = i * 0x10 + hex_numbers.index(c) return i + +hqx_encoding = '!"#$%&\'()*+,-012345689 at ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr' +# Make a fast lookup dictionary for decoding hqx +hqx_decoding = {} +for i, c in enumerate(hqx_encoding): + hqx_decoding[c] = i + +def unpadded_quadruples(s): + while s: + yield s[:4] + s = s[4:] + +def a2b_hqx(s): + decoded = [] + for c in s: + decoded.append(hqx_decoding[c]) + gen = unpadded_quadruples(decoded) + result = [] + for snippet in gen: + length = len(snippet) + if length == 4: + result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) + result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) + result.append(chr((snippet[2] << 6) | (snippet[3]))) + elif length == 3: + result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) + result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) + elif length == 2: + result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) + else: + raise TypeError('Wrong number of characters.') + return ''.join(result) + +def unpadded_triples(s): + while s: + yield [ord(c) for c in s[:3]] + s = s[3:] + +def b2a_hqx(s): + result =[] + gen = unpadded_triples(s) + for snippet in gen: + length = len(snippet) + if length == 3: + result.append( + hqx_encoding[(snippet[0] & 0xfc) >> 2]) + result.append(hqx_encoding[ + ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)]) + result.append(hqx_encoding[ + (snippet[1] & 0x0f) << 2 | ((snippet[2] & 0xc0) >> 6)]) + result.append(hqx_encoding[snippet[2] & 0x3f]) + elif length == 2: + result.append( + hqx_encoding[(snippet[0] & 0xfc) >> 2]) + result.append(hqx_encoding[ + ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)]) + result.append(hqx_encoding[ + (snippet[1] & 0x0f) << 2]) + elif length == 1: + result.append( + hqx_encoding[(snippet[0] & 0xfc) >> 2]) + result.append(hqx_encoding[ + ((snippet[0] & 0x03) << 4)]) + return ''.join(result) + +crctab_hqx = [ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +] + +def crc_hqx(s, crc): + for c in s: + crc=((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ c] + + return crc + +def rlecode_hqx(s): + result = [] + prev = s[0] + count = 1 + # Add a dummy character to get the loop to go one extra round. + # The dummy must be different from the last character of s. + # In the same step we remove the first character, which has + # already been stored in prev. + if s[-1] == '!': + s = s[1:] + '?' + else: + s = s[1:] + '!' + + for c in s: + if c == prev and count < 255: + count += 1 + else: + if count == 1: + if prev != '\x90': + result.append(prev) + else: + result.extend(['\x90', '\x00']) + elif count < 4: + if prev != '\x90': + result.extend([prev] * count) + else: + result.extend(['\x90', '\x00'] * count) + else: + if prev != '\x90': + result.extend([prev, '\x90', chr(count)]) + else: + result.extend(['\x90', '\x00', '\x90', chr(count)]) + count = 1 + prev = c + + return ''.join(result) + +def rledecode_hqx(s): + s = s.split('\x90') + result = [s[0]] + prev = s[0] + for snippet in s[1:]: + count = ord(snippet[0]) + if count > 0: + result.append(prev[-1] * (count-1)) + prev = snippet + else: + result. append('\x90') + prev = '\x90' + result.append(snippet[1:]) + + return ''.join(result) + +crc_32_tab = [ + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +] + +def crc32(s, crc=0): + crc = ~long(crc) & 0xffffffffL + for c in s: + crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8) + #/* Note: (crc >> 8) MUST zero fill on left + + result = crc ^ 0xffffffffL + + return result + +def b2a_hex(s): + result = [] + for char in s: + c = (ord(char) >> 4) & 0xf + if c > 9: + c = c + ord('a') - 10 + else: + c = c + ord('0') + result.append(chr(c)) + c = ord(char) & 0xf + if c > 9: + c = c + ord('a') - 10 + else: + c = c + ord('0') + result.append(chr(c)) + return ''.join(result) + +hexlify = b2a_hex + +table_hex = [ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +] + + +def a2b_hex(t): + result = [] + + def pairs_gen(s): + while s: + try: + a, b = s[0], s[1] + except IndexError: + if len(s): + raise TypeError('Odd-length string') + return + s = s[2:] + yield table_hex[ord(a)], table_hex[ord(b)] + + pairs = pairs_gen(t) + for a, b in pairs: + if a < 0 or b < 0: + raise TypeError('Non-hexadecimal digit found') + result.append(chr((a << 4) + b)) + return ''.join(result) + + +unhexlify = a2b_hex From jacob at codespeak.net Sun Jul 3 15:36:20 2005 From: jacob at codespeak.net (jacob at codespeak.net) Date: Sun, 3 Jul 2005 15:36:20 +0200 (CEST) Subject: [pypy-svn] r14141 - pypy/dist/pypy/lib Message-ID: <20050703133620.D139427B46@code1.codespeak.net> Author: jacob Date: Sun Jul 3 15:36:19 2005 New Revision: 14141 Added: pypy/dist/pypy/lib/binascii.py - copied unchanged from r14140, pypy/dist/pypy/lib/inprogress_binascii.py Removed: pypy/dist/pypy/lib/inprogress_binascii.py Log: Renamed. Deleted: /pypy/dist/pypy/lib/inprogress_binascii.py ============================================================================== --- /pypy/dist/pypy/lib/inprogress_binascii.py Sun Jul 3 15:36:19 2005 +++ (empty file) @@ -1,577 +0,0 @@ -class Error(Exception): - pass - -class Incomplete(Exception): - pass - -def a2b_uu(s): - length = (ord(s[0]) - 0x20) % 64 - a = quadruplets(s[1:].rstrip()) - try: - result = [''.join( - [chr((A - 0x20) << 2 | (((B - 0x20) >> 4) & 0x3)), - chr(((B - 0x20) & 0xF) << 4 | (((C - 0x20) >> 2) & 0xF)), - chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3F)) - ]) for A, B, C, D in a] - except ValueError: - raise Error, 'Illegal char' - result = ''.join(result) - trailingdata = result[length:] - if trailingdata.strip('\x00'): - raise Error, 'Trailing garbage' - result = result[:length] - if len(result) < length: - result += ((length - len(result)) * '\x00') - return result - -def quadruplets(s): - while s: - try: - a, b, c, d = s[0], s[1], s[2], s[3] - except IndexError: - s += ' ' - yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) - return - s = s[4:] - yield ord(a), ord(b), ord(c), ord(d) - -def b2a_uu(s): - length = len(s) - if length > 45: - raise Error, 'At most 45 bytes at once' - - a = triples(s) - result = [''.join( - [chr(0x20 + (( A >> 2 ) & 0x3F)), - chr(0x20 + (((A << 4) | ((B >> 4) & 0xF)) & 0x3F)), - chr(0x20 + (((B << 2) | ((C >> 6) & 0x3)) & 0x3F)), - chr(0x20 + (( C ) & 0x3F))]) for A, B, C in a] - return chr(ord(' ') + (length & 077)) + ''.join(result) + '\n' - -def triples(s): - while s: - try: - a, b, c = s[0], s[1], s[2] - except IndexError: - s += '\0\0' - yield ord(s[0]), ord(s[1]), ord(s[2]) - return - s = s[3:] - yield ord(a), ord(b), ord(c) - - -table_a2b_base64 = { - 'A': 0, - 'B': 1, - 'C': 2, - 'D': 3, - 'E': 4, - 'F': 5, - 'G': 6, - 'H': 7, - 'I': 8, - 'J': 9, - 'K': 10, - 'L': 11, - 'M': 12, - 'N': 13, - 'O': 14, - 'P': 15, - 'Q': 16, - 'R': 17, - 'S': 18, - 'T': 19, - 'U': 20, - 'V': 21, - 'W': 22, - 'X': 23, - 'Y': 24, - 'Z': 25, - 'a': 26, - 'b': 27, - 'c': 28, - 'd': 29, - 'e': 30, - 'f': 31, - 'g': 32, - 'h': 33, - 'i': 34, - 'j': 35, - 'k': 36, - 'l': 37, - 'm': 38, - 'n': 39, - 'o': 40, - 'p': 41, - 'q': 42, - 'r': 43, - 's': 44, - 't': 45, - 'u': 46, - 'v': 47, - 'w': 48, - 'x': 49, - 'y': 50, - 'z': 51, - '0': 52, - '1': 53, - '2': 54, - '3': 55, - '4': 56, - '5': 57, - '6': 58, - '7': 59, - '8': 60, - '9': 61, - '+': 62, - '/': 63, -} - -def quadruplets_base64(s): - while s: - a, b, c, d = table_a2b_base64[s[0]], table_a2b_base64[s[1]], table_a2b_base64[s[2]], table_a2b_base64[s[3]] - s = s[4:] - yield a, b, c, d - -def a2b_base64(s): - s = s.rstrip() - # clean out all invalid characters, this also strips the final '=' padding - clean_s = [] - for item in s: - if item in table_a2b_base64: - clean_s.append(item) - s = ''.join(clean_s) - # Add '=' padding back into the string - if len(s) % 4: - s = s + ('=' * (4 - len(s) % 4)) - - a = quadruplets_base64(s[:-4]) - result = [ - chr(A << 2 | ((B >> 4) & 0x3)) + - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + - chr((C & 0x3) << 6 | D ) - for A, B, C, D in a] - - if s: - final = s[-4:] - if final[2] == '=': - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) - elif final[3] == '=': - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - C = table_a2b_base64[final[2]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) - else: - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - C = table_a2b_base64[final[2]] - D = table_a2b_base64[final[3]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + \ - chr((C & 0x3) << 6 | D ) - result.append(snippet) - - return ''.join(result) - -table_b2a_base64 = \ -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - -def b2a_base64(s): - length = len(s) - final_length = length % 3 - - a = triples(s[ :length - final_length]) - - result = [''.join( - [table_b2a_base64[( A >> 2 ) & 0x3F], - table_b2a_base64[((A << 4) | ((B >> 4) & 0xF)) & 0x3F], - table_b2a_base64[((B << 2) | ((C >> 6) & 0x3)) & 0x3F], - table_b2a_base64[( C ) & 0x3F]]) - for A, B, C in a] - - final = s[length - final_length:] - if final_length == 0: - snippet = '' - elif final_length == 1: - a = ord(final[0]) - snippet = table_b2a_base64[(a >> 2 ) & 0x3F] + \ - table_b2a_base64[(a << 4 ) & 0x3F] + '==' - else: - a = ord(final[0]) - b = ord(final[1]) - snippet = table_b2a_base64[(a >> 2) & 0x3F] + \ - table_b2a_base64[((a << 4) | (b >> 4) & 0xF) & 0x3F] + \ - table_b2a_base64[(b << 2) & 0x3F] + '=' - return ''.join(result) + snippet + '\n' - -def a2b_qp(s): - parts = s.rstrip().split('=') - - # Change the parts in-place - for index, part in enumerate(parts[1:]): - if len(part) > 1 and part[0] in hex_numbers and part[1] in hex_numbers: - parts[index + 1] = chr(strhex_to_int(part[0:2])) + part[2:] - elif index == len(parts) - 2 and len(part) < 2: - parts[index + 1] = '' - else: - parts[index + 1] = '=' + parts[index + 1] - - return ''.join(parts) - -def b2a_qp(s): - """ In this implementation, we are quoting all spaces and tab character. - This is ok by the standard, though it slightly reduces the - readability of the quoted string. The CPython implementation - preserves internal whitespace, which is a different way of - implementing the standard. The reason we are doing things differently - is that it greatly simplifies the code. - - The CPython implementation does not escape CR and LF characters - and does not encode newlines as CRLF sequences. This seems to be - non-standard, and we copy this behaviour. - """ - crlf = s.find('\r\n') - lf = s.find('\n') - linebreak = None - if crlf >= 0 and crlf <= lf: - linebreak = '\r\n' - elif lf > 0: - linebreak = '\n' - - if linebreak: - s = s.replace('\r\n', '\n') - - lines = s.split('\n') - - result = [] - for line in lines: - charlist = [] - count = 0 - for c in line: - if '!' <= c <= '<' or '>' <= c <= '~' or c in '\n\r': - if count >= 75: - charlist.append('=\r\n') - count = 0 - charlist.append(c) - count += 1 - else: - if count >= 72: - charlist.append('=\r\n') - count = 0 - snippet = '=' + two_hex_digits(ord(c)) - count += len(snippet) - charlist.append(snippet) - result.append(''.join(charlist)) - return linebreak.join(result) - -hex_numbers = '0123456789ABCDEF' -def hex(n): - if n == 0: - return '0' - - if n < 0: - n = -n - sign = '-' - else: - sign = '' - arr = [] - for nibble in hexgen(n): - arr = [hex_numbers[nibble]] + arr - return sign + ''.join(arr) - -def two_hex_digits(n): - return hex_numbers[n / 0x10] + hex_numbers[n % 0x10] - -def hexgen(n): - """ Yield a nibble at a time. """ - while n: - remainder = n % 0x10 - n = n / 0x10 - yield remainder - -def strhex_to_int(s): - i = 0 - for c in s: - i = i * 0x10 + hex_numbers.index(c) - return i - -hqx_encoding = '!"#$%&\'()*+,-012345689 at ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr' -# Make a fast lookup dictionary for decoding hqx -hqx_decoding = {} -for i, c in enumerate(hqx_encoding): - hqx_decoding[c] = i - -def unpadded_quadruples(s): - while s: - yield s[:4] - s = s[4:] - -def a2b_hqx(s): - decoded = [] - for c in s: - decoded.append(hqx_decoding[c]) - gen = unpadded_quadruples(decoded) - result = [] - for snippet in gen: - length = len(snippet) - if length == 4: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - result.append(chr((snippet[2] << 6) | (snippet[3]))) - elif length == 3: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - elif length == 2: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - else: - raise TypeError('Wrong number of characters.') - return ''.join(result) - -def unpadded_triples(s): - while s: - yield [ord(c) for c in s[:3]] - s = s[3:] - -def b2a_hqx(s): - result =[] - gen = unpadded_triples(s) - for snippet in gen: - length = len(snippet) - if length == 3: - result.append( - hqx_encoding[(snippet[0] & 0xfc) >> 2]) - result.append(hqx_encoding[ - ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)]) - result.append(hqx_encoding[ - (snippet[1] & 0x0f) << 2 | ((snippet[2] & 0xc0) >> 6)]) - result.append(hqx_encoding[snippet[2] & 0x3f]) - elif length == 2: - result.append( - hqx_encoding[(snippet[0] & 0xfc) >> 2]) - result.append(hqx_encoding[ - ((snippet[0] & 0x03) << 4) | ((snippet[1] & 0xf0) >> 4)]) - result.append(hqx_encoding[ - (snippet[1] & 0x0f) << 2]) - elif length == 1: - result.append( - hqx_encoding[(snippet[0] & 0xfc) >> 2]) - result.append(hqx_encoding[ - ((snippet[0] & 0x03) << 4)]) - return ''.join(result) - -crctab_hqx = [ - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, -] - -def crc_hqx(s, crc): - for c in s: - crc=((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ c] - - return crc - -def rlecode_hqx(s): - result = [] - prev = s[0] - count = 1 - # Add a dummy character to get the loop to go one extra round. - # The dummy must be different from the last character of s. - # In the same step we remove the first character, which has - # already been stored in prev. - if s[-1] == '!': - s = s[1:] + '?' - else: - s = s[1:] + '!' - - for c in s: - if c == prev and count < 255: - count += 1 - else: - if count == 1: - if prev != '\x90': - result.append(prev) - else: - result.extend(['\x90', '\x00']) - elif count < 4: - if prev != '\x90': - result.extend([prev] * count) - else: - result.extend(['\x90', '\x00'] * count) - else: - if prev != '\x90': - result.extend([prev, '\x90', chr(count)]) - else: - result.extend(['\x90', '\x00', '\x90', chr(count)]) - count = 1 - prev = c - - return ''.join(result) - -def rledecode_hqx(s): - s = s.split('\x90') - result = [s[0]] - prev = s[0] - for snippet in s[1:]: - count = ord(snippet[0]) - if count > 0: - result.append(prev[-1] * (count-1)) - prev = snippet - else: - result. append('\x90') - prev = '\x90' - result.append(snippet[1:]) - - return ''.join(result) - -crc_32_tab = [ - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL -] - -def crc32(s, crc=0): - crc = ~long(crc) & 0xffffffffL - for c in s: - crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8) - #/* Note: (crc >> 8) MUST zero fill on left - - result = crc ^ 0xffffffffL - - return result - -def b2a_hex(s): - result = [] - for char in s: - c = (ord(char) >> 4) & 0xf - if c > 9: - c = c + ord('a') - 10 - else: - c = c + ord('0') - result.append(chr(c)) - c = ord(char) & 0xf - if c > 9: - c = c + ord('a') - 10 - else: - c = c + ord('0') - result.append(chr(c)) - return ''.join(result) - -hexlify = b2a_hex - -table_hex = [ - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 -] - - -def a2b_hex(t): - result = [] - - def pairs_gen(s): - while s: - try: - a, b = s[0], s[1] - except IndexError: - if len(s): - raise TypeError('Odd-length string') - return - s = s[2:] - yield table_hex[ord(a)], table_hex[ord(b)] - - pairs = pairs_gen(t) - for a, b in pairs: - if a < 0 or b < 0: - raise TypeError('Non-hexadecimal digit found') - result.append(chr((a << 4) + b)) - return ''.join(result) - - -unhexlify = a2b_hex From ludal at codespeak.net Sun Jul 3 15:36:29 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 15:36:29 +0200 (CEST) Subject: [pypy-svn] r14142 - in pypy/dist/pypy: interpreter module/recparser tool Message-ID: <20050703133629.19CCA27B4A@code1.codespeak.net> Author: ludal Date: Sun Jul 3 15:36:27 2005 New Revision: 14142 Added: pypy/dist/pypy/module/recparser/app_class.py Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/recparser/__init__.py pypy/dist/pypy/module/recparser/pyparser.py pypy/dist/pypy/tool/option.py Log: revived parser module (a bit), add option to select it Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Jul 3 15:36:27 2005 @@ -145,7 +145,7 @@ #self.setbuiltinmodule("_sre", "_sre_pypy") if self.options.useparsermodule == "recparser": self.setbuiltinmodule('parser', 'recparser') - elif self.options.parsermodule == "parser": + elif self.options.useparsermodule == "parser": self.setbuiltinmodule('parser') # initialize with "bootstrap types" from objspace (e.g. w_None) Modified: pypy/dist/pypy/module/recparser/__init__.py ============================================================================== --- pypy/dist/pypy/module/recparser/__init__.py (original) +++ pypy/dist/pypy/module/recparser/__init__.py Sun Jul 3 15:36:27 2005 @@ -1,33 +1,29 @@ from pypy.interpreter.error import OperationError, debug_print -from pypy.interpreter import module - - +import pypy.interpreter.pyparser.pythonparse +from pypy.interpreter.mixedmodule import MixedModule +# Forward imports so they run at startup time +import pyparser +import pypy.interpreter.pyparser.pythonlexer import pypy.interpreter.pyparser.pythonparse -from pypy.interpreter.mixedmodule import MixedModule class Module(MixedModule): - interpleveldefs = {} - appleveldefs = {} + """The builtin parser module. + """ + -## from pypy.interpreter.mixedmodule import MixedModule -## class Module(MixedModule): -## """The builtin parser module. -## """ - - -## appleveldefs = { -## # 'ParserError' : 'app_class.ParserError', -## } -## interpleveldefs = { -## '__name__' : '(space.wrap("parser"))', -## '__doc__' : '(space.wrap("parser (recparser version) module"))', - -## 'suite' : 'pyparser.suite', -## 'expr' : 'pyparser.expr', -## 'STType' : 'pyparser.STType', -## 'ast2tuple' : 'pyparser.ast2tuple', + appleveldefs = { + 'ParserError' : 'app_class.ParserError', + } + interpleveldefs = { + '__name__' : '(space.wrap("parser"))', + '__doc__' : '(space.wrap("parser (recparser version) module"))', + + 'suite' : 'pyparser.suite', + 'expr' : 'pyparser.expr', + 'STType' : 'pyparser.STType', + 'ast2tuple' : 'pyparser.ast2tuple', ## # 'ASTType' : 'pyparser.STType', ## # 'sequence2st' : 'pyparser.sequence2st', ## #'eval_input' : 'pyparser.eval_input', @@ -44,5 +40,5 @@ ## #'tuple2ast' : 'pyparser.tuple2ast', ## #'_pickler' : 'pyparser._pickler', ## #'compilest' : 'pyparser.compilest', -## } + } Added: pypy/dist/pypy/module/recparser/app_class.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/recparser/app_class.py Sun Jul 3 15:36:27 2005 @@ -0,0 +1,8 @@ + +# ______________________________________________________________________ +# ParserError exception + +class ParserError (Exception): + """Class ParserError + Exception class for parser errors (I assume). + """ Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Sun Jul 3 15:36:27 2005 @@ -7,9 +7,9 @@ from pypy.interpreter.typedef import TypeDef from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode -from syntaxtree import SyntaxNode -from pythonparse import parse_python_source -from pythonutil import PYTHON_PARSER +from pypy.interpreter.pyparser.syntaxtree import SyntaxNode +from pypy.interpreter.pyparser.pythonparse import parse_python_source +from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -100,20 +100,24 @@ ) def suite( space, source ): - builder = parse_python_source( source, PYTHON_PARSER, "file_input" ) + # make the annotator life easier (don't use str.splitlines()) + strings = [line + '\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) return space.wrap( STType(space, builder.stack[-1]) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): - builder = parse_python_source( source, PYTHON_PARSER, "eval_input" ) + # make the annotator life easier (don't use str.splitlines()) + strings = [line + '\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) return space.wrap( STType(space, builder.stack[-1]) ) expr.unwrap_spec = [ObjSpace, str] -def ast2tuple(space, node, line_info=False): +def ast2tuple(space, node, line_info=0): """Quick dummy implementation of parser.ast2tuple(tree) function""" tuples = node.totuple(line_info) return space.wrap(tuples) -ast2tuple.unwrap_spec = [ObjSpace, STType, bool] +ast2tuple.unwrap_spec = [ObjSpace, STType, int] Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Sun Jul 3 15:36:27 2005 @@ -10,7 +10,7 @@ spaces = [] oldstyle = 0 uselibfile = 0 - useparsermodule = "recparser" # "cpython" / "recparser" / "parser" + useparsermodule = "cpython" # "cpython" / "recparser" / "parser" parser = "cpython" # "cpython" / "pyparse" compiler = "cpython" # "cpython" # "pyparse" pypy parser, cpython compiler @@ -33,7 +33,7 @@ options.append(make_option( '--oldstyle', action="store_true",dest="oldstyle", - help="enable oldstyle classes as default metaclass (std objspace only)")) + help="enable oldstyle classes as default metaclass (std objspace only)")) options.append(make_option( '--file', action="store_true",dest="uselibfile", help="enable our custom file implementation")) @@ -47,6 +47,10 @@ options.append(make_option( '--pyparse', action="store_const", dest="compiler", const="pyparse", help="enable the internal pypy parser with CPython compiler")) + options.append(make_option( + '--parsermodule', action="store",type="string", dest="useparsermodule", + help="select the parser module to use", + metavar="[cpython|recparser|parser]")) return options From ac at codespeak.net Sun Jul 3 15:51:08 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 3 Jul 2005 15:51:08 +0200 (CEST) Subject: [pypy-svn] r14143 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703135108.050D727B46@code1.codespeak.net> Author: ac Date: Sun Jul 3 15:51:07 2005 New Revision: 14143 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_mutants.py - copied, changed from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mutants.py Log: Make test_mutans not time out. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_mutants.py (from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mutants.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_mutants.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_mutants.py Sun Jul 3 15:51:07 2005 @@ -151,7 +151,7 @@ test_one(random.randrange(1, 100)) # See last comment block for clues about good values for n. -test(100) +test(20) ########################################################################## # Another segfault bug, distilled by Michael Hudson from a c.l.py post. From quest at codespeak.net Sun Jul 3 16:23:28 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Sun, 3 Jul 2005 16:23:28 +0200 (CEST) Subject: [pypy-svn] r14145 - in pypy/branch/dist-2.4.1: lib-python/modified-2.4.1/test pypy/interpreter Message-ID: <20050703142328.B6B4227B46@code1.codespeak.net> Author: quest Date: Sun Jul 3 16:23:27 2005 New Revision: 14145 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_funcattrs.py - copied, changed from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_funcattrs.py Modified: pypy/branch/dist-2.4.1/pypy/interpreter/function.py pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py Log: Adapted to two changes in cpython 2.4.1: 1) function objects can now have their __name__ (and func_name) modified. 2) function objects can only have their func_code replaced with another code object with the same number of co_freevars. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_funcattrs.py (from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_funcattrs.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_funcattrs.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_funcattrs.py Sun Jul 3 16:23:27 2005 @@ -36,8 +36,8 @@ try: del b.__dict__ -except TypeError: pass -else: raise TestFailed, 'del func.__dict__ expected TypeError' +except (AttributeError, TypeError): pass +else: raise TestFailed, 'expected AttributeError or TypeError' b.publish = 1 try: @@ -175,13 +175,13 @@ try: del another.__dict__ -except TypeError: pass -else: raise TestFailed +except (TypeError, AttributeError): pass +else: raise TestFailed, 'del another.__dict__ did not fail' try: del another.func_dict -except TypeError: pass -else: raise TestFailed +except (TypeError, AttributeError): pass +else: raise TestFailed, 'del another.func_dict did not fail' try: another.func_dict = None Modified: pypy/branch/dist-2.4.1/pypy/interpreter/function.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/function.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/function.py Sun Jul 3 16:23:27 2005 @@ -115,6 +115,20 @@ def fset_func_doc(space, self, w_doc): self.w_doc = w_doc + def fget_func_name(space, self): + return space.wrap(self.name) + + def fset_func_name(space, self, w_name): + try: + self.name = space.str_w(w_name) + except OperationError, e: + if e.match(space, space.w_TypeError): + raise OperationError(space.w_TypeError, + space.wrap("func_name must be set " + "to a string object")) + raise + + def fdel_func_doc(space, self): self.w_doc = space.w_None @@ -137,8 +151,10 @@ def fset_func_code(space, self, w_code): code = space.interpclass_w(w_code) - if not isinstance(code, Code ): - raise OperationError( space.w_TypeError, space.wrap("func_code must be set to a code object") ) + if not isinstance(code, Code): + raise OperationError(space.w_TypeError, space.wrap("func_code must be set to a code object") ) + if len(self.code.co_freevars) != len(code.co_freevars): + raise OperationError(space.w_ValueError, space.wrap("%s() requires a code object with %s free vars, not %s " % (self.name, len(self.code.co_freevars), len(code.co_freevars)))) self.code = code def fget_func_closure(space, self): Modified: pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py Sun Jul 3 16:23:27 2005 @@ -430,6 +430,8 @@ Function.fdel_func_defaults) getset_func_code = GetSetProperty(Function.fget_func_code, Function.fset_func_code) +getset_func_name = GetSetProperty(Function.fget_func_name, + Function.fset_func_name) getset_func_dict = GetSetProperty(descr_get_dict, descr_set_dict, cls=Function) @@ -441,13 +443,13 @@ __repr__ = interp2app(Function.descr_function_repr), func_code = getset_func_code, func_doc = getset_func_doc, - func_name = interp_attrproperty('name', cls=Function), - func_dict = getset_func_dict, + func_name = getset_func_name, + func_dict = getset_func_dict, func_defaults = getset_func_defaults, func_globals = interp_attrproperty_w('w_func_globals', cls=Function), func_closure = GetSetProperty( Function.fget_func_closure ), __doc__ = getset_func_doc, - __name__ = interp_attrproperty('name', cls=Function), + __name__ = getset_func_name, __dict__ = getset_func_dict, __module__ = getset___module__, # XXX func_closure, etc.pp From niemeyer at codespeak.net Sun Jul 3 16:28:34 2005 From: niemeyer at codespeak.net (niemeyer at codespeak.net) Date: Sun, 3 Jul 2005 16:28:34 +0200 (CEST) Subject: [pypy-svn] r14146 - pypy/dist/lib-python/modified-2.3.4 Message-ID: <20050703142834.7B4EA27B46@code1.codespeak.net> Author: niemeyer Date: Sun Jul 3 16:28:33 2005 New Revision: 14146 Added: pypy/dist/lib-python/modified-2.3.4/sre_constants.py - copied, changed from r14036, pypy/dist/lib-python/2.3.4/sre_constants.py Log: Adding hack on modified-2.3.4/sre_constants.py file to make it work on the 2.4 engine. Copied: pypy/dist/lib-python/modified-2.3.4/sre_constants.py (from r14036, pypy/dist/lib-python/2.3.4/sre_constants.py) ============================================================================== --- pypy/dist/lib-python/2.3.4/sre_constants.py (original) +++ pypy/dist/lib-python/modified-2.3.4/sre_constants.py Sun Jul 3 16:28:33 2005 @@ -126,6 +126,14 @@ ] +# PyPy hack to make the sre_*.py files from 2.3.4 work on the _sre +# engine of 2.4. +import _sre +if _sre.MAGIC > MAGIC: + GROUPREF_EXISTS = "groupref_exists" + OPCODES.insert(OPCODES.index(GROUPREF)+1, GROUPREF_EXISTS) +del _sre + ATCODES = [ AT_BEGINNING, AT_BEGINNING_LINE, AT_BEGINNING_STRING, AT_BOUNDARY, AT_NON_BOUNDARY, AT_END, AT_END_LINE, AT_END_STRING, From arigo at codespeak.net Sun Jul 3 16:35:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 16:35:54 +0200 (CEST) Subject: [pypy-svn] r14147 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1 Message-ID: <20050703143554.3919127B46@code1.codespeak.net> Author: arigo Date: Sun Jul 3 16:35:53 2005 New Revision: 14147 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_compile.py - copied, changed from r14145, pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_compile.py pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_constants.py - copied, changed from r14145, pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_constants.py Log: Ported Gustavo's excellent revision 14146 in the other direction: it allows regular expressions to work in PyPy/2.4.1 on top of Python 2.3. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_compile.py (from r14145, pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_compile.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_compile.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_compile.py Sun Jul 3 16:35:53 2005 @@ -14,7 +14,8 @@ from sre_constants import * -assert _sre.MAGIC == MAGIC, "SRE module mismatch" +# XXX see PyPy hack in sre_constants to support both the 2.3 and 2.4 _sre.c implementation. +#assert _sre.MAGIC == MAGIC, "SRE module mismatch" if _sre.CODESIZE == 2: MAXCODE = 65535 Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_constants.py (from r14145, pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_constants.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/sre_constants.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/sre_constants.py Sun Jul 3 16:35:53 2005 @@ -127,6 +127,14 @@ ] +# PyPy hack to make the sre_*.py files from 2.4.1 work on the _sre +# engine of 2.3. +import _sre +if _sre.MAGIC < 20031017: + OPCODES.remove(GROUPREF_EXISTS) +del _sre + + ATCODES = [ AT_BEGINNING, AT_BEGINNING_LINE, AT_BEGINNING_STRING, AT_BOUNDARY, AT_NON_BOUNDARY, AT_END, AT_END_LINE, AT_END_STRING, From ludal at codespeak.net Sun Jul 3 16:41:43 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 16:41:43 +0200 (CEST) Subject: [pypy-svn] r14148 - in pypy/dist/pypy/interpreter/astcompiler: . CVS Message-ID: <20050703144143.4CB0327B46@code1.codespeak.net> Author: ludal Date: Sun Jul 3 16:41:42 2005 New Revision: 14148 Added: pypy/dist/pypy/interpreter/astcompiler/ - copied from r14147, pypy/branch/dist-2.4.1/lib-python/2.4.1/compiler/ Removed: pypy/dist/pypy/interpreter/astcompiler/CVS/ Log: * copied compiler module from 2.4.1 branch From arigo at codespeak.net Sun Jul 3 16:58:52 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 16:58:52 +0200 (CEST) Subject: [pypy-svn] r14150 - pypy/dist/pypy/rpython Message-ID: <20050703145852.C847327B46@code1.codespeak.net> Author: arigo Date: Sun Jul 3 16:58:50 2005 New Revision: 14150 Modified: pypy/dist/pypy/rpython/rdict.py Log: Cosmetics: removed the v_ prefix in low-level helpers. These names do not contain Variables but pointers and primitives. Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Jul 3 16:58:50 2005 @@ -331,37 +331,37 @@ # _____________________________________________________________ # methods -def ll_get(v_dict, v_key, v_default): - entry = ll_strdict_lookup(v_dict, v_key) +def ll_get(dict, key, default): + entry = ll_strdict_lookup(dict, key) if entry.key and entry.key != deleted_entry_marker: return entry.value else: - return v_default + return default -def ll_copy(v_dict): - DICTPTR = lltype.typeOf(v_dict) +def ll_copy(dict): + DICTPTR = lltype.typeOf(dict) d = lltype.malloc(DICTPTR.TO) - d.entries = lltype.malloc(DICTPTR.TO.entries.TO, len(v_dict.entries)) - d.num_items = v_dict.num_items - d.num_pristine_entries = v_dict.num_pristine_entries + d.entries = lltype.malloc(DICTPTR.TO.entries.TO, len(dict.entries)) + d.num_items = dict.num_items + d.num_pristine_entries = dict.num_pristine_entries i = 0 dictlen = len(d.entries) while i < dictlen: d_entry = d.entries[i] - v_entry = v_dict.entries[i] - d_entry.key = v_entry.key - d_entry.value = v_entry.value + entry = dict.entries[i] + d_entry.key = entry.key + d_entry.value = entry.value i += 1 return d -def ll_update(v_dic1, v_dic2): - d2len =len(v_dic2.entries) - entries = v_dic2.entries +def ll_update(dic1, dic2): + d2len =len(dic2.entries) + entries = dic2.entries i = 0 while i < d2len: entry = entries[i] if entry.key and entry.key != deleted_entry_marker: - ll_strdict_setitem(v_dic1, entry.key, entry.value) + ll_strdict_setitem(dic1, entry.key, entry.value) i += 1 def dum_keys(): pass @@ -370,13 +370,13 @@ # this is an implementation of keys(), values() and items() # in a single function. -# note that by specialization on v_func, three different +# note that by specialization on func, three different # and very efficient functions are created. -def ll_kvi(v_dic, LISTPTR, v_func): - res = rlist.ll_newlist(LISTPTR, v_dic.num_items) - dlen = len(v_dic.entries) - entries = v_dic.entries +def ll_kvi(dic, LISTPTR, func): + res = rlist.ll_newlist(LISTPTR, dic.num_items) + dlen = len(dic.entries) + entries = dic.entries items = res.items i = 0 p = 0 @@ -384,14 +384,14 @@ entry = entries[i] key = entry.key if key and key != deleted_entry_marker: - if v_func is dum_items: + if func is dum_items: r = lltype.malloc(LISTPTR.TO.items.TO.OF.TO) r.item0 = key r.item1 = entry.value items[p] = r - elif v_func is dum_keys: + elif func is dum_keys: items[p] = key - elif v_func is dum_values: + elif func is dum_values: items[p] = entry.value p += 1 i += 1 From arigo at codespeak.net Sun Jul 3 16:59:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 16:59:39 +0200 (CEST) Subject: [pypy-svn] r14151 - in pypy/dist/pypy/rpython: . test Message-ID: <20050703145939.7614D27B46@code1.codespeak.net> Author: arigo Date: Sun Jul 3 16:59:36 2005 New Revision: 14151 Modified: pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/test/test_rconstantdict.py Log: The get() method of constant dictionaries. Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sun Jul 3 16:59:36 2005 @@ -84,10 +84,10 @@ #def make_iterator_repr(self): # return StrDictIteratorRepr(self) - #def rtype_method_get(self, hop): - # v_dict, v_key, v_default = hop.inputargs(self, string_repr, - # self.value_repr) - # return hop.gendirectcall(ll_get, v_dict, v_key, v_default) + def rtype_method_get(self, hop): + v_dict, v_key, v_default = hop.inputargs(self, self.key_repr, + self.value_repr) + return hop.gendirectcall(ll_constantdict_get, v_dict, v_key, v_default) class __extend__(pairtype(ConstantDictRepr, rmodel.Repr)): @@ -125,6 +125,13 @@ entry = ll_constantdict_lookup(d, key)#, hashcompute) return entry.valid +def ll_constantdict_get(d, key, default):#, hashcompute): + entry = ll_constantdict_lookup(d, key)#, hashcompute) + if entry.valid: + return entry.value + else: + return default + def ll_constantdict_setnewitem(d, key, value):#, hashcompute): entry = ll_constantdict_lookup(d, key)#, hashcompute) assert not entry.valid Modified: pypy/dist/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rconstantdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rconstantdict.py Sun Jul 3 16:59:36 2005 @@ -16,3 +16,12 @@ assert res is False res = interpret(func, [4]) assert res is True + +def test_constantdict_get(): + d = {1: -11, 4: -44, 16: -66} + def func(i, j): + return d.get(i, j) + res = interpret(func, [15, 62]) + assert res == 62 + res = interpret(func, [4, 25]) + assert res == -44 From hpk at codespeak.net Sun Jul 3 17:07:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 17:07:58 +0200 (CEST) Subject: [pypy-svn] r14154 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050703150758.EC61427B46@code1.codespeak.net> Author: hpk Date: Sun Jul 3 17:07:52 2005 New Revision: 14154 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) implemented arrays (finally!) which use variable sized structs. used a recipe from Chris Lattner to compute the sizeof structs. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 17:07:52 2005 @@ -2,16 +2,55 @@ from pypy.rpython import lltype from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode +import itertools log = log.structnode +count = itertools.count().next + class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): self.db = db - assert isinstance(array, lltype.ArrayType) + assert isinstance(array, lltype.Array) self.array = array - self.ref_template = "%%array.%s" % array.OF - self.ref = self.ref_template + ".0" + ref_template = "%%array.%s." % array.OF + c = count() + self.ref = ref_template + str(c) + self.constructor_ref = "%%new.array.%s" % c + self.constructor_decl = "%s * %s(int %%len)" % ( + self.ref, self.constructor_ref) + + def writedecl(self, codewriter): + # declaration for constructor + codewriter.declare(self.constructor_decl) + + def writeimpl(self, codewriter): + """ this function generates a LLVM function like the following: + %array = type { int, [0 x double] } + %array *%NewArray(int %len) { + ;; Get the offset of the 'len' element of the array from the null + ;; pointer. + %size = getelementptr %array* null, int 0, uint 1, %int %len + %usize = cast double* %size to uint + %ptr = malloc sbyte, uint %usize + %result = cast sbyte* %ptr to %array* + %arraylength = getelementptr %array* %result, int 0, uint 0 + store int %len, int* %arraylength + ret %array* %result + }""" + log.writeimpl(self.ref) + codewriter.openfunc(self.constructor_decl) + indices = [("uint", 1), ("int", "%len")] + codewriter.getelementptr("%size", self.ref + "*", + "null", *indices) + fromtype = self.db.repr_arg_type(self.array.OF) + codewriter.cast("%usize", fromtype + "*", "%size", "uint") + codewriter.malloc("%ptr", "sbyte", "%usize") + codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") + codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) + codewriter.store("int", "%len", "%arraylength") + codewriter.ret(self.ref+"*", "%result") + codewriter.closefunc() def __str__(self): return "" % self.ref @@ -26,7 +65,6 @@ def writedatatypedecl(self, codewriter): codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) - # Each ArrayNode is a global constant. This needs to have a specific type of # a certain type. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 3 17:07:52 2005 @@ -105,7 +105,7 @@ self.indent("%%malloc.Ptr.%(cnt)d = malloc sbyte, uint %%malloc.SizeU.%(cnt)d" % locals()) self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) else: - self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)d" % locals()) + self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) def getelementptr(self, targetvar, type, typevar, *indices): res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals() Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 3 17:07:52 2005 @@ -14,10 +14,44 @@ lltype.Float: "double", lltype.Void: "void"} +class NormalizingDict(object): + """ this is a helper dict for obj2node in order + to allow saner key-unification for Ptrs to functions + (and possibly other stuff in the future) + """ + def __init__(self): + self._dict = {} + def __repr__(self): + return repr(self._dict) + def dump(self): + for x,y in self._dict.items(): + print x, y + def _get(self, key): + if isinstance(key, Constant): + if isinstance(key.value, lltype._ptr): + key = key.value._obj + return key + def __getitem__(self, key): + key = self._get(key) + return self._dict[key] + def __contains__(self, key): + key = self._get(key) + return key in self._dict + def __setitem__(self, key, value): + key = self._get(key) + self._dict[key] = value + def __delitem__(self, key): + key = self._get(key) + del self._dict[key] + def values(self): + return self._dict.values() + def items(self): + return self._dict.items() + class Database(object): def __init__(self, translator): self._translator = translator - self.obj2node = {} + self.obj2node = NormalizingDict() self._pendingsetup = [] self._tmpcount = 1 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 17:07:52 2005 @@ -255,16 +255,16 @@ self.codewriter.malloc(targetvar, type) def malloc_varsize(self, op): - XXXXXXXXXXXXXXXXXXXXXX targetvar = self.db.repr_arg(op.result) arg_type = op.args[0] assert (isinstance(arg_type, Constant) and isinstance(arg_type.value, lltype.Array)) -## struct_type = self.db.obj2node[arg_type.value].ref -## struct_cons = self.db.obj2node[arg_type.value].new_var_name + #XXX unclean + struct_type = self.db.obj2node[arg_type.value].ref + struct_cons = self.db.obj2node[arg_type.value].constructor_ref argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - self.codewriter.call("%example", "type*", "constructor", + self.codewriter.call(targetvar, struct_type + "*", struct_cons, argrefs, argtypes) def getfield(self, op): @@ -277,6 +277,7 @@ targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) + assert targettype != "void" #XXX This doesnt work - yet #if isinstance(op.result.concretetype, lltype.Ptr): # self.codewriter.cast(targetvar, targettype, tmpvar, targettype) @@ -293,9 +294,9 @@ fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index)) - valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) + assert valuetype != "void" self.codewriter.store(valuetype, valuevar, tmpvar) def getarrayitem(self, op): Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jul 3 17:07:52 2005 @@ -37,6 +37,7 @@ for typ_decl in db.getobjects(): typ_decl.writedecl(codewriter) + #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() for typ_decl in db.getobjects(): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 17:07:52 2005 @@ -220,18 +220,18 @@ def test_list_getitem(): def list_getitem(i): - l = [1,2,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(3) == 3 + assert f(2) == 3 def Xtest_string_getitem1(): l = "Hello, World" def string_test(i): return l[i] - f = compile_function(string_test, [int], view=False) + f = compile_function(string_test, [int], view=True) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From hpk at codespeak.net Sun Jul 3 17:19:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 17:19:58 +0200 (CEST) Subject: [pypy-svn] r14155 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050703151958.0739927B47@code1.codespeak.net> Author: hpk Date: Sun Jul 3 17:19:57 2005 New Revision: 14155 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) test some more list operations Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 17:19:57 2005 @@ -227,6 +227,23 @@ assert f(1) == 2 assert f(2) == 3 +def test_list_basic_ops(): + 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 Xtest_string_getitem1(): l = "Hello, World" def string_test(i): From ericvrp at codespeak.net Sun Jul 3 17:23:25 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 3 Jul 2005 17:23:25 +0200 (CEST) Subject: [pypy-svn] r14156 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050703152325.574F427B4E@code1.codespeak.net> Author: ericvrp Date: Sun Jul 3 17:23:24 2005 New Revision: 14156 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (ericvrp, bert): Added Garbage Collection using Boehm collector C library. Working nicely but we have no proper test yet. note: the use of the GC is enabled when /usr/lib/libgc.so exists. Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sun Jul 3 17:23:24 2005 @@ -12,6 +12,7 @@ from pypy.translator.pyrex.genpyrex import GenPyrex from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture +from pypy.translator.llvm2.genllvm import use_boehm_gc debug = True @@ -20,7 +21,7 @@ OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline" -def compile_module(module, source_files, object_files): +def compile_module(module, source_files, object_files, library_files): open("%s_setup.py" % module, "w").write(str(py.code.Source( ''' from distutils.core import setup @@ -29,6 +30,7 @@ ext_modules = [Extension( name = "%(module)s", sources = %(source_files)s, + libraries = %(library_files)s, extra_objects = %(object_files)s)]) ''' % locals()))) cmd = "python %s_setup.py build_ext --inplace" % module @@ -44,6 +46,9 @@ b = llvmfile.purebasename source_files = [ "%s.c" % modname ] object_files = [] + library_files = [] + if use_boehm_gc: + library_files.append('gc') if sys.maxint == 2147483647: #32 bit platform if optimize: @@ -76,7 +81,7 @@ if debug: print cmd cmdexec(cmd) make_c_from_pyxfile(pyxfile) - compile_module(modname, source_files, object_files) + compile_module(modname, source_files, object_files, library_files) finally: foutput, foutput = c.done() except: Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 3 17:23:24 2005 @@ -1,19 +1,16 @@ import py from itertools import count from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.codewriter show_line_numbers = True count = count().next -#hack -from os import getenv -use_boehm_gc = getenv('USER','') in ('eric',) -#/hack - class CodeWriter(object): def __init__(self): self._lines = [] + self.append('declare sbyte* %GC_malloc(uint)') def append(self, line): if show_line_numbers: @@ -102,7 +99,7 @@ cnt = count() self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)d" % locals()) self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) - self.indent("%%malloc.Ptr.%(cnt)d = malloc sbyte, uint %%malloc.SizeU.%(cnt)d" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc(uint %%malloc.SizeU.%(cnt)d)" % locals()) self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) else: self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jul 3 17:23:24 2005 @@ -1,3 +1,6 @@ +from os.path import exists +use_boehm_gc = exists('/usr/lib/libgc.so') + import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 17:23:24 2005 @@ -5,6 +5,7 @@ from pypy.translator.translator import Translator from pypy.translator.llvm2.genllvm import genllvm +from pypy.translator.llvm2.genllvm import use_boehm_gc from pypy.translator.llvm2.test import llvmsnippet from pypy.objspace.flow.model import Constant, Variable @@ -27,6 +28,24 @@ t.view() return genllvm(t) +def test_GC_malloc(): + if not use_boehm_gc: + py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") + return + py.test.skip("test_GC_malloc skipped because test not yet correct (Boehm collector IS used anyway)") + return + def tuple_getitem(n): + x = 0 + i = 0 + while i < n: + l = (1,2,i,234,23,23,23,234,234,234,234) + x += l[2] + i += 1 + return x + f = compile_function(tuple_getitem, [int]) + t = 1024*1024*100 + f(t) #assert f(t) == t + def test_return1(): def simple1(): return 1 From arigo at codespeak.net Sun Jul 3 18:09:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 18:09:53 +0200 (CEST) Subject: [pypy-svn] r14159 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050703160953.A891527B50@code1.codespeak.net> Author: arigo Date: Sun Jul 3 18:09:49 2005 New Revision: 14159 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: - more tests about methods in the rtyper, fixed by (don't blink) a new line in rclass.py that filters the method PBCs in the same way that the annotator does, i.e. by ignoring all methods that can't possibly be called at this point, either because they belong to unrelated classes, or because they belong to a parent class and we see that they are overridden. - a special case for built-in types, seen in faking Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Sun Jul 3 18:09:49 2005 @@ -315,7 +315,7 @@ return None return None - def matching(self, pbc, name): + def matching(self, pbc, name=None): d = {} uplookup = None upfunc = None @@ -341,7 +341,7 @@ # PBC dictionary to track more precisely with which 'self' the # method is called. d[upfunc] = self - elif meth: + elif meth and name is not None: self.check_missing_attribute_update(name) if d: return SomePBC(d) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sun Jul 3 18:09:49 2005 @@ -156,6 +156,7 @@ # as MethodType has a custom __get__ too and we don't support # it, it's a very bad idea anyway. if isinstance(s_value, annmodel.SomePBC): + s_value = self.classdef.matching(s_value) debound = {} count = 0 for x, classdef in s_value.prebuiltinstances.items(): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sun Jul 3 18:09:49 2005 @@ -41,6 +41,9 @@ choice = MethodOfFrozenPBCRepr else: raise TyperError("don't know about callable %r" % (x,)) + elif type(x) is type and x.__module__ == '__builtin__': + # special case for built-in types, seen in faking + choice = getPyObjRepr else: # frozen object choice = getFrozenPBCRepr @@ -63,6 +66,9 @@ # ____________________________________________________________ +def getPyObjRepr(rtyper, s_pbc): + return robject.pyobj_repr + def getFrozenPBCRepr(rtyper, s_pbc): if len(s_pbc.prebuiltinstances) <= 1: Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sun Jul 3 18:09:49 2005 @@ -37,6 +37,10 @@ def m(self, x): return self.z - x +class MyStrangerSubclass(MyBase): + def m(self, x, y): + return x*y + def test_method_call(): def f(a, b): obj = MyBase() @@ -58,17 +62,51 @@ res = interpret(f, [-1, 2.3]) assert res == -3.3 +def test_stranger_subclass_1(): + def f1(): + obj = MyStrangerSubclass() + obj.z = 100 + return obj.m(6, 7) + res = interpret(f1, []) + assert res == 42 + +def test_stranger_subclass_2(): + def f2(): + obj = MyStrangerSubclass() + obj.z = 100 + return obj.m(6, 7) + MyBase.m(obj, 58) + res = interpret(f2, []) + assert res == 200 + class MyBaseWithInit: def __init__(self, a): self.a1 = a +class MySubclassWithInit(MyBaseWithInit): + def __init__(self, a, b): + MyBaseWithInit.__init__(self, a) + self.b1 = b + def test_class_init(): def f(a): instance = MyBaseWithInit(a) return instance.a1 assert interpret(f, [5]) == 5 +def test_class_init_2(): + def f(a, b): + instance = MySubclassWithInit(a, b) + return instance.a1 * instance.b1 + assert interpret(f, [6, 7]) == 42 + +def test_class_calling_init(): + def f(): + instance = MySubclassWithInit(1, 2) + instance.__init__(3, 4) + return instance.a1 * instance.b1 + assert interpret(f, []) == 12 + class Freezing: def _freeze_(self): From ac at codespeak.net Sun Jul 3 18:28:20 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 3 Jul 2005 18:28:20 +0200 (CEST) Subject: [pypy-svn] r14160 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050703162820.A899327B3E@code1.codespeak.net> Author: ac Date: Sun Jul 3 18:28:20 2005 New Revision: 14160 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_copy.py - copied, changed from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_copy.py Log: Dissable test that don't make sens in PyPy. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_copy.py (from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_copy.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_copy.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_copy.py Sun Jul 3 18:28:20 2005 @@ -166,24 +166,25 @@ x = C(42) self.assertEqual(copy.copy(x), x) + # These test make no sense in PyPy # tests for copying extension types, iff module trycopy is installed - def test_copy_classictype(self): - from _testcapi import make_copyable - x = make_copyable([23]) - y = copy.copy(x) - self.assertEqual(x, y) - self.assertEqual(x.tag, y.tag) - self.assert_(x is not y) - self.assert_(x.tag is y.tag) - - def test_deepcopy_classictype(self): - from _testcapi import make_copyable - x = make_copyable([23]) - y = copy.deepcopy(x) - self.assertEqual(x, y) - self.assertEqual(x.tag, y.tag) - self.assert_(x is not y) - self.assert_(x.tag is not y.tag) + #def test_copy_classictype(self): + # from _testcapi import make_copyable + # x = make_copyable([23]) + # y = copy.copy(x) + # self.assertEqual(x, y) + # self.assertEqual(x.tag, y.tag) + # self.assert_(x is not y) + # self.assert_(x.tag is y.tag) + + #def test_deepcopy_classictype(self): + # from _testcapi import make_copyable + # x = make_copyable([23]) + # y = copy.deepcopy(x) + # self.assertEqual(x, y) + # self.assertEqual(x.tag, y.tag) + # self.assert_(x is not y) + # self.assert_(x.tag is not y.tag) # regression tests for class-vs-instance and metaclass-confusion def test_copy_classoverinstance(self): From ac at codespeak.net Sun Jul 3 18:29:00 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 3 Jul 2005 18:29:00 +0200 (CEST) Subject: [pypy-svn] r14161 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1 Message-ID: <20050703162900.4F4D927B3E@code1.codespeak.net> Author: ac Date: Sun Jul 3 18:28:59 2005 New Revision: 14161 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/copy.py - copied, changed from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/copy.py Log: Make the copy module mych faster by not importing the inspect module. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/copy.py (from r14133, pypy/branch/dist-2.4.1/lib-python/2.4.1/copy.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/copy.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/copy.py Sun Jul 3 18:28:59 2005 @@ -62,9 +62,24 @@ __all__ = ["Error", "copy", "deepcopy"] -import inspect def _getspecial(cls, name): - for basecls in inspect.getmro(cls): + def getmro(cls): + def _searchbases(cls): + # Simulate the "classic class" search order. + if cls in result: + return + result.append(cls) + for base in cls.__bases__: + _searchbases(base) + + if hasattr(cls, "__mro__"): + return cls.__mro__ + else: + result = [] + _searchbases(cls) + return result + + for basecls in getmro(cls): try: return basecls.__dict__[name] except: From adim at codespeak.net Sun Jul 3 18:34:56 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 18:34:56 +0200 (CEST) Subject: [pypy-svn] r14162 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050703163456.67CD927B3E@code1.codespeak.net> Author: adim Date: Sun Jul 3 18:34:55 2005 New Revision: 14162 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Log: - added more context-information in the token stack - TokenError now extends SyntaxError to be more compliant with the way the compiler package handles errors - fixed test_pytokenizer to match the new API Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Sun Jul 3 18:34:55 2005 @@ -70,13 +70,13 @@ tokenmod.COMMENT = tokenmod.N_TOKENS tokenmod.NL = tokenmod.N_TOKENS + 1 -class TokenError(Exception): +class TokenError(SyntaxError): """Raised when EOF is found prematuerly""" def __init__(self, msg, strstart, token_stack): - # Exception.__init__(self, msg) - self.strstart = strstart + self.lineno, self.offset = strstart + self.text = "XXX" + self.msg = "TokenError at pos (%d, %d)" % (self.lineno, self.offset) self.token_stack = token_stack - def generate_tokens(lines): """ @@ -125,7 +125,7 @@ if -1 != endmatch: pos = end = endmatch tok = token_from_values(tokenmod.STRING, contstr + line[:end]) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((STRING, contstr + line[:end], # strstart, (lnum, end), contline + line)) @@ -133,7 +133,7 @@ contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': tok = token_from_values(tokenmod.ERRORTOKEN, contstr + line) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((ERRORTOKEN, contstr + line, # strstart, (lnum, len(line)), contline)) @@ -168,7 +168,7 @@ tok = token_from_values(tokenmod.NL, line[pos:]) last_comment = '' # XXX Skip NL and COMMENT Tokens - # token_list.append((tok, line)) + # token_list.append((tok, line, lnum, pos)) # token_list.append(((NL, COMMENT)[line[pos] == '#'], # line[pos:], # (lnum, pos), (lnum, len(line)), line)) @@ -177,13 +177,13 @@ if column > indents[-1]: # count indents or dedents indents.append(column) tok = token_from_values(tokenmod.INDENT, line[:pos]) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((INDENT, line[:pos],(lnum, 0),(lnum,pos),line)) while column < indents[-1]: indents = indents[:-1] tok = token_from_values(tokenmod.DEDENT, '') - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((DEDENT, '', (lnum, pos),(lnum,pos),line)) @@ -207,7 +207,7 @@ if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number tok = token_from_values(tokenmod.NUMBER, token) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((NUMBER, token, spos, epos, line)) elif initial in '\r\n': @@ -219,7 +219,7 @@ tok = token_from_values(tokenmod.NEWLINE, token) # XXX YUCK ! tok.value = last_comment - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) elif initial == '#': @@ -229,7 +229,7 @@ encoding = match_encoding_declaration(last_comment) if encoding is not None: encoding = _normalize_encoding(encoding) - # XXX Skip # token_list.append((tok, line)) + # XXX Skip # token_list.append((tok, line, lnum, pos)) # token_list.append((COMMENT, token, spos, epos, line)) elif token in triple_quoted: endDFA = endDFAs[token] @@ -238,7 +238,7 @@ pos = endmatch token = line[start:pos] tok = token_from_values(tokenmod.STRING, token) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((STRING, token, spos, (lnum, pos), line)) else: @@ -258,12 +258,12 @@ break else: # ordinary string tok = token_from_values(tokenmod.STRING, token) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((STRING, token, spos, epos, line)) elif initial in namechars: # ordinary name tok = token_from_values(tokenmod.NAME, token) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((NAME, token, spos, epos, line)) elif initial == '\\': # continued stmt @@ -272,12 +272,12 @@ if initial in '([{': parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 tok = token_from_values(tokenmod.OP, token) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((OP, token, spos, epos, line)) else: tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((ERRORTOKEN, line[pos], # (lnum, pos), (lnum, pos+1), line)) @@ -286,14 +286,14 @@ last_comment = '' for indent in indents[1:]: # pop remaining indent levels tok = token_from_values(tokenmod.DEDENT, '') - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) ## adim - token_list.append((Token('NEWLINE', ''), line)) + token_list.append((Token('NEWLINE', ''), line, lnum, 0)) ## tok = token_from_values(tokenmod.ENDMARKER, '',) - token_list.append((tok, line)) + token_list.append((tok, line, lnum, pos)) # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) return token_list, encoding @@ -305,15 +305,19 @@ self.token_stack = tokens self.encoding = encoding self._current_line = '' # the current line (as a string) + self._lineno = -1 + self._offset = 0 self.stack_pos = 0 def next(self): """Returns the next parsed token""" if self.stack_pos >= len(self.token_stack): raise StopIteration("Remove me") - tok, line = self.token_stack[self.stack_pos] + tok, line, lnum, pos = self.token_stack[self.stack_pos] self.stack_pos += 1 self._current_line = line + self._lineno = lnum + self._offset = pos return tok def current_line(self): @@ -340,22 +344,23 @@ if ctx is None: return self.stack_pos else: - assert type(ctx)==int + assert type(ctx) == int return ctx def get_pos(self): if self.stack_pos >= len(self.stack): return self.pos else: - token, line, pos = self.stack[self.stack_pos] - return pos + token, line, lnum, pos = self.stack[self.stack_pos] + return lnum, pos - def get_source_text(self, pos0, pos1 ): + def get_source_text(self, pos0, pos1): return self.input[pos0:pos1] def debug(self): """return context for debug information""" - return 'line %s : %s' % ('XXX', self._current_line) + return (self._current_line, self._lineno) + # return 'line %s : %s' % ('XXX', self._current_line) NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] NAMED_LIST = [tokenmod.OP, ] Modified: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Sun Jul 3 18:34:55 2005 @@ -72,7 +72,7 @@ try: tokens = parse_source(pstr) except TokenError, error: - tokens = [tok for tok, line in error.token_stack] + tokens = [tok for tok, _, _, _ in error.token_stack] assert tokens[0].name == pstr From adim at codespeak.net Sun Jul 3 18:36:04 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 18:36:04 +0200 (CEST) Subject: [pypy-svn] r14163 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20050703163604.C3D8F27B3E@code1.codespeak.net> Author: adim Date: Sun Jul 3 18:36:04 2005 New Revision: 14163 Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: added test to make sure that the parser raises TokenErrors on incomplete inputs Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Sun Jul 3 18:36:04 2005 @@ -1,11 +1,15 @@ """test module for CPython / PyPy nested tuples comparison""" import os, os.path as osp +from symbol import sym_name +from pprint import pprint + +import py.test + from pypy.interpreter.pyparser.pythonutil import python_parsefile, \ pypy_parsefile, python_parse, pypy_parse -from pprint import pprint from pypy.interpreter.pyparser import grammar +from pypy.interpreter.pyparser.pythonlexer import TokenError grammar.DEBUG = False -from symbol import sym_name def name(elt): return "%s[%s]"% (sym_name.get(elt,elt),elt) @@ -92,8 +96,11 @@ snippets = [ # '\t # hello\n ', 'print 6*7', 'if 1:\n x\n', - # 'if 1:\n x', 'x = (', 'x = (\n', # 'x = (\n\n', ] for snippet in snippets: - print "snippet =", repr(snippet) yield check_parse_input, snippet, 'exec' + +def test_bad_inputs(): + inputs = ['x = (', 'x = (\n', 'x = (\n\n'] + for inp in inputs: + py.test.raises(TokenError, pypy_parse, inp) From adim at codespeak.net Sun Jul 3 18:39:12 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 18:39:12 +0200 (CEST) Subject: [pypy-svn] r14164 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050703163912.0712127B3E@code1.codespeak.net> Author: adim Date: Sun Jul 3 18:39:11 2005 New Revision: 14164 Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py Log: added a lineno optional argument to be able to choose if linenos should be included in the nested tuples (needed for the compiler) Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Sun Jul 3 18:39:11 2005 @@ -16,15 +16,15 @@ } ## convenience functions around CPython's parser functions -def python_parsefile(filename): +def python_parsefile(filename, lineno=False): """parse using CPython's parser module and return nested tuples """ pyf = file(filename) source = pyf.read() pyf.close() - return python_parse(source) + return python_parse(source, 'exec', lineno) -def python_parse(source, mode='exec'): +def python_parse(source, mode='exec', lineno=False): """parse python source using CPython's parser module and return nested tuples """ @@ -35,7 +35,7 @@ return tp.totuple() ## convenience functions around recparser functions -def pypy_parsefile(filename): +def pypy_parsefile(filename, lineno=False): """parse using PyPy's parser module and return a tuple of three elements : - The encoding declaration symbol or None if there were no encoding @@ -49,9 +49,9 @@ pyf = file(filename) source = pyf.read() pyf.close() - return pypy_parse(source) + return pypy_parse(source, 'exec', lineno) -def pypy_parse(source, mode='exec'): +def pypy_parse(source, mode='exec', lineno=False): """parse using PyPy's parser module and return a tuple of three elements : - The encoding declaration symbol or None if there were no encoding @@ -74,21 +74,24 @@ target_rule = TARGET_DICT[mode] pythonparse.parse_python_source(strings, PYTHON_PARSER, target_rule, builder) - # stack_element is a tuplerbuilder.StackElement's instance +## if builder.error_occured(): +## line, lineno, offset, filename = builder.get_error() +## raise SyntaxError(line, lineno, offset, filename) +## # stack_element is a tuplerbuilder.StackElement's instance stack_element = builder.stack[-1] # convert the stack element into nested tuples # XXX : the annotator can't follow this call - nested_tuples = stack_element.as_tuple() + nested_tuples = stack_element.as_tuple(lineno) if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) else: return nested_tuples -## convenience functions for computing AST objects based on recparser +## convenience functions for computing AST objects using recparser def ast_from_input(input, mode): - tuples = pypy_parse(input, mode) + tuples = pypy_parse(input, mode, True) transformer = Transformer() - ast = transformer.transform(tuples) + ast = transformer.compile_node(tuples) return ast ## TARGET FOR ANNOTATORS ############################################# From arigo at codespeak.net Sun Jul 3 18:42:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 18:42:43 +0200 (CEST) Subject: [pypy-svn] r14165 - in pypy/dist/pypy/rpython: . test Message-ID: <20050703164243.4968527B3E@code1.codespeak.net> Author: arigo Date: Sun Jul 3 18:42:40 2005 New Revision: 14165 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Support Void attributes for prebuilt instances. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sun Jul 3 18:42:40 2005 @@ -397,8 +397,11 @@ result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): - attrvalue = getattr(value, name) - llattrvalue = r.convert_const(attrvalue) + if r.lowleveltype == Void: + llattrvalue = None + else: + attrvalue = getattr(value, name) + llattrvalue = r.convert_const(attrvalue) setattr(result, mangled_name, llattrvalue) else: # OBJECT part 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 Sun Jul 3 18:42:40 2005 @@ -63,6 +63,16 @@ res = interpret(dummyfn, []) assert res == 6 +def test_prebuilt_instances_with_void(): + def marker(): + return 42 + a = EmptyBase() + a.nothing_special = marker + def dummyfn(): + return a.nothing_special() + res = interpret(dummyfn, []) + assert res == 42 + # method calls class A: def f(self): From adim at codespeak.net Sun Jul 3 18:43:27 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 18:43:27 +0200 (CEST) Subject: [pypy-svn] r14166 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050703164327.9A6E727B3E@code1.codespeak.net> Author: adim Date: Sun Jul 3 18:43:26 2005 New Revision: 14166 Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Log: - changed default value of lineno optional argument from None to False (more homogeneous / easier to annotate) - re-raise a SyntaxError instead of returning None to be match the pycompiler requirements (will probably re-change soon) Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Sun Jul 3 18:43:26 2005 @@ -30,8 +30,15 @@ debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar() +class BuilderError(SyntaxError): + def __init__(self, line, lineno): + self.filename = 'XXX.py' + self.line = self.text = line + self.lineno = lineno + self.offset = -1 + self.msg = "SyntaxError at line %d: %r" % (self.lineno, self.line) -def parse_python_source( textsrc, gram, goal, builder=None ): +def parse_python_source(textsrc, gram, goal, builder=None): """Parse a python source according to goal""" target = gram.rules[goal] src = Source(textsrc) @@ -44,8 +51,9 @@ if not result: # raising a SyntaxError here is not annotable, and it can # probably be handled in an other way - # raise SyntaxError("at %s" % src.debug() ) - return None + line, lineno = src.debug() + raise BuilderError(line, lineno) + # return None return builder def parse_file_input(pyf, gram, builder=None): Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Sun Jul 3 18:43:26 2005 @@ -10,8 +10,8 @@ self.nodes = [(num, value, lineno)] self.num = num - def as_tuple(self, lineno=None): - if lineno is not None: + def as_tuple(self, lineno=False): + if lineno: return self.nodes[0] else: return self.nodes[0][:-1] @@ -22,7 +22,7 @@ self.nodes = nodes self.num = num - def as_tuple(self, lineno=None): + def as_tuple(self, lineno=False): l = [self.num] + [node.as_tuple(lineno) for node in self.nodes] return tuple(l) @@ -46,11 +46,11 @@ self.source_encoding = None self.lineno = lineno self._unknown = -10 - + def _add_rule(self, rulename): SYMBOLS[rulename] = self._unknown self._unknown -= 1 - + def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): From arigo at codespeak.net Sun Jul 3 18:43:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 18:43:59 +0200 (CEST) Subject: [pypy-svn] r14167 - in pypy/dist/pypy/rpython: . test Message-ID: <20050703164359.2320827B3E@code1.codespeak.net> Author: arigo Date: Sun Jul 3 18:43:56 2005 New Revision: 14167 Added: pypy/dist/pypy/rpython/remptydict.py (contents, props changed) pypy/dist/pypy/rpython/test/test_remptydict.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rdict.py Log: We need to support empty dictionaries for PyPy :-) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Jul 3 18:43:56 2005 @@ -3,7 +3,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rarithmetic import r_uint -from pypy.rpython import rlist, rconstantdict +from pypy.rpython import rlist, rconstantdict, remptydict # ____________________________________________________________ # @@ -39,6 +39,8 @@ return rconstantdict.ConstantDictRepr( rtyper.getrepr(dictkey.s_value), rtyper.getrepr(dictvalue.s_value)) + elif isinstance(s_key, annmodel.SomeImpossibleValue): + return remptydict.EmptyDictRepr() else: raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) Added: pypy/dist/pypy/rpython/remptydict.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/remptydict.py Sun Jul 3 18:43:56 2005 @@ -0,0 +1,14 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.rpython import rmodel, lltype + +# ____________________________________________________________ +# +# PyPy uses dictionaries that are known to be empty at run-time! +# look for 'lazyloaders'. + +class EmptyDictRepr(rmodel.Repr): + lowleveltype = lltype.Void + + def rtype_len(self, hop): + return hop.inputconst(lltype.Signed, 0) Added: pypy/dist/pypy/rpython/test/test_remptydict.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_remptydict.py Sun Jul 3 18:43:56 2005 @@ -0,0 +1,12 @@ +import py +from pypy.rpython.test.test_llinterp import interpret + +def test_empty_dict(): + class A: + pass + a = A() + a.d = {} + def func(): + return bool(a.d) + res = interpret(func, []) + assert res is False From adim at codespeak.net Sun Jul 3 18:47:40 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 18:47:40 +0200 (CEST) Subject: [pypy-svn] r14168 - in pypy/dist/pypy/interpreter: . test Message-ID: <20050703164740.84CFF27B3E@code1.codespeak.net> Author: adim Date: Sun Jul 3 18:47:39 2005 New Revision: 14168 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/test/test_compiler.py Log: - fixed dummy errors in pycompiler - tests using PythonCompiler now work again - (the flags test is skipped for now because it's a bit messy when using the compiler package) Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Sun Jul 3 18:47:39 2005 @@ -176,15 +176,21 @@ from pyparser.pythonparse import parse_python_source, PYTHON_PARSER from pyparser.tuplebuilder import TupleBuilder from pyparser.pythonutil import ast_from_input +import compiler class PythonCompiler(CPythonCompiler): - """Uses the stdlib's python implementation of compiler""" + """Uses the stdlib's python implementation of compiler + XXX: This class should override the baseclass implementation of + compile_command() in order to optimize it, especially in case + of incomplete inputs (e.g. we shouldn't re-compile from sracth + the whole source after having only added a new '\n') + """ def compile(self, source, filename, mode, flags): flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: - ast = ast_from_input(source, mode) + tree = ast_from_input(source, mode) compiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) @@ -210,12 +216,9 @@ from pypy.interpreter.pycode import PyCode return space.wrap(PyCode(space)._from_code(c)) -# This doesn't work for now + class PyPyCompiler(CPythonCompiler): """Uses the PyPy implementation of Compiler - WRITEME + XXX: WRITEME """ -# PyPyCompiler = PythonCompiler = CPythonCompiler -# PyPyCompiler = CPythonCompiler -# PythonCompiler = CPythonCompiler Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Sun Jul 3 18:47:39 2005 @@ -37,6 +37,7 @@ 'if 1:\n x x', '?', 'exec', 0) def test_getcodeflags(self): + py.test.skip("flags don't work correctly when using the compiler package") code = self.compiler.compile('from __future__ import division\n', '', 'exec', 0) flags = self.compiler.getcodeflags(code) @@ -56,12 +57,10 @@ def setup_method(self, method): self.compiler = CPythonCompiler(self.space) - -class SkippedForNowTestPurePythonCompiler(BaseTestCompiler): +class TestPurePythonCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = PythonCompiler(self.space) - class SkippedForNowTestPyPyCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = PyPyCompiler(self.space) From arigo at codespeak.net Sun Jul 3 18:49:06 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 18:49:06 +0200 (CEST) Subject: [pypy-svn] r14169 - pypy/dist/pypy/rpython Message-ID: <20050703164906.8175827B3E@code1.codespeak.net> Author: arigo Date: Sun Jul 3 18:49:04 2005 New Revision: 14169 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Ignore the constant value in this check if it is a Void constant. (The value of Void constants should generally be ignored anyway.) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun Jul 3 18:49:04 2005 @@ -267,7 +267,8 @@ # in all generated operations. if hop.s_result.is_constant(): if isinstance(resultvar, Constant) and \ - isinstance(hop.r_result.lowleveltype, Primitive): + isinstance(hop.r_result.lowleveltype, Primitive) and \ + hop.r_result.lowleveltype != Void: assert resultvar.value == hop.s_result.const resulttype = resultvar.concretetype op.result.concretetype = hop.r_result.lowleveltype From arigo at codespeak.net Sun Jul 3 19:06:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 19:06:19 +0200 (CEST) Subject: [pypy-svn] r14170 - pypy/dist/pypy/interpreter Message-ID: <20050703170619.182C127B46@code1.codespeak.net> Author: arigo Date: Sun Jul 3 19:06:17 2005 New Revision: 14170 Modified: pypy/dist/pypy/interpreter/typedef.py Log: Annotation fine-tuning: get_unique_interplevel_subclass() is called from allocate_instance() in objspace/std, which is specialized on the 'cls'. So the same specialization is needed for get_unique_interplevel_subclass(). Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Sun Jul 3 19:06:17 2005 @@ -39,6 +39,7 @@ return get_unique_interplevel_NoDictWithSlots(cls) else: return get_unique_interplevel_NoDictNoSlots(cls) +get_unique_interplevel_subclass._annspecialcase_ = "specialize:arg0" for hasdict in False, True: for wants_slots in False, True: From arigo at codespeak.net Sun Jul 3 19:06:52 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 19:06:52 +0200 (CEST) Subject: [pypy-svn] r14171 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050703170652.A12B427B46@code1.codespeak.net> Author: arigo Date: Sun Jul 3 19:06:52 2005 New Revision: 14171 Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Log: Ported rev 14170 from the trunk to the snapshot branch. Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Sun Jul 3 19:06:52 2005 @@ -39,6 +39,7 @@ return get_unique_interplevel_NoDictWithSlots(cls) else: return get_unique_interplevel_NoDictNoSlots(cls) +get_unique_interplevel_subclass._annspecialcase_ = "specialize:arg0" for hasdict in False, True: for wants_slots in False, True: From adim at codespeak.net Sun Jul 3 19:10:38 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Sun, 3 Jul 2005 19:10:38 +0200 (CEST) Subject: [pypy-svn] r14172 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050703171038.D8CAE27B46@code1.codespeak.net> Author: adim Date: Sun Jul 3 19:10:38 2005 New Revision: 14172 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Log: define pos out of the loop to make the annotator happy Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Sun Jul 3 19:10:38 2005 @@ -109,7 +109,7 @@ last_comment = '' encoding = None strstart = (0, 0) - + pos = -1 lines.append('') # XXX HACK probably not needed endDFA = automata.DFA([], []) # XXX Make the translator happy line = '' # XXX Make the translator happy From arigo at codespeak.net Sun Jul 3 19:44:51 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 19:44:51 +0200 (CEST) Subject: [pypy-svn] r14173 - pypy/dist/pypy/rpython Message-ID: <20050703174451.2725327B42@code1.codespeak.net> Author: arigo Date: Sun Jul 3 19:44:49 2005 New Revision: 14173 Modified: pypy/dist/pypy/rpython/rpbc.py Log: Sanitized the selection of PBC representations. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sun Jul 3 19:44:49 2005 @@ -16,6 +16,7 @@ # categories below, and doesn't for example mix functions, classes # and methods. call_families = rtyper.annotator.getpbccallfamilies() + userclasses = rtyper.annotator.getuserclasses() choices = {} for x, classdef in self.prebuiltinstances.items(): cdefflag = isclassdef(classdef) @@ -26,31 +27,40 @@ if isinstance(x, types.MethodType) and x.im_self is None: x = x.im_func - # callable or frozen object? - if (classdef, x) in call_families: - # what type of callable? - if isinstance(x, types.FunctionType): - if cdefflag: - choice = MethodsPBCRepr - cdefflag = False - else: - choice = FunctionsPBCRepr - elif isinstance(x, (type, types.ClassType)): + if cdefflag: + # methods of a run-time instance + if not isinstance(x, types.FunctionType): + raise TyperError("%r appears to be a method bound to %r, " + "but it is not a function" % ( + x, classdef)) + choice = MethodsPBCRepr + + elif isinstance(x, (type, types.ClassType)): + # classes + if x in userclasses: + # user classes choice = ClassesPBCRepr + elif type(x) is type and x.__module__ == '__builtin__': + # special case for built-in types, seen in faking + choice = getPyObjRepr + else: + raise TyperError("don't known about class %r" % (x,)) + + elif (classdef, x) in call_families: + # other kind of callable + if isinstance(x, types.FunctionType): + # function + choice = FunctionsPBCRepr elif isinstance(x, types.MethodType): + # prebuilt bound method choice = MethodOfFrozenPBCRepr else: raise TyperError("don't know about callable %r" % (x,)) - elif type(x) is type and x.__module__ == '__builtin__': - # special case for built-in types, seen in faking - choice = getPyObjRepr + else: - # frozen object + # otherwise, just assume it's a plain frozen object choice = getFrozenPBCRepr - if cdefflag: - raise TyperError("unexpected classdef in PBC set %r" % ( - self.prebuiltinstances,)) choices[choice] = True if len(choices) > 1: From hpk at codespeak.net Sun Jul 3 19:50:38 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 19:50:38 +0200 (CEST) Subject: [pypy-svn] r14174 - pypy/extradoc/sprintinfo Message-ID: <20050703175038.B015B27B49@code1.codespeak.net> Author: hpk Date: Sun Jul 3 19:50:37 2005 New Revision: 14174 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: update after common session Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sun Jul 3 19:50:37 2005 @@ -39,7 +39,7 @@ we decide about pairing at the venue (after everybody tells what he/she is interested in). These are the people expected currently:: - Gustavo Niemeyer until 2nd (including) + Gustavo Niemeyer until 3rd (including) Adrien Di Mascio until 4th (including) @@ -48,7 +48,6 @@ Armin Rigo whole-time - Mikael Jansson until 2nd (including) Niklaus Haldimann until 4th (including) Ludovic Aubry until 4th (including) @@ -63,14 +62,7 @@ Eric van Riet Paap until 8th Bert Freudenberg whole-time - Marius Gedminas until 2nd (including) - Gintas M. until 2nd (including) - Ignas M. until 2nd (including) Beatrice Duering (visiting, 5th-) - Rob Collins until 2nd afternoon - #Joe Wrigley until 2nd morning - Volker Gietz 2nd only - Translation tasks ------------------ @@ -118,26 +110,29 @@ ----------------------- subcoach: Armin -Niklaus, Gintas, Ignas, Arre, Anders, Mikael - +Niklaus, Arre, Anders experiment in a branch with using Python 2.4 semantics and the standard library -* use lib-python/2.4.1 instead of 2.3.4, review all modified - tests and library modules (good progress, we still need to - review ca. 25 modified test files) +* (MOSTLY DONE) use lib-python/2.4.1 instead of 2.3.4, review all + modified tests and library modules (good progress, we still need to + review ca. 1 modified test files) + +* Merge 2.4.1 branch (blocked by parser/compiler being able + to process 2.4.1 files on top of CPython 2.3.4) * DONE: semantic differences: comparison of recursive data structures, more? * new required C-level modules: - - MOSTLY DONE: 'sets' - - implement 'collections' module + - DONE: 'sets' + - (mostly naively mostly done) implement 'collections' module - (probably) revert 'bisect' module to the 2.3 version (or 2.5) - (probably) revert 'heapq' module to the 2.3 version (2.5) -* check that test results page still works (and fix) +* check that test results page still works (and fix) after + we merged 2.4.1 branch Misc @@ -148,24 +143,26 @@ Consider distributing the actual annotation to multiple hosts. * (medium) finish objspace/std/longobject.py. - - div implementation (christian, jacob) + - (MOSTLY DONE) div implementation (christian, jacob) * (hard, starting soon to be discussed) find a way to generate c_api calls (including automated conversions from ll-strings to c-like strings) + -> conceptually discussed, needs to be written + down and posted to pypy-dev (samuele/holger) * fix Windows-related issues * '%'-formatting rounding errors ( '%.3f' % (2.999999,)) -* (progressing) add missing docstrings on app-level built-in types and functions, - etc. (Laura): there now is a program that generates the docstrings - into the appropriate places but it needs prettification. +* (mostly done) add missing docstrings on app-level built-in types and + functions, etc. (Laura): there now is a program that generates the + docstrings into the appropriate places but it needs prettification. -* (should start sunday) GC discussion in the middle of the sprint - (kickoff Carl Friedrich) +* (should start sometime soon) GC discussion in the middle of the sprint + (kickoff Carl Friedrich with Armin/Samuele) -* (should start sunday) _sre module reimplementation kickoff +* DONE: (should start sunday) _sre module reimplementation kickoff Rewriting important C functionality in Python -------------------------------------------------- @@ -177,15 +174,21 @@ a case-by-case basis). - (DONE) Parser is fully annotable - not translated and run in C, yet. + + * (DONE) parser integrated in PyPy ("py.py --pyparse" for + non-interactive usage), needs more testing. + + * (progress, Ludovic, Adrien) try to make 2.4.1 compiler + package work for PyPy and using the parser. - * (starting, Ludovic, Adrien) move towards a rpython - compliant (translatable) compiler + * move towards a rpython compliant (translatable) compiler * rewrite in Python a C module you are familiar with (partial list of missing/incomplete modules: math, array, regular expressions, binascii...) -* (Jacob, progressing) finish binascii implementation +* (Jacob, progress) binascii implementation, needs more tests + (but compliancy tests already pass) * implement Python 2.3's import hook extensions (zip-imports etc.) @@ -198,17 +201,25 @@ - (DONE, eric, bert) make llvm work on osx -- (PROGRESS, cfbolz, rxe) implement variable - sized structs (Richard, Eric / Carl) +- (DONE) arrays work (special case of variable sized structs) + +- (PROGRESS, cfbolz, hpk) implement variable + sized structs -- (Eric, Bert) more void transformations +- DONE: (Eric, Bert) added some void-helpers to Structs - there are problems with voids all around the flowgraph, which is being reduced by a cfg transformation - DONE: support function pointers -- implement exceptions (Carl, Ludovic) +- implement exceptions + +- (DONE, bert, eric) try to integrate Boehm GC -- try to integrate Boehm GC +after 9am at Lauras place: +Niklaus, Adrien, Arre, Christian, Ludovic, (Samuele and Eric for a bit), +next sprint: in heidelberg end of august: very likely 22nd-29th August + (Carl will try to fix this until 15th July) +next sprint after that: supposedly in Paris, no dates yet From pedronis at codespeak.net Sun Jul 3 19:59:20 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 3 Jul 2005 19:59:20 +0200 (CEST) Subject: [pypy-svn] r14175 - pypy/dist/pypy/documentation Message-ID: <20050703175920.25D3427B49@code1.codespeak.net> Author: pedronis Date: Sun Jul 3 19:59:19 2005 New Revision: 14175 Added: pypy/dist/pypy/documentation/ext-functions-draft.txt (contents, props changed) Log: draft of text describing our current thinking on how to express and implement calls to external functions. Added: pypy/dist/pypy/documentation/ext-functions-draft.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/ext-functions-draft.txt Sun Jul 3 19:59:19 2005 @@ -0,0 +1,23 @@ +example of interp-level code needing to somehow call an external function: +:: + + def open(space, w_fname): + fname = space.str_w(fname) + fd = os.open(fname) + return space.wrap(fd) + +* os.open will be special-cased along all translation levels, there + will be a table mapping "sys calls" functions to the information + needed by the various level. + +* annotation/builtin.py will take information from the common table to + annotate the calls. + +* rtyper will replace the calls with for testing or dummy lowlevel + functions (ll_os_open for os.open), specified somehow trough the + table (issue: how to annotate these helper calls avoiding making + copies as in the usual case, so that the backends can recognize them) + +* the backends will have implementations for these helper functions + (to allow writing such implementations we will need a way to assign + fixed names for some of the defined lltypes introduced by the rtyper) From arigo at codespeak.net Sun Jul 3 20:11:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 20:11:11 +0200 (CEST) Subject: [pypy-svn] r14176 - pypy/dist/pypy/translator/goal Message-ID: <20050703181111.54F8927B50@code1.codespeak.net> Author: arigo Date: Sun Jul 3 20:11:10 2005 New Revision: 14176 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/goal/unixcheckpoint.py Log: Fixed unixcheckpoint to not stop on Ctrl-D, just like it doesn't stop on Ctrl-C. Disable recording on debugging info for translate_pypy, as they consume lots of memory for little usefulness. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sun Jul 3 20:11:10 2005 @@ -80,6 +80,7 @@ from pypy.translator.tool import buildpyxmodule buildpyxmodule.enable_fast_compilation() +annmodel.DEBUG = False Modified: pypy/dist/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- pypy/dist/pypy/translator/goal/unixcheckpoint.py (original) +++ pypy/dist/pypy/translator/goal/unixcheckpoint.py Sun Jul 3 20:11:10 2005 @@ -6,8 +6,8 @@ print '---> Checkpoint: run / quit / pdb ?' try: line = raw_input().strip().lower() - except KeyboardInterrupt: - print '(KeyboardInterrupt ignored)' + except (KeyboardInterrupt, EOFError), e: + print '(%s ignored)' % e.__class__.__name__ continue if line == 'run': break From hpk at codespeak.net Sun Jul 3 20:12:23 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 20:12:23 +0200 (CEST) Subject: [pypy-svn] r14177 - pypy/dist/pypy/documentation Message-ID: <20050703181223.20D5927B5C@code1.codespeak.net> Author: hpk Date: Sun Jul 3 20:12:19 2005 New Revision: 14177 Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt Log: small fixes Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt ============================================================================== --- pypy/dist/pypy/documentation/ext-functions-draft.txt (original) +++ pypy/dist/pypy/documentation/ext-functions-draft.txt Sun Jul 3 20:12:19 2005 @@ -1,6 +1,6 @@ example of interp-level code needing to somehow call an external function: :: - + import os def open(space, w_fname): fname = space.str_w(fname) fd = os.open(fname) @@ -8,10 +8,10 @@ * os.open will be special-cased along all translation levels, there will be a table mapping "sys calls" functions to the information - needed by the various level. + needed by the various levels. -* annotation/builtin.py will take information from the common table to - annotate the calls. +* annotation/builtin.py will take information from the common table + to annotate the calls. * rtyper will replace the calls with for testing or dummy lowlevel functions (ll_os_open for os.open), specified somehow trough the From hpk at codespeak.net Sun Jul 3 20:12:55 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 20:12:55 +0200 (CEST) Subject: [pypy-svn] r14178 - pypy/dist/pypy/documentation Message-ID: <20050703181255.0FA3927B5E@code1.codespeak.net> Author: hpk Date: Sun Jul 3 20:12:54 2005 New Revision: 14178 Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt Log: fix bad ReST Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt ============================================================================== --- pypy/dist/pypy/documentation/ext-functions-draft.txt (original) +++ pypy/dist/pypy/documentation/ext-functions-draft.txt Sun Jul 3 20:12:54 2005 @@ -1,5 +1,5 @@ -example of interp-level code needing to somehow call an external function: -:: +example of interp-level code needing to somehow call an external function:: + import os def open(space, w_fname): fname = space.str_w(fname) From arigo at codespeak.net Sun Jul 3 20:13:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 20:13:53 +0200 (CEST) Subject: [pypy-svn] r14180 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050703181353.3C6AC27B60@code1.codespeak.net> Author: arigo Date: Sun Jul 3 20:13:47 2005 New Revision: 14180 Modified: pypy/dist/pypy/interpreter/eval.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/objspace/std/fake.py Log: Add a default hidden_applevel to all Code objects, as the ExecutionContext assumes there is always one. Type-checking in CPythonFakeFrame to prevent the 'cpy_callable' attribute from being lifted to the base Code class by the annotator. Modified: pypy/dist/pypy/interpreter/eval.py ============================================================================== --- pypy/dist/pypy/interpreter/eval.py (original) +++ pypy/dist/pypy/interpreter/eval.py Sun Jul 3 20:13:47 2005 @@ -9,6 +9,7 @@ class Code(Wrappable): """A code is a compiled version of some source code. Abstract base class.""" + hidden_applevel = False def __init__(self, co_name): self.co_name = co_name Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Sun Jul 3 20:13:47 2005 @@ -332,6 +332,7 @@ class BuiltinCode(eval.Code): "The code object implementing a built-in (interpreter-level) hook." + hidden_applevel = True # When a BuiltinCode is stored in a Function object, # you get the functionality of CPython's built-in function type. Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Sun Jul 3 20:13:47 2005 @@ -142,13 +142,17 @@ self.unwrappedargs = self.space.unwrap(w_args) self.unwrappedkwds = self.space.unwrap(w_kwds) except UnwrapError, e: - raise UnwrapError('calling %s: %s' % (self.code.cpy_callable, e)) + code = self.code + assert isinstance(code, CPythonFakeCode) + raise UnwrapError('calling %s: %s' % (code.cpy_callable, e)) def getfastscope(self): raise OperationError(self.space.w_TypeError, self.space.wrap("cannot get fastscope of a CPythonFakeFrame")) def run(self): - fn = self.code.cpy_callable + code = self.code + assert isinstance(code, CPythonFakeCode) + fn = code.cpy_callable try: result = apply(fn, self.unwrappedargs, self.unwrappedkwds) except: From arigo at codespeak.net Sun Jul 3 20:14:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 20:14:25 +0200 (CEST) Subject: [pypy-svn] r14181 - in pypy/branch/pypy-translation-snapshot: interpreter objspace/std Message-ID: <20050703181425.7C09327B62@code1.codespeak.net> Author: arigo Date: Sun Jul 3 20:14:24 2005 New Revision: 14181 Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py pypy/branch/pypy-translation-snapshot/interpreter/gateway.py pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Log: Port rev 14180 from the trunk to the snapshot branch. Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/eval.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/eval.py Sun Jul 3 20:14:24 2005 @@ -9,6 +9,7 @@ class Code(Wrappable): """A code is a compiled version of some source code. Abstract base class.""" + hidden_applevel = False def __init__(self, co_name): self.co_name = co_name Modified: pypy/branch/pypy-translation-snapshot/interpreter/gateway.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/gateway.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/gateway.py Sun Jul 3 20:14:24 2005 @@ -332,6 +332,7 @@ class BuiltinCode(eval.Code): "The code object implementing a built-in (interpreter-level) hook." + hidden_applevel = True # When a BuiltinCode is stored in a Function object, # you get the functionality of CPython's built-in function type. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/fake.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/fake.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Sun Jul 3 20:14:24 2005 @@ -142,13 +142,17 @@ self.unwrappedargs = self.space.unwrap(w_args) self.unwrappedkwds = self.space.unwrap(w_kwds) except UnwrapError, e: - raise UnwrapError('calling %s: %s' % (self.code.cpy_callable, e)) + code = self.code + assert isinstance(code, CPythonFakeCode) + raise UnwrapError('calling %s: %s' % (code.cpy_callable, e)) def getfastscope(self): raise OperationError(self.space.w_TypeError, self.space.wrap("cannot get fastscope of a CPythonFakeFrame")) def run(self): - fn = self.code.cpy_callable + code = self.code + assert isinstance(code, CPythonFakeCode) + fn = code.cpy_callable try: result = apply(fn, self.unwrappedargs, self.unwrappedkwds) except: From hpk at codespeak.net Sun Jul 3 20:21:42 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 3 Jul 2005 20:21:42 +0200 (CEST) Subject: [pypy-svn] r14182 - pypy/extradoc/sprintinfo Message-ID: <20050703182142.BF9AF27B62@code1.codespeak.net> Author: hpk Date: Sun Jul 3 20:21:41 2005 New Revision: 14182 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: fix ReST Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sun Jul 3 20:21:41 2005 @@ -172,8 +172,8 @@ * (PROGRESS): translate to C (fix annotation problems by either tweaking the code or extending the annotator on a case-by-case basis). - - (DONE) Parser is fully annotable - - not translated and run in C, yet. + - (DONE) Parser is fully annotable + - not translated and run in C, yet. * (DONE) parser integrated in PyPy ("py.py --pyparse" for non-interactive usage), needs more testing. @@ -221,5 +221,5 @@ Niklaus, Adrien, Arre, Christian, Ludovic, (Samuele and Eric for a bit), next sprint: in heidelberg end of august: very likely 22nd-29th August - (Carl will try to fix this until 15th July) +(Carl will try to fix this until 15th July) next sprint after that: supposedly in Paris, no dates yet From tismer at codespeak.net Sun Jul 3 20:22:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 3 Jul 2005 20:22:56 +0200 (CEST) Subject: [pypy-svn] r14183 - pypy/dist/pypy/objspace/std Message-ID: <20050703182256.BE85E27B6A@code1.codespeak.net> Author: tismer Date: Sun Jul 3 20:22:55 2005 New Revision: 14183 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: basic unsigned long division works with full bit size. A problem that kept me busy for a while was an assertion that the carry ends up with -1 at the end of the operation. Had to convince myself that the impl is equivalent. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Sun Jul 3 20:22:55 2005 @@ -582,7 +582,7 @@ return z -#Substract the absolute values of two longs +# Substract the absolute values of two longs def _x_sub(a, b, space): size_a = len(a.digits) size_b = len(b.digits) @@ -648,7 +648,6 @@ z._normalize() return z - def _inplace_divrem1(pout, pin, n): """ Divide long pin by non-zero digit n, storing quotient @@ -677,3 +676,217 @@ rem = _inplace_divrem1(z, a, n) z._normalize() return z, rem + +def _muladd1(space, a, n, extra): + """Multiply by a single digit and add a single digit, ignoring the sign. + """ + digitpairs = len(a.digits) + size_a = digitpairs * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + z = W_LongObject(space, [r_uint(0)] * (digitpairs+1), 1) + carry = extra + for i in range(size_a): + carry += a._getshort(i) * n + z._setshort(i, carry & SHORT_MASK) + carry >>= SHORT_BIT + i += 1 + z._setshort(i, carry) + z._normalize() + return z + +# for the carry in _x_divrem, we need something that can hold +# two digits plus a sign. +# for the time being, we here implement such a 33 bit number just +# for the purpose of the division. +# In the long term, it might be considered to implement the +# notation of a "double anything" unsigned type, which could +# be used recursively to implement longs of any size. + +class r_suint(object): + # we do not inherit from r_uint, because we only + # support a few operations for our purpose + def __init__(self, value=0): + if isinstance(value, r_suint): + self.value = value.value + self.sign = value.sign + else: + self.value = r_uint(value) + self.sign = -(value < 0) + + def longval(self): + if self.sign: + return -long(-self.value) + else: + return long(self.value) + + def __repr__(self): + return repr(self.longval()) + + def __str__(self): + return str(self.longval()) + + def __iadd__(self, other): + hold = self.value + self.value += other + self.sign ^= - ( (other < 0) != (self.value < hold) ) + return self + + def __add__(self, other): + res = r_suint(self) + res += other + return res + + def __isub__(self, other): + hold = self.value + self.value -= other + self.sign ^= - ( (other < 0) != (self.value > hold) ) + return self + + def __sub__(self, other): + res = r_suint(self) + res -= other + return res + + def __irshift__(self, n): + self.value >>= n + if self.sign: + self.value += LONG_MASK << (LONG_BIT - n) + return self + + def __rshift__(self, n): + res = r_suint(self) + res >>= n + return res + + def __and__(self, mask): + # only used to get bits from the value + return self.value & mask + + def __eq__(self, other): + if not isinstance(other,r_suint): + other = r_suint(other) + return self.sign == other.sign and self.value == other.value + +def _x_divrem(space, v1, w1): # return as tuple, PyLongObject **prem) + size_w = len(w1.digits) * 2 + # hack for the moment: + # find where w1 is really nonzero + if w1._getshort(size_w-1) == 0: + size_w -= 1 + d = (SHORT_MASK+1) // (w1._getshort(size_w-1) + 1) + v = _muladd1(space, v1, d, r_uint(0)) + w = _muladd1(space, w1, d, r_uint(0)) + size_v = len(v.digits) * 2 + if v._getshort(size_v-1) == 0: + size_v -= 1 + size_w = len(w.digits) * 2 + if w._getshort(size_w-1) == 0: + size_w -= 1 + assert size_v >= size_w and size_w > 1 # Assert checks by div() + + size_a = size_v - size_w + 1 + digitpairs = (size_a + 1) // 2 + a = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + j = size_v + for k in range(size_a-1, -1, -1): + if j >= size_v: + vj = r_uint(0) + else: + vj = v._getshort(j) + carry = r_suint(0) # note: this must hold two digits and sign! + + if vj == w._getshort(size_w-1): + q = r_uint(SHORT_MASK) + else: + q = ((vj << SHORT_BIT) + v._getshort(j-1)) // w._getshort(size_w-1) + + while (w._getshort(size_w-2) * q > + (( + (vj << SHORT_BIT) + + v._getshort(j-1) + - q * w._getshort(size_w-1) + ) << SHORT_BIT) + + v._getshort(j-2)): + q -= 1 + + for i in range(size_w): + if i+k >= size_v: + break + z = w._getshort(i) * q + zz = z >> SHORT_BIT + carry += v._getshort(i+k) + (zz << SHORT_BIT) + carry -= z + v._setshort(i+k, r_uint(carry.value & SHORT_MASK)) + carry >>= SHORT_BIT + carry -= zz + + i += 1 # compare C code which re-uses i of loop + if i+k < size_v: + carry += v._getshort(i+k) + v._setshort(i+k, r_uint(0)) + + if carry == 0: + a._setshort(k, q) + else: + #assert carry == -1 + # the above would hold if we didn't minimize size_w + a._setshort(k, q-1) + carry = r_suint(0) + + for i in range(size_w): + if i+k >= size_v: + break + carry += v._getshort(i+k) + w._getshort(i) + v._setshort(i+k, r_uint(carry) & SHORT_MASK) + carry >>= SHORT_BIT + j -= 1 + + a._normalize() + rem, _ = _divrem1(space, v, d) + return a, rem + + +##def _divrem(a, b) +## size_a = len(a.digits) * 2 +## size_b = len(b.digits) * 2 +## PyLongObject *z; +## +## if (size_b == 0) { +## PyErr_SetString(PyExc_ZeroDivisionError, +## "long division or modulo by zero"); +## return -1; +## } +## if (size_a < size_b || +## (size_a == size_b && +## a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { +## /* |a| < |b|. */ +## *pdiv = _PyLong_New(0); +## Py_INCREF(a); +## *prem = (PyLongObject *) a; +## return 0; +## } +## if (size_b == 1) { +## digit rem = 0; +## z = divrem1(a, b->ob_digit[0], &rem); +## if (z == NULL) +## return -1; +## *prem = (PyLongObject *) PyLong_FromLong((long)rem); +## } +## else { +## z = x_divrem(a, b, prem); +## if (z == NULL) +## return -1; +## } +## /* Set the signs. +## The quotient z has the sign of a*b; +## the remainder r has the sign of a, +## so a = b*z + r. */ +## if ((a->ob_size < 0) != (b->ob_size < 0)) +## z->ob_size = -(z->ob_size); +## if (a->ob_size < 0 && (*prem)->ob_size != 0) +## (*prem)->ob_size = -((*prem)->ob_size); +## *pdiv = z; +## return 0; + +## XXXX From arigo at codespeak.net Sun Jul 3 20:36:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 20:36:09 +0200 (CEST) Subject: [pypy-svn] r14184 - in pypy/branch/dist-2.4.1: lib-python/modified-2.3.4 pypy/annotation pypy/bin pypy/documentation pypy/interpreter pypy/interpreter/astcompiler pypy/interpreter/pyparser pypy/interpreter/pyparser/data pypy/interpreter/pyparser/test pypy/interpreter/pyparser/test/samples pypy/interpreter/test pypy/lib pypy/module/recparser pypy/module/recparser/compiler pypy/module/recparser/data pypy/module/recparser/test pypy/objspace/std pypy/objspace/std/test pypy/rpython pypy/rpython/test pypy/tool pypy/translator pypy/translator/goal pypy/translator/llvm2 pypy/translator/llvm2/test pypy/translator/test pypy/translator/tool/pygame Message-ID: <20050703183609.13B7327B72@code1.codespeak.net> Author: arigo Date: Sun Jul 3 20:36:05 2005 New Revision: 14184 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/sre_constants.py - copied unchanged from r14183, pypy/dist/lib-python/modified-2.3.4/sre_constants.py pypy/branch/dist-2.4.1/pypy/documentation/ext-functions-draft.txt - copied unchanged from r14183, pypy/dist/pypy/documentation/ext-functions-draft.txt pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/ (props changed) - copied from r14183, pypy/dist/pypy/interpreter/astcompiler/ pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/__init__.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/__init__.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/ast.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/consts.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/consts.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/future.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/future.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/misc.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/misc.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/pyassem.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/pyassem.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/pycodegen.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/symbols.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/symbols.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/syntax.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/syntax.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/transformer.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/transformer.py pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/visitor.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/astcompiler/visitor.py pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ - copied from r14183, pypy/dist/pypy/interpreter/pyparser/ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/__init__.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/__init__.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/automata.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/automata.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/data/ - copied from r14183, pypy/dist/pypy/interpreter/pyparser/data/ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/data/Grammar2.3 - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/data/Grammar2.3 pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/data/Grammar2.4 - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/data/Grammar2.4 pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnflexer.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/ebnflexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnfparse.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/grammar.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/pytokenize.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/syntaxtree.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/syntaxtree.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/ (props changed) - copied from r14183, pypy/dist/pypy/interpreter/pyparser/test/ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/ (props changed) - copied from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_1.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_1.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_2.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_2.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_3.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_3.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_4.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_4.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_comment.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_comment.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration2.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration2.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration3.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration3.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_function_calls.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_function_calls.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_generator.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_generator.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_import_statements.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_import_statements.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_list_comps.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_list_comps.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_numbers.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_numbers.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_redirected_prints.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_redirected_prints.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_samples.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_samples.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_simple_assignment.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_simple_assignment.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_simple_class.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_simple_class.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_simple_for_loop.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_simple_for_loop.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_simple_in_expr.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_simple_in_expr.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_slice.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_slice.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_whitespaces.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_whitespaces.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_lookahead.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_pytokenizer.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/test_samples.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/unittest_samples.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/test/unittest_samples.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/tuplebuilder.py - copied unchanged from r14183, pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py pypy/branch/dist-2.4.1/pypy/lib/binascii.py - copied unchanged from r14183, pypy/dist/pypy/lib/binascii.py pypy/branch/dist-2.4.1/pypy/module/recparser/app_class.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/app_class.py pypy/branch/dist-2.4.1/pypy/module/recparser/astbuilder.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/astbuilder.py pypy/branch/dist-2.4.1/pypy/module/recparser/codegen.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/codegen.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/ - copied from r14183, pypy/dist/pypy/module/recparser/compiler/ pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/__init__.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/__init__.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/ast.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/ast.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/ast.txt - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/ast.txt pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/astfactory.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/astfactory.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/astgen.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/astgen.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/bytecode.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/bytecode.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/consts.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/consts.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/future.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/future.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/misc.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/misc.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/pyassem.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/pyassem.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/pycodegen.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/pycodegen.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/symbols.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/symbols.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/syntax.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/syntax.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/transformer.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/transformer.py pypy/branch/dist-2.4.1/pypy/module/recparser/compiler/visitor.py - copied unchanged from r14183, pypy/dist/pypy/module/recparser/compiler/visitor.py pypy/branch/dist-2.4.1/pypy/rpython/remptydict.py - copied unchanged from r14183, pypy/dist/pypy/rpython/remptydict.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_remptydict.py - copied unchanged from r14183, pypy/dist/pypy/rpython/test/test_remptydict.py pypy/branch/dist-2.4.1/pypy/translator/goal/targetparser.py - copied unchanged from r14183, pypy/dist/pypy/translator/goal/targetparser.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py - copied unchanged from r14183, pypy/dist/pypy/translator/llvm2/arraynode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/node.py - copied unchanged from r14183, pypy/dist/pypy/translator/llvm2/node.py pypy/branch/dist-2.4.1/pypy/translator/test/test_backendoptimization.py - copied unchanged from r14183, pypy/dist/pypy/translator/test/test_backendoptimization.py Removed: pypy/branch/dist-2.4.1/pypy/interpreter/compiler.py pypy/branch/dist-2.4.1/pypy/lib/inprogress_binascii.py pypy/branch/dist-2.4.1/pypy/module/recparser/data/ pypy/branch/dist-2.4.1/pypy/module/recparser/ebnflexer.py pypy/branch/dist-2.4.1/pypy/module/recparser/ebnfparse.py pypy/branch/dist-2.4.1/pypy/module/recparser/grammar.py pypy/branch/dist-2.4.1/pypy/module/recparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/module/recparser/pythonparse.py pypy/branch/dist-2.4.1/pypy/module/recparser/pythonutil.py pypy/branch/dist-2.4.1/pypy/module/recparser/syntaxtree.py pypy/branch/dist-2.4.1/pypy/module/recparser/test/ pypy/branch/dist-2.4.1/pypy/module/recparser/tuplebuilder.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/cfgtransform.py Modified: pypy/branch/dist-2.4.1/pypy/annotation/classdef.py pypy/branch/dist-2.4.1/pypy/annotation/unaryop.py pypy/branch/dist-2.4.1/pypy/bin/translator.py pypy/branch/dist-2.4.1/pypy/documentation/architecture.txt pypy/branch/dist-2.4.1/pypy/documentation/objspace.txt pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py pypy/branch/dist-2.4.1/pypy/interpreter/eval.py pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py pypy/branch/dist-2.4.1/pypy/interpreter/gateway.py pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py pypy/branch/dist-2.4.1/pypy/lib/_formatting.py pypy/branch/dist-2.4.1/pypy/module/recparser/__init__.py pypy/branch/dist-2.4.1/pypy/module/recparser/compat.py pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py pypy/branch/dist-2.4.1/pypy/objspace/std/fake.py pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py pypy/branch/dist-2.4.1/pypy/rpython/lltype.py pypy/branch/dist-2.4.1/pypy/rpython/rclass.py pypy/branch/dist-2.4.1/pypy/rpython/rconstantdict.py pypy/branch/dist-2.4.1/pypy/rpython/rdict.py pypy/branch/dist-2.4.1/pypy/rpython/rpbc.py pypy/branch/dist-2.4.1/pypy/rpython/rstr.py pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_lltype.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rclass.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rconstantdict.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rpbc.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py pypy/branch/dist-2.4.1/pypy/tool/option.py pypy/branch/dist-2.4.1/pypy/translator/backendoptimization.py pypy/branch/dist-2.4.1/pypy/translator/goal/translate_pypy.py pypy/branch/dist-2.4.1/pypy/translator/goal/unixcheckpoint.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py pypy/branch/dist-2.4.1/pypy/translator/tool/pygame/drawgraph.py Log: Merged the trunk into the dist-2.4.1 branch: svn merge -r14032:14183 http://codespeak.net/svn/pypy/dist Modified: pypy/branch/dist-2.4.1/pypy/annotation/classdef.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/annotation/classdef.py (original) +++ pypy/branch/dist-2.4.1/pypy/annotation/classdef.py Sun Jul 3 20:36:05 2005 @@ -315,7 +315,7 @@ return None return None - def matching(self, pbc, name): + def matching(self, pbc, name=None): d = {} uplookup = None upfunc = None @@ -341,7 +341,7 @@ # PBC dictionary to track more precisely with which 'self' the # method is called. d[upfunc] = self - elif meth: + elif meth and name is not None: self.check_missing_attribute_update(name) if d: return SomePBC(d) Modified: pypy/branch/dist-2.4.1/pypy/annotation/unaryop.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/annotation/unaryop.py (original) +++ pypy/branch/dist-2.4.1/pypy/annotation/unaryop.py Sun Jul 3 20:36:05 2005 @@ -301,6 +301,9 @@ def method_endswith(str, frag): return SomeBool() + def method_find(str, frag): + return SomeInteger() + def method_join(str, s_list): getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() @@ -324,6 +327,12 @@ def method_replace(str, s1, s2): return SomeString() + def method_lower(str): + return SomeString() + + def method_upper(str): + return SomeString() + class __extend__(SomeChar): Modified: pypy/branch/dist-2.4.1/pypy/bin/translator.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/bin/translator.py (original) +++ pypy/branch/dist-2.4.1/pypy/bin/translator.py Sun Jul 3 20:36:05 2005 @@ -226,8 +226,11 @@ import atexit atexit.register(readline.write_history_file, histfile) - if __name__ == '__main__': + try: + setup_readline() + except ImportError, err: + print "Disabling readline support (%s)" % err from pypy.translator.test import snippet as test from pypy.translator.llvm.test import llvmsnippet as test2 from pypy.rpython.rtyper import RPythonTyper Modified: pypy/branch/dist-2.4.1/pypy/documentation/architecture.txt ============================================================================== --- pypy/branch/dist-2.4.1/pypy/documentation/architecture.txt (original) +++ pypy/branch/dist-2.4.1/pypy/documentation/architecture.txt Sun Jul 3 20:36:05 2005 @@ -105,7 +105,7 @@ Please note that we are using the term *interpreter* most often in reference to the *plain interpreter* which just knows enough to read, dispatch and implement *bytecodes* thus shuffling objects around on the -stack and between namespaces. The (plain) interpreter is completly +stack and between namespaces. The (plain) interpreter is completely ignorant of how to access, modify or construct objects and their structure and thus delegates such operations to a so called `Object Space`_. Modified: pypy/branch/dist-2.4.1/pypy/documentation/objspace.txt ============================================================================== --- pypy/branch/dist-2.4.1/pypy/documentation/objspace.txt (original) +++ pypy/branch/dist-2.4.1/pypy/documentation/objspace.txt Sun Jul 3 20:36:05 2005 @@ -354,7 +354,7 @@ :args: list of arguments. Each one is a Constant or a Variable seen previously in the basic block. :result: a *new* Variable into which the result is to be stored. - Note that operations usually cannot implicitely raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. + Note that operations usually cannot implicitly raise exceptions at run-time; so for example, code generators can assume that a ``getitem`` operation on a list is safe and can be performed without bound checking. The exceptions to this rule are: (1) if the operation is the last in the block, which ends with ``exitswitch == Constant(last_exception)``, then the implicit exceptions must be checked for, generated, and caught appropriately; (2) calls to other functions, as per ``simple_call`` or ``call_args``, can always raise whatever the called function can raise --- and such exceptions must be passed through to the parent unless they are caught as above. Variable Modified: pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py Sun Jul 3 20:36:05 2005 @@ -1,9 +1,12 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments +from pypy.interpreter.pycompiler import CPythonCompiler +from pypy.interpreter.pycompiler import PythonCompiler, PyPyCompiler from pypy.interpreter.miscutils import ThreadLocals from pypy.tool.cache import Cache from pypy.rpython.rarithmetic import r_uint +import pypy.tool.option __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'BaseWrappable', 'W_Root'] @@ -92,12 +95,17 @@ full_exceptions = True # full support for exceptions (normalization & more) - def __init__(self): + def __init__(self, options=None): "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() # set recursion limit # sets all the internal descriptors + + # XXX: Options in option.py is replaced by a function so + # it's not really clean to do a from option import Options + # since changing import order can change the Options object + self.options = options or pypy.tool.option.Options() self.initialize() def __repr__(self): @@ -134,9 +142,11 @@ #self.setbuiltinmodule('_codecs') # XXX we need to resolve unwrapping issues to # make this the default _sre module - #self.setbuiltinmodule("_sre", "_sre_pypy") - - # XXX disabled: self.setbuiltinmodule('parser') + #self.setbuiltinmodule("_sre", "_sre_pypy") + if self.options.useparsermodule == "recparser": + self.setbuiltinmodule('parser', 'recparser') + elif self.options.useparsermodule == "parser": + self.setbuiltinmodule('parser') # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): @@ -173,6 +183,20 @@ "Factory function for execution contexts." return ExecutionContext(self) + def createcompiler(self): + "Factory function creating a compiler object." + if self.options.parser == 'recparser': + if self.options.compiler == 'cpython': + return PythonCompiler(self) + else: + return PyPyCompiler(self) + elif self.options.compiler == 'pyparse': + # <=> options.parser == 'cpython' + return PythonCompiler(self) + else: + # <=> options.compiler == 'cpython' and options.parser == 'cpython' + return CPythonCompiler(self) + # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses # may also override specific functions for performance. Deleted: /pypy/branch/dist-2.4.1/pypy/interpreter/compiler.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/interpreter/compiler.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,165 +0,0 @@ -""" -General classes for bytecode compilers. -Compiler instances are stored into 'space.getexecutioncontext().compiler'. -""" -from codeop import PyCF_DONT_IMPLY_DEDENT -from pypy.interpreter.error import OperationError - - -class Compiler: - """Abstract base class for a bytecode compiler.""" - - # The idea is to grow more methods here over the time, - # e.g. to handle .pyc files in various ways if we have multiple compilers. - - def __init__(self, space): - self.space = space - - def compile(self, source, filename, mode, flags): - """Compile and return an pypy.interpreter.eval.Code instance.""" - raise NotImplementedError - - def getcodeflags(self, code): - """Return the __future__ compiler flags that were used to compile - the given code object.""" - return 0 - - def compile_command(self, source, filename, mode, flags): - """Same as compile(), but tries to compile a possibly partial - interactive input. If more input is needed, it returns None. - """ - # Hackish default implementation based on the stdlib 'codeop' module. - # See comments over there. - space = self.space - flags |= PyCF_DONT_IMPLY_DEDENT - # Check for source consisting of only blank lines and comments - if mode != "eval": - in_comment = False - for c in source: - if c in ' \t\f\v': # spaces - pass - elif c == '#': - in_comment = True - elif c in '\n\r': - in_comment = False - elif not in_comment: - break # non-whitespace, non-comment character - else: - source = "pass" # Replace it with a 'pass' statement - - try: - code = self.compile(source, filename, mode, flags) - return code # success - except OperationError, err: - if not err.match(space, space.w_SyntaxError): - raise - - try: - self.compile(source + "\n", filename, mode, flags) - return None # expect more - except OperationError, err1: - if not err1.match(space, space.w_SyntaxError): - raise - - try: - self.compile(source + "\n\n", filename, mode, flags) - raise # uh? no error with \n\n. re-raise the previous error - except OperationError, err2: - if not err2.match(space, space.w_SyntaxError): - raise - - if space.eq_w(err1.w_value, err2.w_value): - raise # twice the same error, re-raise - - return None # two different errors, expect more - - -# ____________________________________________________________ -# faked compiler - -import warnings -import __future__ -compiler_flags = 0 -for fname in __future__.all_feature_names: - compiler_flags |= getattr(__future__, fname).compiler_flag - - -class CPythonCompiler(Compiler): - """Faked implementation of a compiler, using the underlying compile().""" - - def compile(self, source, filename, mode, flags): - flags |= __future__.generators.compiler_flag # always on (2.2 compat) - space = self.space - try: - old = self.setup_warn_explicit(warnings) - try: - c = compile(source, filename, mode, flags, True) - finally: - self.restore_warn_explicit(warnings, old) - # It would be nice to propagate all exceptions to app level, - # but here we only propagate the 'usual' ones, until we figure - # out how to do it generically. - except SyntaxError,e: - w_synerr = space.newtuple([space.wrap(e.msg), - space.newtuple([space.wrap(e.filename), - space.wrap(e.lineno), - space.wrap(e.offset), - space.wrap(e.text)])]) - raise OperationError(space.w_SyntaxError, w_synerr) - except ValueError,e: - raise OperationError(space.w_ValueError,space.wrap(str(e))) - except TypeError,e: - raise OperationError(space.w_TypeError,space.wrap(str(e))) - from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) - compile._annspecialcase_ = "override:cpy_compile" - - def getcodeflags(self, code): - from pypy.interpreter.pycode import PyCode - if isinstance(code, PyCode): - return code.co_flags & compiler_flags - else: - return 0 - - def _warn_explicit(self, message, category, filename, lineno, - module=None, registry=None): - if hasattr(category, '__bases__') and \ - issubclass(category, SyntaxWarning): - assert isinstance(message, str) - space = self.space - w_mod = space.sys.getmodule('warnings') - if w_mod is not None: - w_dict = w_mod.getdict() - w_reg = space.call_method(w_dict, 'setdefault', - space.wrap("__warningregistry__"), - space.newdict([])) - try: - space.call_method(w_mod, 'warn_explicit', - space.wrap(message), - space.w_SyntaxWarning, - space.wrap(filename), - space.wrap(lineno), - space.w_None, - space.w_None) - except OperationError, e: - if e.match(space, space.w_SyntaxWarning): - raise OperationError( - space.w_SyntaxError, - space.wrap(message)) - raise - - def setup_warn_explicit(self, warnings): - """ - this is a hack until we have our own parsing/compiling - in place: we bridge certain warnings to the applevel - warnings module to let it decide what to do with - a syntax warning ... - """ - # there is a hack to make the flow space happy: - # 'warnings' should not look like a Constant - old_warn_explicit = warnings.warn_explicit - warnings.warn_explicit = self._warn_explicit - return old_warn_explicit - - def restore_warn_explicit(self, warnings, old_warn_explicit): - warnings.warn_explicit = old_warn_explicit Modified: pypy/branch/dist-2.4.1/pypy/interpreter/eval.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/eval.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/eval.py Sun Jul 3 20:36:05 2005 @@ -9,6 +9,7 @@ class Code(Wrappable): """A code is a compiled version of some source code. Abstract base class.""" + hidden_applevel = False def __init__(self, co_name): self.co_name = co_name Modified: pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/executioncontext.py Sun Jul 3 20:36:05 2005 @@ -1,7 +1,6 @@ import sys from pypy.interpreter.miscutils import Stack from pypy.interpreter.error import OperationError -from pypy.interpreter.compiler import CPythonCompiler class ExecutionContext: """An ExecutionContext holds the state of an execution thread @@ -13,7 +12,7 @@ self.w_tracefunc = None self.w_profilefunc = None self.is_tracing = 0 - self.compiler = CPythonCompiler(space) + self.compiler = space.createcompiler() def enter(self, frame): if self.framestack.depth() > self.space.sys.recursionlimit: Modified: pypy/branch/dist-2.4.1/pypy/interpreter/gateway.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/gateway.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/gateway.py Sun Jul 3 20:36:05 2005 @@ -332,6 +332,7 @@ class BuiltinCode(eval.Code): "The code object implementing a built-in (interpreter-level) hook." + hidden_applevel = True # When a BuiltinCode is stored in a Function object, # you get the functionality of CPython's built-in function type. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py Sun Jul 3 20:36:05 2005 @@ -53,7 +53,7 @@ oparg = self.nextarg() fn(self, oparg) else: - fn = self.dispatch_table_no_arg[opcode] + fn = self.dispatch_table_no_arg[opcode] fn(self) def nextop(self): Modified: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py Sun Jul 3 20:36:05 2005 @@ -1,13 +1,13 @@ import __future__ import autopath import py -from pypy.interpreter.compiler import CPythonCompiler, Compiler +from pypy.interpreter.pycompiler import CPythonCompiler, PythonCompiler from pypy.interpreter.pycode import PyCode -class TestCompiler: +class BaseTestCompiler: def setup_method(self, method): - self.compiler = CPythonCompiler(self.space) + self.compiler = self.space.createcompiler() def test_compile(self): code = self.compiler.compile('6*7', '', 'eval', 0) @@ -37,6 +37,7 @@ 'if 1:\n x x', '?', 'exec', 0) def test_getcodeflags(self): + py.test.skip("flags don't work correctly when using the compiler package") code = self.compiler.compile('from __future__ import division\n', '', 'exec', 0) flags = self.compiler.getcodeflags(code) @@ -48,6 +49,18 @@ assert flags == flags2 -class TestECCompiler(TestCompiler): +class TestECCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = self.space.getexecutioncontext().compiler + +class TestPyCCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = CPythonCompiler(self.space) + +class TestPurePythonCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = PythonCompiler(self.space) + +class SkippedForNowTestPyPyCompiler(BaseTestCompiler): + def setup_method(self, method): + self.compiler = PyPyCompiler(self.space) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/typedef.py Sun Jul 3 20:36:05 2005 @@ -39,6 +39,7 @@ return get_unique_interplevel_NoDictWithSlots(cls) else: return get_unique_interplevel_NoDictNoSlots(cls) +get_unique_interplevel_subclass._annspecialcase_ = "specialize:arg0" for hasdict in False, True: for wants_slots in False, True: Modified: pypy/branch/dist-2.4.1/pypy/lib/_formatting.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/_formatting.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/_formatting.py Sun Jul 3 20:36:05 2005 @@ -453,9 +453,12 @@ try: f = format_registry[t[0]] except KeyError: + char = t[0] + if isinstance(char, unicode): + char = char.encode(sys.getdefaultencoding(), 'replace') raise ValueError("unsupported format character " "'%s' (0x%x) at index %d" - %(t[0], ord(t[0]), fmtiter.i-1)) + % (char, ord(t[0]), fmtiter.i - 1)) # Trying to translate this using the flow space. # Currently, star args give a problem there, # so let's be explicit about the args: @@ -467,12 +470,7 @@ # Switch to using the unicode formatters and retry. do_unicode = True format_registry = unicode_format_registry - try: - f = format_registry[t[0]] - except KeyError: - raise ValueError("unsupported format character " - "'%s' (0x%x) at index %d" - %(t[0], ord(t[0]), fmtiter.i-1)) + f = format_registry[t[0]] r.append(f(char, flags, width, prec, value).format()) else: Deleted: /pypy/branch/dist-2.4.1/pypy/lib/inprogress_binascii.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/lib/inprogress_binascii.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,299 +0,0 @@ -class Error(Exception): - pass - -class Incomplete(Exception): - pass - -def a2b_uu(s): - length = (ord(s[0]) - 0x20) % 64 - a = quadruplets(s[1:].rstrip()) - try: - result = [''.join( - [chr((A - 0x20) << 2 | (((B - 0x20) >> 4) & 0x3)), - chr(((B - 0x20) & 0xF) << 4 | (((C - 0x20) >> 2) & 0xF)), - chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3F)) - ]) for A, B, C, D in a] - except ValueError: - raise Error, 'Illegal char' - result = ''.join(result) - trailingdata = result[length:] - if trailingdata.strip('\x00'): - raise Error, 'Trailing garbage' - result = result[:length] - if len(result) < length: - result += ((length - len(result)) * '\x00') - return result - -def quadruplets(s): - while s: - try: - a, b, c, d = s[0], s[1], s[2], s[3] - except IndexError: - s += ' ' - yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) - return - s = s[4:] - yield ord(a), ord(b), ord(c), ord(d) - -def b2a_uu(s): - length = len(s) - if length > 45: - raise Error, 'At most 45 bytes at once' - - a = triples(s) - result = [''.join( - [chr(0x20 + (( A >> 2 ) & 0x3F)), - chr(0x20 + (((A << 4) | ((B >> 4) & 0xF)) & 0x3F)), - chr(0x20 + (((B << 2) | ((C >> 6) & 0x3)) & 0x3F)), - chr(0x20 + (( C ) & 0x3F))]) for A, B, C in a] - return chr(ord(' ') + (length & 077)) + ''.join(result) + '\n' - -def triples(s): - while s: - try: - a, b, c = s[0], s[1], s[2] - except IndexError: - s += '\0\0' - yield ord(s[0]), ord(s[1]), ord(s[2]) - return - s = s[3:] - yield ord(a), ord(b), ord(c) - - -table_a2b_base64 = { - 'A': 0, - 'B': 1, - 'C': 2, - 'D': 3, - 'E': 4, - 'F': 5, - 'G': 6, - 'H': 7, - 'I': 8, - 'J': 9, - 'K': 10, - 'L': 11, - 'M': 12, - 'N': 13, - 'O': 14, - 'P': 15, - 'Q': 16, - 'R': 17, - 'S': 18, - 'T': 19, - 'U': 20, - 'V': 21, - 'W': 22, - 'X': 23, - 'Y': 24, - 'Z': 25, - 'a': 26, - 'b': 27, - 'c': 28, - 'd': 29, - 'e': 30, - 'f': 31, - 'g': 32, - 'h': 33, - 'i': 34, - 'j': 35, - 'k': 36, - 'l': 37, - 'm': 38, - 'n': 39, - 'o': 40, - 'p': 41, - 'q': 42, - 'r': 43, - 's': 44, - 't': 45, - 'u': 46, - 'v': 47, - 'w': 48, - 'x': 49, - 'y': 50, - 'z': 51, - '0': 52, - '1': 53, - '2': 54, - '3': 55, - '4': 56, - '5': 57, - '6': 58, - '7': 59, - '8': 60, - '9': 61, - '+': 62, - '/': 63, -} - -def quadruplets_base64(s): - while s: - a, b, c, d = table_a2b_base64[s[0]], table_a2b_base64[s[1]], table_a2b_base64[s[2]], table_a2b_base64[s[3]] - s = s[4:] - yield a, b, c, d - -def a2b_base64(s): - s = s.rstrip() - # clean out all invalid characters, this also strips the final '=' padding - clean_s = [] - for item in s: - if item in table_a2b_base64: - clean_s.append(item) - s = ''.join(clean_s) - # Add '=' padding back into the string - if len(s) % 4: - s = s + ('=' * (4 - len(s) % 4)) - - a = quadruplets_base64(s[:-4]) - result = [ - chr(A << 2 | ((B >> 4) & 0x3)) + - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + - chr((C & 0x3) << 6 | D ) - for A, B, C, D in a] - - if s: - final = s[-4:] - if final[2] == '=': - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) - elif final[3] == '=': - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - C = table_a2b_base64[final[2]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) - else: - A = table_a2b_base64[final[0]] - B = table_a2b_base64[final[1]] - C = table_a2b_base64[final[2]] - D = table_a2b_base64[final[3]] - snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + \ - chr((C & 0x3) << 6 | D ) - result.append(snippet) - - return ''.join(result) - -table_b2a_base64 = \ -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - -def b2a_base64(s): - length = len(s) - final_length = length % 3 - - a = triples(s[ :length - final_length]) - - result = [''.join( - [table_b2a_base64[( A >> 2 ) & 0x3F], - table_b2a_base64[((A << 4) | ((B >> 4) & 0xF)) & 0x3F], - table_b2a_base64[((B << 2) | ((C >> 6) & 0x3)) & 0x3F], - table_b2a_base64[( C ) & 0x3F]]) - for A, B, C in a] - - final = s[length - final_length:] - if final_length == 0: - snippet = '' - elif final_length == 1: - a = ord(final[0]) - snippet = table_b2a_base64[(a >> 2 ) & 0x3F] + \ - table_b2a_base64[(a << 4 ) & 0x3F] + '==' - else: - a = ord(final[0]) - b = ord(final[1]) - snippet = table_b2a_base64[(a >> 2) & 0x3F] + \ - table_b2a_base64[((a << 4) | (b >> 4) & 0xF) & 0x3F] + \ - table_b2a_base64[(b << 2) & 0x3F] + '=' - return ''.join(result) + snippet + '\n' - -def a2b_qp(s): - parts = s.rstrip().split('=') - - # Change the parts in-place - for index, part in enumerate(parts[1:]): - if len(part) > 1 and part[0] in hex_numbers and part[1] in hex_numbers: - parts[index + 1] = chr(strhex_to_int(part[0:2])) + part[2:] - elif index == len(parts) - 2 and len(part) < 2: - parts[index + 1] = '' - else: - parts[index + 1] = '=' + parts[index + 1] - - return ''.join(parts) - -def b2a_qp(s): - """ In this implementation, we are quoting all spaces and tab character. - This is ok by the standard, though it slightly reduces the - readability of the quoted string. The CPython implementation - preserves internal whitespace, which is a different way of - implementing the standard. The reason we are doing things differently - is that it greatly simplifies the code. - - The CPython implementation does not escape CR and LF characters - and does not encode newlines as CRLF sequences. This seems to be - non-standard, and we copy this behaviour. - """ - crlf = s.find('\r\n') - lf = s.find('\n') - linebreak = None - if crlf >= 0 and crlf <= lf: - linebreak = '\r\n' - elif lf > 0: - linebreak = '\n' - - if linebreak: - s = s.replace('\r\n', '\n') - - lines = s.split('\n') - - result = [] - for line in lines: - charlist = [] - count = 0 - for c in line: - if '!' <= c <= '<' or '>' <= c <= '~' or c in '\n\r': - if count >= 75: - charlist.append('=\r\n') - count = 0 - charlist.append(c) - count += 1 - else: - if count >= 72: - charlist.append('=\r\n') - count = 0 - snippet = '=' + two_hex_digits(ord(c)) - count += len(snippet) - charlist.append(snippet) - result.append(''.join(charlist)) - return linebreak.join(result) - -hex_numbers = '0123456789ABCDEF' -def hex(n): - if n == 0: - return '0' - - if n < 0: - n = -n - sign = '-' - else: - sign = '' - arr = [] - for nibble in hexgen(n): - arr = [hex_numbers[nibble]] + arr - return sign + ''.join(arr) - -def two_hex_digits(n): - return hex_numbers[n / 0x10] + hex_numbers[n % 0x10] - -def hexgen(n): - """ Yield a nibble at a time. """ - while n: - remainder = n % 0x10 - n = n / 0x10 - yield remainder - -def strhex_to_int(s): - i = 0 - for c in s: - i = i * 0x10 + hex_numbers.index(c) - return i Modified: pypy/branch/dist-2.4.1/pypy/module/recparser/__init__.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/recparser/__init__.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/recparser/__init__.py Sun Jul 3 20:36:05 2005 @@ -1,44 +1,44 @@ from pypy.interpreter.error import OperationError, debug_print -from pypy.interpreter import module -from pypy.interpreter.mixedmodule import MixedModule - +import pypy.interpreter.pyparser.pythonparse -import pythonutil +from pypy.interpreter.mixedmodule import MixedModule -debug_print( "Loading grammar %s" % pythonutil.PYTHON_GRAMMAR ) -PYTHON_PARSER = pythonutil.python_grammar() +# Forward imports so they run at startup time +import pyparser +import pypy.interpreter.pyparser.pythonlexer +import pypy.interpreter.pyparser.pythonparse class Module(MixedModule): - """The builtin parser module. - """ + """The builtin parser module. + """ - appleveldefs = { - # 'ParserError' : 'app_class.ParserError', - } - interpleveldefs = { - '__name__' : '(space.wrap("parser"))', - '__doc__' : '(space.wrap("parser (recparser version) module"))', - - 'suite' : 'pyparser.suite', - 'expr' : 'pyparser.expr', - 'STType' : 'pyparser.STType', - 'ast2tuple' : 'pyparser.ast2tuple', -# 'ASTType' : 'pyparser.STType', - # 'sequence2st' : 'pyparser.sequence2st', - #'eval_input' : 'pyparser.eval_input', - #'file_input' : 'pyparser.file_input', - #'compileast' : 'pyparser.compileast', - #'st2tuple' : 'pyparser.st2tuple', - #'st2list' : 'pyparser.st2list', - #'issuite' : 'pyparser.issuite', - #'ast2tuple' : 'pyparser.ast2tuple', - #'tuple2st' : 'pyparser.tuple2st', - #'isexpr' : 'pyparser.isexpr', - #'ast2list' : 'pyparser.ast2list', - #'sequence2ast' : 'pyparser.sequence2ast', - #'tuple2ast' : 'pyparser.tuple2ast', - #'_pickler' : 'pyparser._pickler', - #'compilest' : 'pyparser.compilest', - } + appleveldefs = { + 'ParserError' : 'app_class.ParserError', + } + interpleveldefs = { + '__name__' : '(space.wrap("parser"))', + '__doc__' : '(space.wrap("parser (recparser version) module"))', + + 'suite' : 'pyparser.suite', + 'expr' : 'pyparser.expr', + 'STType' : 'pyparser.STType', + 'ast2tuple' : 'pyparser.ast2tuple', +## # 'ASTType' : 'pyparser.STType', +## # 'sequence2st' : 'pyparser.sequence2st', +## #'eval_input' : 'pyparser.eval_input', +## #'file_input' : 'pyparser.file_input', +## #'compileast' : 'pyparser.compileast', +## #'st2tuple' : 'pyparser.st2tuple', +## #'st2list' : 'pyparser.st2list', +## #'issuite' : 'pyparser.issuite', +## #'ast2tuple' : 'pyparser.ast2tuple', +## #'tuple2st' : 'pyparser.tuple2st', +## #'isexpr' : 'pyparser.isexpr', +## #'ast2list' : 'pyparser.ast2list', +## #'sequence2ast' : 'pyparser.sequence2ast', +## #'tuple2ast' : 'pyparser.tuple2ast', +## #'_pickler' : 'pyparser._pickler', +## #'compilest' : 'pyparser.compilest', + } Modified: pypy/branch/dist-2.4.1/pypy/module/recparser/compat.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/recparser/compat.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/recparser/compat.py Sun Jul 3 20:36:05 2005 @@ -1,16 +1,28 @@ """Compatibility layer for CPython's parser module""" from pythonparse import parse_python_source -from pypy.module.recparser import PYTHON_PARSER +from pythonutil import PYTHON_PARSER from compiler import transformer, compile as pycompile - + def suite( source ): - builder = parse_python_source( source, PYTHON_PARSER, "file_input" ) - return builder.stack[-1] + strings = [line+'\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) + nested_tuples = builder.stack[-1].as_tuple() + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + return nested_tuples def expr( source ): - builder = parse_python_source( source, PYTHON_PARSER, "eval_input" ) - return builder.stack[-1] + strings = [line+'\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) + nested_tuples = builder.stack[-1].as_tuple() + if builder.source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, builder.source_encoding) + else: + return (None, nested_tuples, None) + return nested_tuples def ast2tuple(node, line_info=False): """Quick dummy implementation of parser.ast2tuple(tree) function""" Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/ebnflexer.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/ebnflexer.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,71 +0,0 @@ -"""This is a lexer for a Python recursive descent parser -it obeys the TokenSource interface defined for the grammar -analyser in grammar.py -""" - -import re -from grammar import TokenSource - -DEBUG = False - -## Lexer for Python's grammar ######################################## -g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:",re.M) -g_symbol = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*",re.M) -g_string = re.compile(r"'[^']+'",re.M) -g_tok = re.compile(r"\[|\]|\(|\)|\*|\+|\|",re.M) -g_skip = re.compile(r"\s*(#.*$)?",re.M) - -class GrammarSource(TokenSource): - """The grammar tokenizer""" - def __init__(self, inpstring ): - TokenSource.__init__(self) - self.input = inpstring - self.pos = 0 - - def context(self): - return self.pos - - def offset(self, ctx=None): - if ctx is None: - return self.pos - else: - assert type(ctx)==int - return ctx - - def restore(self, ctx ): - self.pos = ctx - - def next(self): - pos = self.pos - inp = self.input - m = g_skip.match(inp, pos) - while m and pos!=m.end(): - pos = m.end() - if pos==len(inp): - self.pos = pos - return None, None - m = g_skip.match(inp, pos) - m = g_symdef.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return 'SYMDEF',tk[:-1] - m = g_tok.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return tk,tk - m = g_string.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return 'STRING',tk[1:-1] - m = g_symbol.match(inp,pos) - if m: - tk = m.group(0) - self.pos = m.end() - return 'SYMBOL',tk - raise ValueError("Unknown token at pos=%d context='%s'" % (pos,inp[pos:pos+20]) ) - - def debug(self): - return self.input[self.pos:self.pos+20] Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/ebnfparse.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/ebnfparse.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,253 +0,0 @@ -#!/usr/bin/env python -from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ - KleenStar, GrammarElement -from ebnflexer import GrammarSource - -import re -py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) - -punct=['>=', '<>', '!=', '<', '>', '<=', '==', '\\*=', - '//=', '%=', '^=', '<<=', '\\*\\*=', '\\', '=', - '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', '@', '\\[', '\\]', '`', '\\{', '\\}'] - -py_punct = re.compile(r""" ->=|<>|!=|<|>|<=|==|~| -\*=|//=|%=|\^=|<<=|\*\*=|\|=|\+=|>>=|=|&=|/=|-=| -,|\^|>>|&|\+|\*|-|/|\.|\*\*|%|<<|//|\|| -\)|\(|;|:|@|\[|\]|`|\{|\} -""", re.M | re.X) - - -TERMINALS = [ - 'NAME', 'NUMBER', 'STRING', 'NEWLINE', 'ENDMARKER', - 'INDENT', 'DEDENT' ] - - -## Grammar Visitors ################################################## -# FIXME: parsertools.py ? parser/__init__.py ? - -class NameToken(Token): - """A token that is not a keyword""" - def __init__(self, keywords=None ): - Token.__init__(self, "NAME") - self.keywords = keywords - - def match(self, source, builder): - """Matches a token. - the default implementation is to match any token whose type - corresponds to the object's name. You can extend Token - to match anything returned from the lexer. for exemple - type, value = source.next() - if type=="integer" and int(value)>=0: - # found - else: - # error unknown or negative integer - """ - ctx = source.context() - tk_type, tk_value = source.next() - if tk_type==self.name: - if tk_value not in self.keywords: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type, tk_value ) - source.restore( ctx ) - return None - - -class EBNFVisitor(object): - def __init__(self): - self.rules = {} - self.terminals = {} - self.current_rule = None - self.current_subrule = 0 - self.tokens = {} - self.items = [] - self.terminals['NAME'] = NameToken() - - def new_name( self ): - rule_name = ":%s_%s" % (self.current_rule, self.current_subrule) - self.current_subrule += 1 - return rule_name - - def new_item( self, itm ): - self.items.append( itm ) - return itm - - def visit_grammar( self, node ): - # print "Grammar:" - for rule in node.nodes: - rule.visit(self) - # the rules are registered already - # we do a pass through the variables to detect - # terminal symbols from non terminals - for r in self.items: - for i,a in enumerate(r.args): - if a.name in self.rules: - assert isinstance(a,Token) - r.args[i] = self.rules[a.name] - if a.name in self.terminals: - del self.terminals[a.name] - # XXX .keywords also contains punctuations - self.terminals['NAME'].keywords = self.tokens.keys() - - def visit_rule( self, node ): - symdef = node.nodes[0].value - self.current_rule = symdef - self.current_subrule = 0 - alt = node.nodes[1] - rule = alt.visit(self) - if not isinstance( rule, Token ): - rule.name = symdef - self.rules[symdef] = rule - - def visit_alternative( self, node ): - items = [ node.nodes[0].visit(self) ] - items+= node.nodes[1].visit(self) - if len(items)==1 and items[0].name.startswith(':'): - return items[0] - alt = Alternative( self.new_name(), *items ) - return self.new_item( alt ) - - def visit_sequence( self, node ): - """ """ - items = [] - for n in node.nodes: - items.append( n.visit(self) ) - if len(items)==1: - return items[0] - elif len(items)>1: - return self.new_item( Sequence( self.new_name(), *items) ) - raise SyntaxError("Found empty sequence") - - def visit_sequence_cont( self, node ): - """Returns a list of sequences (possibly empty)""" - return [n.visit(self) for n in node.nodes] -## L = [] -## for n in node.nodes: -## L.append( n.visit(self) ) -## return L - - def visit_seq_cont_list(self, node): - return node.nodes[1].visit(self) - - - def visit_symbol(self, node): - star_opt = node.nodes[1] - sym = node.nodes[0].value - terminal = self.terminals.get( sym ) - if not terminal: - terminal = Token( sym ) - self.terminals[sym] = terminal - - return self.repeat( star_opt, terminal ) - - def visit_option( self, node ): - rule = node.nodes[1].visit(self) - return self.new_item( KleenStar( self.new_name(), 0, 1, rule ) ) - - def visit_group( self, node ): - rule = node.nodes[1].visit(self) - return self.repeat( node.nodes[3], rule ) - - def visit_STRING( self, node ): - value = node.value - tok = self.tokens.get(value) - if not tok: - if py_punct.match( value ): - tok = Token( value ) - elif py_name.match( value ): - tok = Token('NAME', value) - else: - raise SyntaxError("Unknown STRING value ('%s')" % value ) - self.tokens[value] = tok - return tok - - def visit_sequence_alt( self, node ): - res = node.nodes[0].visit(self) - assert isinstance( res, GrammarElement ) - return res - - def repeat( self, star_opt, myrule ): - if star_opt.nodes: - rule_name = self.new_name() - tok = star_opt.nodes[0].nodes[0] - if tok.value == '+': - return self.new_item( KleenStar( rule_name, _min=1, rule = myrule ) ) - elif tok.value == '*': - return self.new_item( KleenStar( rule_name, _min=0, rule = myrule ) ) - else: - raise SyntaxError("Got symbol star_opt with value='%s'" % tok.value ) - return myrule - - -def grammar_grammar(): - """Builds the grammar for the grammar file - - Here's the description of the grammar's grammar :: - - grammar: rule+ - rule: SYMDEF alternative - - alternative: sequence ( '|' sequence )+ - star: '*' | '+' - sequence: (SYMBOL star? | STRING | option | group star? )+ - option: '[' alternative ']' - group: '(' alternative ')' star? - """ - # star: '*' | '+' - star = Alternative( "star", Token('*'), Token('+') ) - star_opt = KleenStar ( "star_opt", 0, 1, rule=star ) - - # rule: SYMBOL ':' alternative - symbol = Sequence( "symbol", Token('SYMBOL'), star_opt ) - symboldef = Token( "SYMDEF" ) - alternative = Sequence( "alternative" ) - rule = Sequence( "rule", symboldef, alternative ) - - # grammar: rule+ - grammar = KleenStar( "grammar", _min=1, rule=rule ) - - # alternative: sequence ( '|' sequence )* - sequence = KleenStar( "sequence", 1 ) - seq_cont_list = Sequence( "seq_cont_list", Token('|'), sequence ) - sequence_cont = KleenStar( "sequence_cont",0, rule=seq_cont_list ) - - alternative.args = [ sequence, sequence_cont ] - - # option: '[' alternative ']' - option = Sequence( "option", Token('['), alternative, Token(']') ) - - # group: '(' alternative ')' - group = Sequence( "group", Token('('), alternative, Token(')'), star_opt ) - - # sequence: (SYMBOL | STRING | option | group )+ - string = Token('STRING') - alt = Alternative( "sequence_alt", symbol, string, option, group ) - sequence.args = [ alt ] - - return grammar - - -def parse_grammar(stream): - """parses the grammar file - - stream : file-like object representing the grammar to parse - """ - source = GrammarSource(stream.read()) - rule = grammar_grammar() - builder = BaseGrammarBuilder() - result = rule.match(source, builder) - node = builder.stack[-1] - vis = EBNFVisitor() - node.visit(vis) - return vis - - -from pprint import pprint -if __name__ == "__main__": - grambuild = parse_grammar(file('../python/Grammar')) - for i,r in enumerate(grambuild.items): - print "% 3d : %s" % (i, r) - pprint(grambuild.terminals.keys()) - pprint(grambuild.tokens) - print "|".join(grambuild.tokens.keys() ) - Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/grammar.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/grammar.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,322 +0,0 @@ -""" -a generic recursive descent parser -the grammar is defined as a composition of objects -the objects of the grammar are : -Alternative : as in S -> A | B | C -Sequence : as in S -> A B C -KleenStar : as in S -> A* or S -> A+ -Token : a lexer token -""" - -DEBUG = 0 - -#### Abstract interface for a lexer/tokenizer -class TokenSource(object): - """Abstract base class for a source tokenizer""" - def context(self): - """Returns a context to restore the state of the object later""" - - def restore(self, ctx): - """Restore the context""" - - def next(self): - """Returns the next token from the source - a token is a tuple : (type,value) or (None,None) if the end of the - source has been found - """ - - def offset(self, ctx=None): - """Returns the position we're at so far in the source - optionnally provide a context and you'll get the offset - of the context""" - return -1 - - def current_line(self): - """Returns the current line number""" - return 0 - - -###################################################################### - -from syntaxtree import SyntaxNode, TempSyntaxNode, TokenNode - -class BaseGrammarBuilder(object): - """Base/default class for a builder""" - def __init__( self, rules=None, debug=0): - self.rules = rules or {} # a dictionary of grammar rules for debug/reference - self.debug = debug - self.stack = [] - - def context(self): - """Returns the state of the builder to be restored later""" - #print "Save Stack:", self.stack - return len(self.stack) - - def restore(self, ctx): - del self.stack[ctx:] - #print "Restore Stack:", self.stack - - def alternative(self, rule, source): - # Do nothing, keep rule on top of the stack - if rule.is_root(): - elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.name, source, *elems) - if self.debug: - self.stack[-1].dumpstr() - return True - - def sequence(self, rule, source, elts_number): - """ """ - items = [] - for node in self.stack[-elts_number:]: - items += node.expand() - if rule.is_root(): - node_type = SyntaxNode - else: - node_type = TempSyntaxNode - # replace N elements with 1 element regrouping them - if elts_number >= 1: - elem = node_type(rule.name, source, *items) - del self.stack[-elts_number:] - self.stack.append(elem) - elif elts_number == 0: - self.stack.append(node_type(rule.name, source)) - if self.debug: - self.stack[-1].dumpstr() - return True - - def token(self, name, value, source): - self.stack.append(TokenNode(name, source, value)) - if self.debug: - self.stack[-1].dumpstr() - return True - - -###################################################################### -# Grammar Elements Classes (Alternative, Sequence, KleenStar, Token) # -###################################################################### -class GrammarElement(object): - """Base parser class""" - def __init__(self, name): - # the rule name - self.name = name - self.args = [] - self._is_root = False - - def is_root(self): - """This is a root node of the grammar, that is one that will - be included in the syntax tree""" - if self.name!=":" and self.name.startswith(":"): - return False - return True - - def match(self, source, builder): - """Try to match a grammar rule - - If next set of tokens matches this grammar element, use - to build an appropriate object, otherwise returns None. - - /!\ If the sets of element didn't match the current grammar - element, then the is restored as it was before the - call to the match() method - - returns None if no match or an object build by builder - """ - return None - - def parse(self, source): - """Returns a simplified grammar if the rule matched at the source - current context or None""" - # **NOT USED** **NOT IMPLEMENTED** - # To consider if we need to improve speed in parsing - pass - - def first_set(self): - """Returns a list of possible tokens that can start this rule - None means the rule can be empty - """ - # **NOT USED** **NOT IMPLEMENTED** - # To consider if we need to improve speed in parsing - pass - - def __str__(self): - return self.display(0) - - def __repr__(self): - return self.display(0) - - def display(self, level): - """Helper function used to represent the grammar. - mostly used for debugging the grammar itself""" - return "GrammarElement" - - - def debug_return(self, ret, *args ): - # FIXME: use a wrapper of match() methods instead of debug_return() - # to prevent additional indirection - if ret and DEBUG>0: - sargs = ",".join( [ str(i) for i in args ] ) - print "matched %s (%s): %s" % (self.__class__.__name__, sargs, self.display() ) - return ret - -class Alternative(GrammarElement): - """Represents an alternative in a grammar rule (as in S -> A | B | C)""" - def __init__(self, name, *args): - GrammarElement.__init__(self, name ) - self.args = list(args) - for i in self.args: - assert isinstance( i, GrammarElement ) - - def match(self, source, builder): - """If any of the rules in self.args matches - returns the object built from the first rules that matches - """ - if DEBUG>1: - print "try alt:", self.display() - # Here we stop at the first match we should - # try instead to get the longest alternative - # to see if this solve our problems with infinite recursion - for rule in self.args: - m = rule.match( source, builder ) - if m: - ret = builder.alternative( self, source ) - return self.debug_return( ret ) - return False - - def display(self, level=0): - if level==0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - items = [ a.display(1) for a in self.args ] - return name+"(" + "|".join( items ) + ")" - - -class Sequence(GrammarElement): - """Reprensents a Sequence in a grammar rule (as in S -> A B C)""" - def __init__(self, name, *args): - GrammarElement.__init__(self, name ) - self.args = list(args) - for i in self.args: - assert isinstance( i, GrammarElement ) - - def match(self, source, builder): - """matches all of the symbols in order""" - if DEBUG>1: - print "try seq:", self.display() - ctx = source.context() - bctx = builder.context() - for rule in self.args: - m = rule.match(source, builder) - if not m: - # Restore needed because some rules may have been matched - # before the one that failed - source.restore(ctx) - builder.restore(bctx) - return None - ret = builder.sequence(self, source, len(self.args)) - return self.debug_return( ret ) - - def display(self, level=0): - if level == 0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - items = [a.display(1) for a in self.args] - return name + "(" + " ".join( items ) + ")" - -class KleenStar(GrammarElement): - """Represents a KleenStar in a grammar rule as in (S -> A+) or (S -> A*)""" - def __init__(self, name, _min = 0, _max = -1, rule=None): - GrammarElement.__init__( self, name ) - self.args = [rule] - self.min = _min - if _max == 0: - raise ValueError("KleenStar needs max==-1 or max>1") - self.max = _max - self.star = "x" - - def match(self, source, builder): - """matches a number of times self.args[0]. the number must be comprised - between self._min and self._max inclusive. -1 is used to represent infinity""" - if DEBUG>1: - print "try kle:", self.display() - ctx = source.context() - bctx = builder.context() - rules = 0 - rule = self.args[0] - while True: - m = rule.match(source, builder) - if not m: - # Rule should be matched at least 'min' times - if rules0 and rules == self.max: - ret = builder.sequence(self, source, rules) - return self.debug_return( ret, rules ) - - def display(self, level=0): - if level==0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name - else: - name = "" - star = "{%d,%d}" % (self.min,self.max) - if self.min==0 and self.max==1: - star = "?" - elif self.min==0 and self.max==-1: - star = "*" - elif self.min==1 and self.max==-1: - star = "+" - s = self.args[0].display(1) - return name + "%s%s" % (s, star) - - -class Token(GrammarElement): - """Represents a Token in a grammar rule (a lexer token)""" - def __init__( self, name, value = None): - GrammarElement.__init__( self, name ) - self.value = value - - def match(self, source, builder): - """Matches a token. - the default implementation is to match any token whose type - corresponds to the object's name. You can extend Token - to match anything returned from the lexer. for exemple - type, value = source.next() - if type=="integer" and int(value)>=0: - # found - else: - # error unknown or negative integer - """ - ctx = source.context() - tk_type, tk_value = source.next() - if tk_type==self.name: - if self.value is None: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type ) - elif self.value == tk_value: - ret = builder.token( tk_type, tk_value, source ) - return self.debug_return( ret, tk_type, tk_value ) - if DEBUG>1: - print "tried tok:", self.display() - source.restore( ctx ) - return None - - def display(self, level=0): - if self.value is None: - return "<%s>" % self.name - else: - return "<%s>=='%s'" % (self.name, self.value) - - Modified: pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py Sun Jul 3 20:36:05 2005 @@ -7,9 +7,9 @@ from pypy.interpreter.typedef import TypeDef from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode -from syntaxtree import SyntaxNode -from pythonparse import parse_python_source -from pypy.module.recparser import PYTHON_PARSER +from pypy.interpreter.pyparser.syntaxtree import SyntaxNode +from pypy.interpreter.pyparser.pythonparse import parse_python_source +from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -100,20 +100,24 @@ ) def suite( space, source ): - builder = parse_python_source( source, PYTHON_PARSER, "file_input" ) + # make the annotator life easier (don't use str.splitlines()) + strings = [line + '\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) return space.wrap( STType(space, builder.stack[-1]) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): - builder = parse_python_source( source, PYTHON_PARSER, "eval_input" ) + # make the annotator life easier (don't use str.splitlines()) + strings = [line + '\n' for line in source.split('\n')] + builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) return space.wrap( STType(space, builder.stack[-1]) ) expr.unwrap_spec = [ObjSpace, str] -def ast2tuple(space, node, line_info=False): +def ast2tuple(space, node, line_info=0): """Quick dummy implementation of parser.ast2tuple(tree) function""" tuples = node.totuple(line_info) return space.wrap(tuples) -ast2tuple.unwrap_spec = [ObjSpace, STType, bool] +ast2tuple.unwrap_spec = [ObjSpace, STType, int] Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonlexer.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonlexer.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,411 +0,0 @@ -"""This is a lexer for a Python recursive descent parser -it obeys the TokenSource interface defined for the grammar -analyser in grammar.py -""" - -from grammar import TokenSource - -DEBUG = False -import re - -KEYWORDS = [ - 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', - 'elif', 'if', 'import', 'in', 'is', 'finally', 'for', 'from', - 'global', 'else', 'except', 'exec', 'lambda', 'not', 'or', - 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield' - ] - -py_keywords = re.compile(r'(%s)$' % ('|'.join(KEYWORDS)), re.M | re.X) - -py_punct = re.compile(r""" -<>|!=|==|~| -<=|<<=|<<|<| ->=|>>=|>>|>| -\*=|\*\*=|\*\*|\*| -//=|/=|//|/| -%=|\^=|\|=|\+=|=|&=|-=| -,|\^|&|\+|-|\.|%|\|| -\)|\(|;|:|@|\[|\]|`|\{|\} -""", re.M | re.X) - -g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:", re.M) -g_string = re.compile(r"'[^']+'", re.M) -py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) -py_comment = re.compile(r"#.*$|[ \t\014]*$", re.M) -py_ws = re.compile(r" *", re.M) -py_skip = re.compile(r"[ \t\014]*(#.*$)?", re.M) -py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") -# py_number = re.compile(r"0x[0-9a-z]+|[0-9]+l|([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?j?||[0-9]+", re.I) - -# 0x[\da-f]+l matches hexadecimal numbers, possibly defined as long -# \d+l matches and only matches long integers -# (\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? matches simple integers, -# exponential notations and complex -py_number = re.compile(r"""0x[\da-f]+l?| -\d+l| -(\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? -""", re.I | re.X) - -def _normalize_encoding(encoding): - """returns normalized name for - - see dist/src/Parser/tokenizer.c 'get_normal_name()' - for implementation details / reference - - NOTE: for now, parser.suite() raises a MemoryError when - a bad encoding is used. (SF bug #979739) - """ - # lower() + '_' / '-' conversion - encoding = encoding.replace('_', '-').lower() - if encoding.startswith('utf-8'): - return 'utf-8' - for variant in ('latin-1', 'iso-latin-1', 'iso-8859-1'): - if encoding.startswith(variant): - return 'iso-8859-1' - return encoding - -class PythonSource(TokenSource): - """The Python tokenizer""" - def __init__(self, inpstring): - TokenSource.__init__(self) - self.input = inpstring - self.pos = 0 - self.indent = 0 - self.indentstack = [ 0 ] - self.atbol = True - self.line = 1 - self._current_line = 1 - self.pendin = 0 # indentation change waiting to be reported - self.level = 0 - self.linestart = 0 - self.stack = [] - self.stack_pos = 0 - self.comment = '' - self.encoding = None - - def current_line(self): - return self._current_line - - def context(self): - return self.stack_pos - - def restore(self, ctx): - self.stack_pos = ctx - - def offset(self, ctx=None): - if ctx is None: - return self.stack_pos - else: - assert type(ctx)==int - return ctx - - def _next(self): - """returns the next token from source""" - inp = self.input - pos = self.pos - input_length = len(inp) - if pos >= input_length: - return self.end_of_file() - # Beginning of line - if self.atbol: - self.linestart = pos - col = 0 - m = py_ws.match(inp, pos) - pos = m.end() - col = pos - self.linestart - self.atbol = False - # skip blanklines - m = py_comment.match(inp, pos) - if m: - if not self.comment: - self.comment = m.group(0) - # XXX FIXME: encoding management - if self.line <= 2: - # self.comment can be the previous comment, so don't use it - comment = m.group(0)[1:] - m_enc = py_encoding.search(comment) - if m_enc is not None: - self.encoding = _normalize_encoding(m_enc.group(1)) - # - self.pos = m.end() + 1 - self.line += 1 - self.atbol = True - return self._next() - # the current block is more indented than the previous one - if col > self.indentstack[-1]: - self.indentstack.append(col) - return "INDENT", None - # the current block is less indented than the previous one - while col < self.indentstack[-1]: - self.pendin += 1 - self.indentstack.pop(-1) - if col != self.indentstack[-1]: - raise SyntaxError("Indentation Error") - if self.pendin > 0: - self.pendin -= 1 - return "DEDENT", None - m = py_skip.match(inp, pos) - if m.group(0)[-1:] == '\n': - self.line += 1 - self.comment = m.group(1) or '' - pos = m.end() # always match - if pos >= input_length: - return self.end_of_file() - self.pos = pos - - # STRING - c = inp[pos] - if c in ('r','R'): - if pos < input_length-1 and inp[pos+1] in ("'",'"'): - return self.next_string(raw=1) - elif c in ('u','U'): - if pos < input_length-1: - if inp[pos+1] in ("r",'R'): - if pos 0: - return self._next() - else: - self.atbol = True - comment = self.comment - self.comment = '' - return "NEWLINE", comment - - if c == '\\': - if pos < input_length-1 and inp[pos+1] == '\n': - self.pos += 2 - return self._next() - - m = py_punct.match(inp, pos) - if m: - punct = m.group(0) - if punct in ( '(', '{', '[' ): - self.level += 1 - if punct in ( ')', '}', ']' ): - self.level -= 1 - self.pos = m.end() - return punct, None - raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) - - def next(self): - if self.stack_pos >= len(self.stack): - tok, val = self._next() - self.stack.append( (tok, val, self.line) ) - self._current_line = self.line - else: - tok,val,line = self.stack[self.stack_pos] - self._current_line = line - self.stack_pos += 1 - if DEBUG: - print "%d/%d: %s, %s" % (self.stack_pos, len(self.stack), tok, val) - return (tok, val) - - def end_of_file(self): - """return DEDENT and ENDMARKER""" - if len(self.indentstack) == 1: - self.indentstack.pop(-1) - return "NEWLINE", '' #self.comment - elif len(self.indentstack) > 1: - self.indentstack.pop(-1) - return "DEDENT", None - return "ENDMARKER", None - - - def next_string(self, raw=0, uni=0): - pos = self.pos + raw + uni - inp = self.input - quote = inp[pos] - qsize = 1 - if inp[pos:pos+3] == 3*quote: - pos += 3 - quote = 3*quote - qsize = 3 - else: - pos += 1 - while True: - if inp[pos:pos+qsize] == quote: - s = inp[self.pos:pos+qsize] - self.pos = pos+qsize - return "STRING", s - # FIXME : shouldn't it be inp[pos] == os.linesep ? - if inp[pos:pos+2] == "\n" and qsize == 1: - return None, None - if inp[pos] == "\\": - pos += 1 - pos += 1 - - def debug(self): - """return context for debug information""" - if not hasattr(self, '_lines'): - # split lines only once - self._lines = self.input.splitlines() - if self.line > len(self._lines): - lineno = len(self._lines) - else: - lineno = self.line - return 'line %s : %s' % (lineno, self._lines[lineno-1]) - - ## ONLY refactor ideas ########################################### -## def _mynext(self): -## """returns the next token from source""" -## inp = self.input -## pos = self.pos -## input_length = len(inp) -## if pos >= input_length: -## return self.end_of_file() -## # Beginning of line -## if self.atbol: -## self.linestart = pos -## col = 0 -## m = py_ws.match(inp, pos) -## pos = m.end() -## col = pos - self.linestart -## self.atbol = False -## # skip blanklines -## m = py_comment.match(inp, pos) -## if m: -## self.pos = m.end() + 1 -## self.line += 1 -## self.atbol = True -## return self._next() -## # the current block is more indented than the previous one -## if col > self.indentstack[-1]: -## self.indentstack.append(col) -## return "INDENT", None -## # the current block is less indented than the previous one -## while col < self.indentstack[-1]: -## self.pendin += 1 -## self.indentstack.pop(-1) -## if col != self.indentstack[-1]: -## raise SyntaxError("Indentation Error") -## if self.pendin > 0: -## self.pendin -= 1 -## return "DEDENT", None -## m = py_skip.match(inp, pos) -## if m.group(0)[-1:] == '\n': -## self.line += 1 -## pos = m.end() # always match -## if pos >= input_length: -## return self.end_of_file() -## self.pos = pos - -## c = inp[pos] -## chain = (self._check_string, self._check_name, self._check_number, -## self._check_newline, self._check_backslash, self._check_punct) -## for check_meth in chain: -## token_val_pair = check_meth(c, pos) -## if token_val_pair is not None: -## return token_val_pair - - -## def _check_string(self, c, pos): -## inp = self.input -## input_length = len(inp) -## # STRING -## if c in ('r', 'R'): -## if pos < input_length-1 and inp[pos+1] in ("'",'"'): -## return self.next_string(raw=1) -## elif c in ('u','U'): -## if pos < input_length - 1: -## if inp[pos+1] in ("r", 'R'): -## if pos 0: -## return self._next() -## else: -## self.atbol = True -## return "NEWLINE", None -## return None - -## def _check_backslash(self, c, pos): -## inp = self.input -## input_length = len(inp) -## if c == '\\': -## if pos < input_length-1 and inp[pos+1] == '\n': -## self.pos += 2 -## return self._next() -## return None - -## def _check_punct(self, c, pos): -## inp = self.input -## input_length = len(inp) -## m = py_punct.match(inp, pos) -## if m: -## punct = m.group(0) -## if punct in ( '(', '{' ): -## self.level += 1 -## if punct in ( ')', '}' ): -## self.level -= 1 -## self.pos = m.end() -## return punct, None -## raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) - - - -def tokenize_file(filename): - f = file(filename).read() - src = PythonSource(f) - token = src.next() - while token!=("ENDMARKER",None) and token!=(None,None): - print token - token = src.next() - -if __name__ == '__main__': - import sys - tokenize_file(sys.argv[1]) Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonparse.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonparse.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,65 +0,0 @@ -#!/usr/bin/env python -from grammar import BaseGrammarBuilder -from pythonlexer import PythonSource -from ebnfparse import parse_grammar -import sys -import pythonutil -import symbol - -def parse_python_source( textsrc, gram, goal ): - """Parse a python source according to goal""" - target = gram.rules[goal] - src = PythonSource(textsrc) - builder = BaseGrammarBuilder(debug=False, rules=gram.rules) - result = target.match(src, builder) - # XXX find a clean way to process encoding declarations - if src.encoding: - builder._source_encoding = src.encoding - # - if not result: - raise SyntaxError("at %s" % src.debug() ) - return builder - -def parse_file_input(pyf, gram): - """Parse a python file""" - return parse_python_source( pyf.read(), gram, "file_input" ) - -def parse_single_input(textsrc, gram): - """Parse a python file""" - return parse_python_source( textsrc, gram, "single_input" ) - -def parse_eval_input(textsrc, gram): - """Parse a python file""" - return parse_python_source( textsrc, gram, "eval_input" ) - -def pypy_parse(filename): - """parse using PyPy's parser module and return nested tuples - """ - pyf = file(filename) - builder = parse_file_input(pyf, pythonutil.python_grammar()) - pyf.close() - if builder.stack: - # print builder.stack[-1] - root_node = builder.stack[-1] - nested_tuples = root_node.totuple() - if hasattr(builder, '_source_encoding'): - # XXX: maybe the parser could fix that instead ? - return ( symbol.encoding_decl, nested_tuples, builder._source_encoding) - else: - return nested_tuples - return None # XXX raise an exception instead - -if __name__ == "__main__": - if len(sys.argv) < 2: - print "python parse.py [-d N] test_file.py" - sys.exit(1) - if sys.argv[1] == "-d": - debug_level = int(sys.argv[2]) - test_file = sys.argv[3] - else: - test_file = sys.argv[1] - print "-"*20 - print - print "pyparse \n", pypy_parse(test_file) - print "parser \n", pythonutil.python_parse(test_file) - Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonutil.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/pythonutil.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,35 +0,0 @@ -__all__ = ["python_grammar", "PYTHON_GRAMMAR" ] - -import os -import sys - -_ver = ".".join([str(i) for i in sys.version_info[:2]]) -PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) - -def python_grammar(): - """returns a """ - from ebnfparse import parse_grammar - level = get_debug() - set_debug( 0 ) - gram = parse_grammar( file(PYTHON_GRAMMAR) ) - set_debug( level ) - return gram - -def get_debug(): - """Return debug level""" - import grammar - return grammar.DEBUG - -def set_debug( level ): - """sets debug mode to """ - import grammar - grammar.DEBUG = level - - -def python_parse(filename): - """parse using CPython's parser module and return nested tuples - """ - pyf = file(filename) - import parser - tp2 = parser.suite(pyf.read()) - return tp2.totuple() Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/syntaxtree.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/syntaxtree.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,160 +0,0 @@ -import symbol -import token - -TOKEN_MAP = { - "STRING" : token.STRING, - "NUMBER" : token.NUMBER, - "NAME" : token.NAME, - "NEWLINE" : token.NEWLINE, - "DEDENT" : token.DEDENT, - "ENDMARKER" : token.ENDMARKER, - "INDENT" : token.INDENT, - "NEWLINE" : token.NEWLINE, - "NT_OFFSET" : token.NT_OFFSET, - "N_TOKENS" : token.N_TOKENS, - "OP" : token.OP, - "?ERRORTOKEN" : token.ERRORTOKEN, - "&" : token.AMPER, - "&=" : token.AMPEREQUAL, - "`" : token.BACKQUOTE, - "^" : token.CIRCUMFLEX, - "^=" : token.CIRCUMFLEXEQUAL, - ":" : token.COLON, - "," : token.COMMA, - "." : token.DOT, - "//" : token.DOUBLESLASH, - "//=" : token.DOUBLESLASHEQUAL, - "**" : token.DOUBLESTAR, - "**=" : token.DOUBLESTAREQUAL, - "==" : token.EQEQUAL, - "=" : token.EQUAL, - ">" : token.GREATER, - ">=" : token.GREATEREQUAL, - "{" : token.LBRACE, - "}" : token.RBRACE, - "<<" : token.LEFTSHIFT, - "<<=" : token.LEFTSHIFTEQUAL, - "<" : token.LESS, - "<=" : token.LESSEQUAL, - "(" : token.LPAR, - "[" : token.LSQB, - "-=" : token.MINEQUAL, - "-" : token.MINUS, - "!=" : token.NOTEQUAL, - "<>" : token.NOTEQUAL, - "%" : token.PERCENT, - "%=" : token.PERCENTEQUAL, - "+" : token.PLUS, - "+=" : token.PLUSEQUAL, - ")" : token.RBRACE, - ">>" : token.RIGHTSHIFT, - ">>=" : token.RIGHTSHIFTEQUAL, - ")" : token.RPAR, - "]" : token.RSQB, - ";" : token.SEMI, - "/" : token.SLASH, - "/=" : token.SLASHEQUAL, - "*" : token.STAR, - "*=" : token.STAREQUAL, - "~" : token.TILDE, - "|" : token.VBAR, - "|=" : token.VBAREQUAL, - } - -SYMBOLS = {} -# copies the numerical mapping between symbol name and symbol value -# into SYMBOLS -for k,v in symbol.__dict__.items(): - if type(v)==int: - SYMBOLS[k] = v - - -class SyntaxNode(object): - """A syntax node""" - def __init__(self, name, source, *args): - self.name = name - self.nodes = list(args) - self.lineno = source.current_line() - - def dumptree(self, treenodes, indent): - treenodes.append(self.name) - if len(self.nodes) > 1: - treenodes.append(" -> (\n") - treenodes.append(indent+" ") - for node in self.nodes: - node.dumptree(treenodes, indent+" ") - treenodes.append(")\n") - treenodes.append(indent) - elif len(self.nodes) == 1: - treenodes.append(" ->\n") - treenodes.append(indent+" ") - self.nodes[0].dumptree(treenodes, indent+" ") - - def dumpstr(self): - treenodes = [] - self.dumptree(treenodes, "") - return "".join(treenodes) - - def __repr__(self): - return "" % (self.name, id(self)) - - def __str__(self): - return "(%s)" % self.name - - def visit(self, visitor): - visit_meth = getattr(visitor, "visit_%s" % self.name, None) - if visit_meth: - return visit_meth(self) - # helper function for nodes that have only one subnode: - if len(self.nodes) == 1: - return self.nodes[0].visit(visitor) - raise RuntimeError("Unknonw Visitor for %r" % self.name) - - def expand(self): - return [ self ] - - def totuple(self, lineno=False ): - symvalue = SYMBOLS.get( self.name, (0,self.name) ) - l = [ symvalue ] - l += [node.totuple(lineno) for node in self.nodes] - return tuple(l) - - -class TempSyntaxNode(SyntaxNode): - """A temporary syntax node to represent intermediate rules""" - def expand(self): - return self.nodes - -class TokenNode(SyntaxNode): - """A token node""" - def __init__(self, name, source, value): - SyntaxNode.__init__(self, name, source) - self.value = value - - def dumptree(self, treenodes, indent): - if self.value: - treenodes.append("%s='%s' (%d) " % (self.name, self.value, self.lineno)) - else: - treenodes.append("'%s' (%d) " % (self.name, self.lineno)) - - def __repr__(self): - if self.value is not None: - return "<%s=%s>" % ( self.name, repr(self.value)) - else: - return "<%s!>" % (self.name,) - - def totuple(self, lineno=False): - num = TOKEN_MAP.get(self.name, -1) - if num == -1: - print "Unknown", self.name, self.value - if self.value is not None: - val = self.value - else: - if self.name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): - val = self.name - else: - val = self.value or '' - if lineno: - return (num, val, self.lineno) - else: - return (num, val) Deleted: /pypy/branch/dist-2.4.1/pypy/module/recparser/tuplebuilder.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/module/recparser/tuplebuilder.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,61 +0,0 @@ - -from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP, SYMBOLS, NT_OFFSET - - -def _expand_nodes( nodes ): - expanded = [] - for n in nodes: - if n[0]==-2: - expanded.extend( expand_nodes(n[1:]) ) - else: - expanded.append(n) - return tuple(expanded) - -def expand_nodes( nodes ): - r = _expand_nodes( nodes ) - for n in nodes: - assert type(n[0])==int - return r - -class TupleBuilder(BaseGrammarBuilder): - """A builder that directly produce the AST""" - - def __init__( self, rules=None, debug=0, lineno=False ): - BaseGrammarBuilder.__init__(self, rules, debug ) - self.lineno = True - - def alternative( self, rule, source ): - # Do nothing, keep rule on top of the stack - if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] - node += expand_nodes( [self.stack[-1]] ) - self.stack[-1] = tuple(node) - return True - - def sequence(self, rule, source, elts_number): - """ """ - if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] - else: - node = [ -2 ] - if elts_number>0: - node += expand_nodes( self.stack[-elts_number:] ) - self.stack[-elts_number:] = [tuple(node)] - else: - self.stack.append( tuple(node) ) - return True - - def token(self, name, value, source): - num = TOKEN_MAP.get( name, -1) - lineno = source.current_line() - if value is None: - if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): - value = name - else: - value = '' - if self.lineno: - self.stack.append( (num, value, lineno) ) - else: - self.stack.append( (num, value) ) - return True Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/fake.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/fake.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/fake.py Sun Jul 3 20:36:05 2005 @@ -142,13 +142,17 @@ self.unwrappedargs = self.space.unwrap(w_args) self.unwrappedkwds = self.space.unwrap(w_kwds) except UnwrapError, e: - raise UnwrapError('calling %s: %s' % (self.code.cpy_callable, e)) + code = self.code + assert isinstance(code, CPythonFakeCode) + raise UnwrapError('calling %s: %s' % (code.cpy_callable, e)) def getfastscope(self): raise OperationError(self.space.w_TypeError, self.space.wrap("cannot get fastscope of a CPythonFakeFrame")) def run(self): - fn = self.code.cpy_callable + code = self.code + assert isinstance(code, CPythonFakeCode) + fn = code.cpy_callable try: result = apply(fn, self.unwrappedargs, self.unwrappedkwds) except: Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py Sun Jul 3 20:36:05 2005 @@ -582,7 +582,7 @@ return z -#Substract the absolute values of two longs +# Substract the absolute values of two longs def _x_sub(a, b, space): size_a = len(a.digits) size_b = len(b.digits) @@ -649,8 +649,244 @@ return z def _inplace_divrem1(pout, pin, n): - rem = r_uint(0, space) + """ + Divide long pin by non-zero digit n, storing quotient + in pout, and returning the remainder. It's OK for pin == pout on entry. + """ + rem = r_uint(0) assert n > 0 and n <= SHORT_MASK size = len(pin.digits) * 2 - 1 while size >= 0: rem = (rem << SHORT_BIT) + pin._getshort(size) + hi = rem // n + pout._setshort(size, hi) + rem -= hi * n + size -= 1 + return rem + +def _divrem1(space, a, n): + """ + Divide a long integer by a digit, returning both the quotient + and the remainder as a tuple. + The sign of a is ignored; n should not be zero. + """ + assert n > 0 and n <= SHORT_MASK + size = len(a.digits) + z = W_LongObject(space, [r_uint(0)] * size, 1) + rem = _inplace_divrem1(z, a, n) + z._normalize() + return z, rem + +def _muladd1(space, a, n, extra): + """Multiply by a single digit and add a single digit, ignoring the sign. + """ + digitpairs = len(a.digits) + size_a = digitpairs * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + z = W_LongObject(space, [r_uint(0)] * (digitpairs+1), 1) + carry = extra + for i in range(size_a): + carry += a._getshort(i) * n + z._setshort(i, carry & SHORT_MASK) + carry >>= SHORT_BIT + i += 1 + z._setshort(i, carry) + z._normalize() + return z + +# for the carry in _x_divrem, we need something that can hold +# two digits plus a sign. +# for the time being, we here implement such a 33 bit number just +# for the purpose of the division. +# In the long term, it might be considered to implement the +# notation of a "double anything" unsigned type, which could +# be used recursively to implement longs of any size. + +class r_suint(object): + # we do not inherit from r_uint, because we only + # support a few operations for our purpose + def __init__(self, value=0): + if isinstance(value, r_suint): + self.value = value.value + self.sign = value.sign + else: + self.value = r_uint(value) + self.sign = -(value < 0) + + def longval(self): + if self.sign: + return -long(-self.value) + else: + return long(self.value) + + def __repr__(self): + return repr(self.longval()) + + def __str__(self): + return str(self.longval()) + + def __iadd__(self, other): + hold = self.value + self.value += other + self.sign ^= - ( (other < 0) != (self.value < hold) ) + return self + + def __add__(self, other): + res = r_suint(self) + res += other + return res + + def __isub__(self, other): + hold = self.value + self.value -= other + self.sign ^= - ( (other < 0) != (self.value > hold) ) + return self + + def __sub__(self, other): + res = r_suint(self) + res -= other + return res + + def __irshift__(self, n): + self.value >>= n + if self.sign: + self.value += LONG_MASK << (LONG_BIT - n) + return self + + def __rshift__(self, n): + res = r_suint(self) + res >>= n + return res + + def __and__(self, mask): + # only used to get bits from the value + return self.value & mask + + def __eq__(self, other): + if not isinstance(other,r_suint): + other = r_suint(other) + return self.sign == other.sign and self.value == other.value + +def _x_divrem(space, v1, w1): # return as tuple, PyLongObject **prem) + size_w = len(w1.digits) * 2 + # hack for the moment: + # find where w1 is really nonzero + if w1._getshort(size_w-1) == 0: + size_w -= 1 + d = (SHORT_MASK+1) // (w1._getshort(size_w-1) + 1) + v = _muladd1(space, v1, d, r_uint(0)) + w = _muladd1(space, w1, d, r_uint(0)) + size_v = len(v.digits) * 2 + if v._getshort(size_v-1) == 0: + size_v -= 1 + size_w = len(w.digits) * 2 + if w._getshort(size_w-1) == 0: + size_w -= 1 + assert size_v >= size_w and size_w > 1 # Assert checks by div() + + size_a = size_v - size_w + 1 + digitpairs = (size_a + 1) // 2 + a = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + j = size_v + for k in range(size_a-1, -1, -1): + if j >= size_v: + vj = r_uint(0) + else: + vj = v._getshort(j) + carry = r_suint(0) # note: this must hold two digits and sign! + + if vj == w._getshort(size_w-1): + q = r_uint(SHORT_MASK) + else: + q = ((vj << SHORT_BIT) + v._getshort(j-1)) // w._getshort(size_w-1) + + while (w._getshort(size_w-2) * q > + (( + (vj << SHORT_BIT) + + v._getshort(j-1) + - q * w._getshort(size_w-1) + ) << SHORT_BIT) + + v._getshort(j-2)): + q -= 1 + + for i in range(size_w): + if i+k >= size_v: + break + z = w._getshort(i) * q + zz = z >> SHORT_BIT + carry += v._getshort(i+k) + (zz << SHORT_BIT) + carry -= z + v._setshort(i+k, r_uint(carry.value & SHORT_MASK)) + carry >>= SHORT_BIT + carry -= zz + + i += 1 # compare C code which re-uses i of loop + if i+k < size_v: + carry += v._getshort(i+k) + v._setshort(i+k, r_uint(0)) + + if carry == 0: + a._setshort(k, q) + else: + #assert carry == -1 + # the above would hold if we didn't minimize size_w + a._setshort(k, q-1) + carry = r_suint(0) + + for i in range(size_w): + if i+k >= size_v: + break + carry += v._getshort(i+k) + w._getshort(i) + v._setshort(i+k, r_uint(carry) & SHORT_MASK) + carry >>= SHORT_BIT + j -= 1 + + a._normalize() + rem, _ = _divrem1(space, v, d) + return a, rem + + +##def _divrem(a, b) +## size_a = len(a.digits) * 2 +## size_b = len(b.digits) * 2 +## PyLongObject *z; +## +## if (size_b == 0) { +## PyErr_SetString(PyExc_ZeroDivisionError, +## "long division or modulo by zero"); +## return -1; +## } +## if (size_a < size_b || +## (size_a == size_b && +## a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { +## /* |a| < |b|. */ +## *pdiv = _PyLong_New(0); +## Py_INCREF(a); +## *prem = (PyLongObject *) a; +## return 0; +## } +## if (size_b == 1) { +## digit rem = 0; +## z = divrem1(a, b->ob_digit[0], &rem); +## if (z == NULL) +## return -1; +## *prem = (PyLongObject *) PyLong_FromLong((long)rem); +## } +## else { +## z = x_divrem(a, b, prem); +## if (z == NULL) +## return -1; +## } +## /* Set the signs. +## The quotient z has the sign of a*b; +## the remainder r has the sign of a, +## so a = b*z + r. */ +## if ((a->ob_size < 0) != (b->ob_size < 0)) +## z->ob_size = -(z->ob_size); +## if (a->ob_size < 0 && (*prem)->ob_size != 0) +## (*prem)->ob_size = -((*prem)->ob_size); +## *pdiv = z; +## return 0; + +## XXXX Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py Sun Jul 3 20:36:05 2005 @@ -1084,7 +1084,8 @@ # CPython's logic for deciding if ""%values is # an error (1 value, 0 %-formatters) or not # (values is of a mapping type) - if hasattr(values, '__getitem__') and not isinstance(values, str): + if (hasattr(values, '__getitem__') + and not isinstance(values, basestring)): return _formatting.format(format, (values,), values) else: return _formatting.format(format, (values,), None) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py Sun Jul 3 20:36:05 2005 @@ -50,6 +50,24 @@ result = lobj.mul__Long_Long(self.space, f1, f2) assert result.longval() == x * y + def test__inplace_divrem1(self): + # signs are not handled in the helpers! + x = 1238585838347L + y = 3 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + remainder = lobj._inplace_divrem1(f1, f1, f2) + assert (f1.longval(), remainder) == divmod(x, y) + + def test__divrem1(self): + # signs are not handled in the helpers! + x = 1238585838347L + y = 3 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + div, rem = lobj._divrem1(self.space, f1, f2) + assert (div.longval(), rem) == divmod(x, y) + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringobject.py Sun Jul 3 20:36:05 2005 @@ -116,9 +116,24 @@ assert self.space.eq_w(space.getitem(w_str, w_slice), w('el')) class AppTestStringObject: + def test_format_wrongchar(self): raises(ValueError, 'a%Zb'.__mod__, ((23,),)) + def test_format(self): + raises(TypeError, "foo".__mod__, "bar") + raises(TypeError, u"foo".__mod__, "bar") + raises(TypeError, "foo".__mod__, u"bar") + + for format, arg, cls in [("a %s b", "foo", str), + (u"a %s b", "foo", unicode), + ("a %s b", u"foo", unicode), + (u"a %s b", u"foo", unicode)]: + raises(TypeError, format[:2].__mod__, arg) + result = format % arg + assert result == "a foo b" + assert isinstance(result, cls) + def test_split(self): assert "".split() == [] assert " ".split() == [] Modified: pypy/branch/dist-2.4.1/pypy/rpython/lltype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/lltype.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/lltype.py Sun Jul 3 20:36:05 2005 @@ -4,6 +4,8 @@ from pypy.tool.uid import Hashable from pypy.tool.tls import tlsobject +log = py.log.Producer('lltype') + TLS = tlsobject() def saferecursive(func, defl): @@ -141,6 +143,30 @@ raise AttributeError, 'struct %s has no field %r' % (self._name, name) + + + + def _names_without_voids(self, at_root=True): + if at_root: #XXX debug stuff + log('_names_without_voids: ' + self._str_without_voids()) + names_without_voids = [name for name in self._names if self._flds[name] is not Void] + if names_without_voids != list(self._names): + log('_names_without_voids: removed Void(s) _names=%s, return=%s' % (str(list(self._names)), str(names_without_voids))) + #return self._names + return names_without_voids + + def _str_fields_without_voids(self): + return ', '.join(['%s: %s' % (name, self._flds[name]) + for name in self._names_without_voids(False)]) + _str_fields_without_voids = saferecursive(_str_fields_without_voids, '...') + + def _str_without_voids(self): + return "%s %s { %s }" % (self.__class__.__name__, + self._name, self._str_fields_without_voids()) + + + + def _str_fields(self): return ', '.join(['%s: %s' % (name, self._flds[name]) for name in self._names]) @@ -240,6 +266,10 @@ return self.RESULT._defl() return _func(self, _callable=ex) + def _trueargs(self): + return [arg for arg in self.ARGS if arg is not Void] + + class OpaqueType(ContainerType): def __init__(self, tag): Modified: pypy/branch/dist-2.4.1/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rclass.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rclass.py Sun Jul 3 20:36:05 2005 @@ -156,6 +156,7 @@ # as MethodType has a custom __get__ too and we don't support # it, it's a very bad idea anyway. if isinstance(s_value, annmodel.SomePBC): + s_value = self.classdef.matching(s_value) debound = {} count = 0 for x, classdef in s_value.prebuiltinstances.items(): @@ -396,8 +397,11 @@ result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): - attrvalue = getattr(value, name) - llattrvalue = r.convert_const(attrvalue) + if r.lowleveltype == Void: + llattrvalue = None + else: + attrvalue = getattr(value, name) + llattrvalue = r.convert_const(attrvalue) setattr(result, mangled_name, llattrvalue) else: # OBJECT part Modified: pypy/branch/dist-2.4.1/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rconstantdict.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rconstantdict.py Sun Jul 3 20:36:05 2005 @@ -84,10 +84,10 @@ #def make_iterator_repr(self): # return StrDictIteratorRepr(self) - #def rtype_method_get(self, hop): - # v_dict, v_key, v_default = hop.inputargs(self, string_repr, - # self.value_repr) - # return hop.gendirectcall(ll_get, v_dict, v_key, v_default) + def rtype_method_get(self, hop): + v_dict, v_key, v_default = hop.inputargs(self, self.key_repr, + self.value_repr) + return hop.gendirectcall(ll_constantdict_get, v_dict, v_key, v_default) class __extend__(pairtype(ConstantDictRepr, rmodel.Repr)): @@ -125,6 +125,13 @@ entry = ll_constantdict_lookup(d, key)#, hashcompute) return entry.valid +def ll_constantdict_get(d, key, default):#, hashcompute): + entry = ll_constantdict_lookup(d, key)#, hashcompute) + if entry.valid: + return entry.value + else: + return default + def ll_constantdict_setnewitem(d, key, value):#, hashcompute): entry = ll_constantdict_lookup(d, key)#, hashcompute) assert not entry.valid Modified: pypy/branch/dist-2.4.1/pypy/rpython/rdict.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rdict.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rdict.py Sun Jul 3 20:36:05 2005 @@ -3,7 +3,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rarithmetic import r_uint -from pypy.rpython import rlist, rconstantdict +from pypy.rpython import rlist, rconstantdict, remptydict # ____________________________________________________________ # @@ -39,6 +39,8 @@ return rconstantdict.ConstantDictRepr( rtyper.getrepr(dictkey.s_value), rtyper.getrepr(dictvalue.s_value)) + elif isinstance(s_key, annmodel.SomeImpossibleValue): + return remptydict.EmptyDictRepr() else: raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) @@ -331,37 +333,37 @@ # _____________________________________________________________ # methods -def ll_get(v_dict, v_key, v_default): - entry = ll_strdict_lookup(v_dict, v_key) +def ll_get(dict, key, default): + entry = ll_strdict_lookup(dict, key) if entry.key and entry.key != deleted_entry_marker: return entry.value else: - return v_default + return default -def ll_copy(v_dict): - DICTPTR = lltype.typeOf(v_dict) +def ll_copy(dict): + DICTPTR = lltype.typeOf(dict) d = lltype.malloc(DICTPTR.TO) - d.entries = lltype.malloc(DICTPTR.TO.entries.TO, len(v_dict.entries)) - d.num_items = v_dict.num_items - d.num_pristine_entries = v_dict.num_pristine_entries + d.entries = lltype.malloc(DICTPTR.TO.entries.TO, len(dict.entries)) + d.num_items = dict.num_items + d.num_pristine_entries = dict.num_pristine_entries i = 0 dictlen = len(d.entries) while i < dictlen: d_entry = d.entries[i] - v_entry = v_dict.entries[i] - d_entry.key = v_entry.key - d_entry.value = v_entry.value + entry = dict.entries[i] + d_entry.key = entry.key + d_entry.value = entry.value i += 1 return d -def ll_update(v_dic1, v_dic2): - d2len =len(v_dic2.entries) - entries = v_dic2.entries +def ll_update(dic1, dic2): + d2len =len(dic2.entries) + entries = dic2.entries i = 0 while i < d2len: entry = entries[i] if entry.key and entry.key != deleted_entry_marker: - ll_strdict_setitem(v_dic1, entry.key, entry.value) + ll_strdict_setitem(dic1, entry.key, entry.value) i += 1 def dum_keys(): pass @@ -370,13 +372,13 @@ # this is an implementation of keys(), values() and items() # in a single function. -# note that by specialization on v_func, three different +# note that by specialization on func, three different # and very efficient functions are created. -def ll_kvi(v_dic, LISTPTR, v_func): - res = rlist.ll_newlist(LISTPTR, v_dic.num_items) - dlen = len(v_dic.entries) - entries = v_dic.entries +def ll_kvi(dic, LISTPTR, func): + res = rlist.ll_newlist(LISTPTR, dic.num_items) + dlen = len(dic.entries) + entries = dic.entries items = res.items i = 0 p = 0 @@ -384,14 +386,14 @@ entry = entries[i] key = entry.key if key and key != deleted_entry_marker: - if v_func is dum_items: + if func is dum_items: r = lltype.malloc(LISTPTR.TO.items.TO.OF.TO) r.item0 = key r.item1 = entry.value items[p] = r - elif v_func is dum_keys: + elif func is dum_keys: items[p] = key - elif v_func is dum_values: + elif func is dum_values: items[p] = entry.value p += 1 i += 1 Modified: pypy/branch/dist-2.4.1/pypy/rpython/rpbc.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rpbc.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rpbc.py Sun Jul 3 20:36:05 2005 @@ -16,6 +16,7 @@ # categories below, and doesn't for example mix functions, classes # and methods. call_families = rtyper.annotator.getpbccallfamilies() + userclasses = rtyper.annotator.getuserclasses() choices = {} for x, classdef in self.prebuiltinstances.items(): cdefflag = isclassdef(classdef) @@ -26,28 +27,40 @@ if isinstance(x, types.MethodType) and x.im_self is None: x = x.im_func - # callable or frozen object? - if (classdef, x) in call_families: - # what type of callable? - if isinstance(x, types.FunctionType): - if cdefflag: - choice = MethodsPBCRepr - cdefflag = False - else: - choice = FunctionsPBCRepr - elif isinstance(x, (type, types.ClassType)): + if cdefflag: + # methods of a run-time instance + if not isinstance(x, types.FunctionType): + raise TyperError("%r appears to be a method bound to %r, " + "but it is not a function" % ( + x, classdef)) + choice = MethodsPBCRepr + + elif isinstance(x, (type, types.ClassType)): + # classes + if x in userclasses: + # user classes choice = ClassesPBCRepr + elif type(x) is type and x.__module__ == '__builtin__': + # special case for built-in types, seen in faking + choice = getPyObjRepr + else: + raise TyperError("don't known about class %r" % (x,)) + + elif (classdef, x) in call_families: + # other kind of callable + if isinstance(x, types.FunctionType): + # function + choice = FunctionsPBCRepr elif isinstance(x, types.MethodType): + # prebuilt bound method choice = MethodOfFrozenPBCRepr else: raise TyperError("don't know about callable %r" % (x,)) + else: - # frozen object + # otherwise, just assume it's a plain frozen object choice = getFrozenPBCRepr - if cdefflag: - raise TyperError("unexpected classdef in PBC set %r" % ( - self.prebuiltinstances,)) choices[choice] = True if len(choices) > 1: @@ -63,6 +76,9 @@ # ____________________________________________________________ +def getPyObjRepr(rtyper, s_pbc): + return robject.pyobj_repr + def getFrozenPBCRepr(rtyper, s_pbc): if len(s_pbc.prebuiltinstances) <= 1: Modified: pypy/branch/dist-2.4.1/pypy/rpython/rstr.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rstr.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rstr.py Sun Jul 3 20:36:05 2005 @@ -26,6 +26,8 @@ STR = GcStruct('str', ('hash', Signed), ('chars', Array(Char))) +SIGNED_ARRAY = GcArray(Signed) + class __extend__(annmodel.SomeString): def rtyper_makerepr(self, rtyper): @@ -104,6 +106,18 @@ v_str, v_value = hop.inputargs(string_repr, string_repr) return hop.gendirectcall(ll_endswith, v_str, v_value) + def rtype_method_find(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_find, v_str, v_value) + + def rtype_method_upper(_, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_upper, v_str) + + def rtype_method_lower(_, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_lower, v_str) + def rtype_method_join(_, hop): r_lst = hop.args_r[1] s_item = r_lst.listitem.s_value @@ -556,8 +570,83 @@ return True +def ll_find(s1, s2): + """Knuth Morris Prath algorithm for substring match""" + len1 = len(s1.chars) + len2 = len(s2.chars) + # 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 ) + i = 0 + j = -1 + while i=0 and s2.chars[i] == s2.chars[j]: + j += 1 + T[i] = j + i += 1 + elif j>0: + j = T[j-1] + else: + T[i] = 0 + i += 1 + j = 0 + + # Now the find algorithm + i = 0 + m = 0 + while m+i0: + i = e + return -1 + emptystr = string_repr.convert_const("") +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: + ochar = ord(s_chars[i]) + if ochar >= 97 and ochar <= 122: + upperchar = ochar - 32 + else: + upperchar = ochar + result.chars[i] = chr(upperchar) + 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: + ochar = ord(s_chars[i]) + if ochar >= 65 and ochar <= 96: + lowerchar = ochar + 32 + else: + lowerchar = ochar + result.chars[i] = chr(lowerchar) + i += 1 + return result + def ll_join(s, items): s_chars = s.chars s_len = len(s_chars) Modified: pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py Sun Jul 3 20:36:05 2005 @@ -267,7 +267,8 @@ # in all generated operations. if hop.s_result.is_constant(): if isinstance(resultvar, Constant) and \ - isinstance(hop.r_result.lowleveltype, Primitive): + isinstance(hop.r_result.lowleveltype, Primitive) and \ + hop.r_result.lowleveltype != Void: assert resultvar.value == hop.s_result.const resulttype = resultvar.concretetype op.result.concretetype = hop.r_result.lowleveltype Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_lltype.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_lltype.py Sun Jul 3 20:36:05 2005 @@ -261,6 +261,10 @@ py.test.raises(TypeError, pf, 0, 0) py.test.raises(TypeError, pf, 'a') +def test_truargs(): + F = FuncType((Void, Signed, Void, Unsigned), Float) + assert Void not in F._trueargs() + def test_inconsistent_gc_containers(): A = GcArray(('y', Signed)) S = GcStruct('b', ('y', Signed)) Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rclass.py Sun Jul 3 20:36:05 2005 @@ -63,6 +63,16 @@ res = interpret(dummyfn, []) assert res == 6 +def test_prebuilt_instances_with_void(): + def marker(): + return 42 + a = EmptyBase() + a.nothing_special = marker + def dummyfn(): + return a.nothing_special() + res = interpret(dummyfn, []) + assert res == 42 + # method calls class A: def f(self): Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rconstantdict.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rconstantdict.py Sun Jul 3 20:36:05 2005 @@ -16,3 +16,12 @@ assert res is False res = interpret(func, [4]) assert res is True + +def test_constantdict_get(): + d = {1: -11, 4: -44, 16: -66} + def func(i, j): + return d.get(i, j) + res = interpret(func, [15, 62]) + assert res == 62 + res = interpret(func, [4, 25]) + assert res == -44 Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rpbc.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rpbc.py Sun Jul 3 20:36:05 2005 @@ -37,6 +37,10 @@ def m(self, x): return self.z - x +class MyStrangerSubclass(MyBase): + def m(self, x, y): + return x*y + def test_method_call(): def f(a, b): obj = MyBase() @@ -58,17 +62,51 @@ res = interpret(f, [-1, 2.3]) assert res == -3.3 +def test_stranger_subclass_1(): + def f1(): + obj = MyStrangerSubclass() + obj.z = 100 + return obj.m(6, 7) + res = interpret(f1, []) + assert res == 42 + +def test_stranger_subclass_2(): + def f2(): + obj = MyStrangerSubclass() + obj.z = 100 + return obj.m(6, 7) + MyBase.m(obj, 58) + res = interpret(f2, []) + assert res == 200 + class MyBaseWithInit: def __init__(self, a): self.a1 = a +class MySubclassWithInit(MyBaseWithInit): + def __init__(self, a, b): + MyBaseWithInit.__init__(self, a) + self.b1 = b + def test_class_init(): def f(a): instance = MyBaseWithInit(a) return instance.a1 assert interpret(f, [5]) == 5 +def test_class_init_2(): + def f(a, b): + instance = MySubclassWithInit(a, b) + return instance.a1 * instance.b1 + assert interpret(f, [6, 7]) == 42 + +def test_class_calling_init(): + def f(): + instance = MySubclassWithInit(1, 2) + instance.__init__(3, 4) + return instance.a1 * instance.b1 + assert interpret(f, []) == 12 + class Freezing: def _freeze_(self): Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py Sun Jul 3 20:36:05 2005 @@ -180,6 +180,32 @@ res = 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(6): + res = interpret(fn, [i,j]) + assert res == fn(i, j) + +def test_upper(): + def fn(i): + strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,'] + return strings[i].upper() + for i in range(5): + res = interpret(fn, [i]) + assert ''.join(res.chars) == fn(i) + +def test_lower(): + def fn(i): + strings = ['', ' ', 'lower', 'LoWeR', ',lowEr,'] + return strings[i].lower() + for i in range(5): + res = interpret(fn, [i]) + assert ''.join(res.chars) == fn(i) + def test_join(): res = interpret(lambda: ''.join([]), []) assert ''.join(res.chars) == "" Modified: pypy/branch/dist-2.4.1/pypy/tool/option.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/tool/option.py (original) +++ pypy/branch/dist-2.4.1/pypy/tool/option.py Sun Jul 3 20:36:05 2005 @@ -10,6 +10,11 @@ spaces = [] oldstyle = 0 uselibfile = 0 + useparsermodule = "cpython" # "cpython" / "recparser" / "parser" + parser = "cpython" # "cpython" / "pyparse" + compiler = "cpython" # "cpython" + # "pyparse" pypy parser, cpython compiler + # "pycomp" pypy parser and compiler (TBD) def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server @@ -28,7 +33,7 @@ options.append(make_option( '--oldstyle', action="store_true",dest="oldstyle", - help="enable oldstyle classes as default metaclass (std objspace only)")) + help="enable oldstyle classes as default metaclass (std objspace only)")) options.append(make_option( '--file', action="store_true",dest="uselibfile", help="enable our custom file implementation")) @@ -39,6 +44,13 @@ '-H', action="callback", callback=run_tb_server, help="use web browser for traceback info")) + options.append(make_option( + '--pyparse', action="store_const", dest="compiler", const="pyparse", + help="enable the internal pypy parser with CPython compiler")) + options.append(make_option( + '--parsermodule', action="store",type="string", dest="useparsermodule", + help="select the parser module to use", + metavar="[cpython|recparser|parser]")) return options @@ -67,7 +79,7 @@ except KeyError: module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) Space = module.Space - space = Space() + space = Space( Options() ) if name == 'std' and Options.oldstyle: space.enable_old_style_classes_as_default_metaclass() if Options.uselibfile: Modified: pypy/branch/dist-2.4.1/pypy/translator/backendoptimization.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/backendoptimization.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/backendoptimization.py Sun Jul 3 20:36:05 2005 @@ -1,9 +1,10 @@ import autopath from pypy.translator.translator import Translator from pypy.objspace.flow.model import Variable, Constant, Block, Link +from pypy.objspace.flow.model import SpaceOperation from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph from pypy.tool.unionfind import UnionFind - +from pypy.rpython.lltype import Void def remove_same_as(graph): """Remove all 'same_as' operations. @@ -41,6 +42,21 @@ traverse(visit, graph) +def remove_void(translator): + for func, graph in translator.flowgraphs.iteritems(): + args = [arg for arg in graph.startblock.inputargs + if arg.concretetype is not Void] + graph.startblock.inputargs = args + def visit(block): + if isinstance(block, Block): + for op in block.operations: + if op.opname == 'direct_call': + args = [arg for arg in op.args + if arg.concretetype is not Void] + op.args = args + for func, graph in translator.flowgraphs.iteritems(): + traverse(visit, graph) + def SSI_to_SSA(graph): """Rename the variables in a flow graph as much as possible without violating the SSA rule. 'SSI' means that each Variable in a flow graph is Modified: pypy/branch/dist-2.4.1/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/goal/translate_pypy.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/goal/translate_pypy.py Sun Jul 3 20:36:05 2005 @@ -25,6 +25,8 @@ -no-d Disable recording of debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed + -no-snapshot + Don't redirect imports to the translation snapshot -save filename saves the translator to a file. The file type can either be .py or .zip (recommended). @@ -34,32 +36,33 @@ """ import autopath, sys, os -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -basedir = autopath.this_dir +if '-no-snapshot' not in sys.argv: + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + basedir = autopath.this_dir -pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') + pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') -if not os.path.isdir(pypy_translation_snapshot_dir): - print """ -Translation is performed on a specific revision of PyPy which lives on -a branch. This needs to be checked out into translator/goal with: + if not os.path.isdir(pypy_translation_snapshot_dir): + print """ + Translation is performed on a specific revision of PyPy which lives on + a branch. This needs to be checked out into translator/goal with: -svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot -"""[1:] - sys.exit(2) + svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot + """[1:] + sys.exit(2) -# override imports from pypy head with imports from pypy-translation-snapshot -import pypy -pypy.__path__.insert(0, pypy_translation_snapshot_dir) + # override imports from pypy head with imports from pypy-translation-snapshot + import pypy + pypy.__path__.insert(0, pypy_translation_snapshot_dir) -# complement imports from pypy.objspace (from pypy-translation-snapshot) -# with pypy head objspace/ -import pypy.objspace -pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) + # complement imports from pypy.objspace (from pypy-translation-snapshot) + # with pypy head objspace/ + import pypy.objspace + pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) -print "imports redirected to pypy-translation-snapshot." + print "imports redirected to pypy-translation-snapshot." -# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx import threading, pdb @@ -77,6 +80,7 @@ from pypy.translator.tool import buildpyxmodule buildpyxmodule.enable_fast_compilation() +annmodel.DEBUG = False @@ -258,6 +262,7 @@ '-no-o': False, '-tcc': False, '-no-d': False, + '-no-snapshot' : False, '-load': False, '-save': False, '-fork': False, Modified: pypy/branch/dist-2.4.1/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/goal/unixcheckpoint.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/goal/unixcheckpoint.py Sun Jul 3 20:36:05 2005 @@ -6,8 +6,8 @@ print '---> Checkpoint: run / quit / pdb ?' try: line = raw_input().strip().lower() - except KeyboardInterrupt: - print '(KeyboardInterrupt ignored)' + except (KeyboardInterrupt, EOFError), e: + print '(%s ignored)' % e.__class__.__name__ continue if line == 'run': break Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py Sun Jul 3 20:36:05 2005 @@ -12,6 +12,7 @@ from pypy.translator.pyrex.genpyrex import GenPyrex from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture +from pypy.translator.llvm2.genllvm import use_boehm_gc debug = True @@ -20,6 +21,22 @@ OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline" +def compile_module(module, source_files, object_files, library_files): + open("%s_setup.py" % module, "w").write(str(py.code.Source( + ''' + from distutils.core import setup + from distutils.extension import Extension + setup(name="%(module)s", + ext_modules = [Extension( + name = "%(module)s", + sources = %(source_files)s, + libraries = %(library_files)s, + extra_objects = %(object_files)s)]) + ''' % locals()))) + cmd = "python %s_setup.py build_ext --inplace" % module + if debug: print cmd + cmdexec(cmd) + def make_module_from_llvm(llvmfile, pyxfile, optimize=False): include_dir = py.magic.autopath().dirpath() dirpath = llvmfile.dirpath() @@ -27,29 +44,32 @@ os.chdir(str(dirpath)) modname = pyxfile.purebasename b = llvmfile.purebasename + source_files = [ "%s.c" % modname ] + object_files = [] + library_files = [] + if use_boehm_gc: + library_files.append('gc') if sys.maxint == 2147483647: #32 bit platform if optimize: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), - "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b), - "as %s.s -o %s.o" % (b, b)] + "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b)] else: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), - "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b), - "as %s.s -o %s.o" % (b, b)] - ops2 = ["gcc -c -shared -I/usr/include/python2.3 %s.c" % pyxfile.purebasename, - "gcc -shared %s.o %s.o -o %s.so" % (b, modname, modname)] + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b)] + cmds.append("as %s.s -o %s.o" % (b, b)) + object_files.append("%s.o" % b) else: #assume 64 bit platform (x86-64?) #this special case for x86-64 (called ia64 in llvm) can go as soon as llc supports ia64 assembly output! if optimize: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), "llc -enable-correct-eh-support %s_optimized.bc -march=c -f -o %s.c" % (b, b)] else: - ops1 = ["llvm-as %s.ll -f -o %s.bc" % (b, b), + cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "llc -enable-correct-eh-support %s.bc -march=c -f -o %s.c" % (b, b)] - ops2 = ["gcc -shared -fPIC -I/usr/include/python2.3 %s.c %s.c -o %s.so" % (b, modname, modname)] + source_files.append("%s.c" % b) try: if debug: print "modname", modname @@ -57,13 +77,11 @@ if debug: print "working in", path.local() try: try: - for op in ops1: - if debug: print op - cmdexec(op) + for cmd in cmds: + if debug: print cmd + cmdexec(cmd) make_c_from_pyxfile(pyxfile) - for op in ops2: - if debug: print op - cmdexec(op) + compile_module(modname, source_files, object_files, library_files) finally: foutput, foutput = c.done() except: Deleted: /pypy/branch/dist-2.4.1/pypy/translator/llvm2/cfgtransform.py ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/translator/llvm2/cfgtransform.py Sun Jul 3 20:36:05 2005 +++ (empty file) @@ -1,44 +0,0 @@ -from pypy.objspace.flow.model import traverse, Block, checkgraph -from pypy.translator.unsimplify import remove_double_links - - -def remove_same_as(graph): - same_as_positions = [] - def visit(node): - if isinstance(node, Block): - for i, op in enumerate(node.operations): - if op.opname == 'same_as': - same_as_positions.append((node, i)) - traverse(visit, graph) - while same_as_positions: - block, index = same_as_positions.pop() - same_as_result = block.operations[index].result - same_as_arg = block.operations[index].args[0] - # replace the new variable (same_as_result) with the old variable - # (from all subsequent positions) - for op in block.operations[index:]: - if op is not None: - for i in range(len(op.args)): - if op.args[i] == same_as_result: - op.args[i] = same_as_arg - for link in block.exits: - for i in range(len(link.args)): - if link.args[i] == same_as_result: - link.args[i] = same_as_arg - if block.exitswitch == same_as_result: - block.exitswitch = same_as_arg - block.operations[index] = None - - # remove all same_as operations - def visit(node): - if isinstance(node, Block) and node.operations: - node.operations[:] = filter(None, node.operations) - traverse(visit, graph) - checkgraph(graph) - - -def prepare_graph(graph, translator): - remove_same_as(graph) - remove_double_links(translator, graph) - return graph - Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py Sun Jul 3 20:36:05 2005 @@ -1,25 +1,48 @@ import py +from itertools import count from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.codewriter +show_line_numbers = True +count = count().next class CodeWriter(object): def __init__(self): self._lines = [] + self.append('declare sbyte* %GC_malloc(uint)') def append(self, line): + if show_line_numbers: + line = "%-75s; %d" % (line, len(self._lines) + 1) self._lines.append(line) log(line) + def comment(self, line): + self.append(";; " + line) + + def newline(self): + self.append("") + def indent(self, line): self.append(" " + line) def label(self, name): self.append(" %s:" % name) + def globalinstance(self, name, type, data): + self.append("%s = internal constant %s {%s}" % (name, type, data)) + def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) + def arraydef(self, name, typerepr): + self.append("%s = type { int, [0 x %s] }" % (name, typerepr)) + + def funcdef(self, name, rettyperepr, argtypereprs): + self.append("%s = type %s (%s)" % (name, rettyperepr, + ", ".join(argtypereprs))) + def declare(self, decl): self.append("declare %s" %(decl,)) @@ -42,7 +65,10 @@ self.append("}") def ret(self, type_, ref): - self.indent("ret %s %s" % (type_, ref)) + self.indent("ret %s %s" % (type_, ref)) + + def ret_void(self): + self.indent("ret void") def phi(self, targetvar, type_, refs, blocknames): assert targetvar.startswith('%') @@ -60,16 +86,28 @@ self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref, ", ".join(arglist))) + def call_void(self, functionref, argrefs, argtypes): + arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] + self.indent("call void %s(%s)" % (functionref, ", ".join(arglist))) + def cast(self, targetvar, fromtype, fromvar, targettype): self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) - def malloc(self, targetvar, type): - self.indent("%(targetvar)s = malloc %(type)s" % locals()) - - def getelementptr(self, targetvar, type, typevar, index): - self.indent("%(targetvar)s = getelementptr " - "%(type)s %(typevar)s, int 0, uint %(index)s" % locals()) + def malloc(self, targetvar, type_, size=1): + if use_boehm_gc: + cnt = count() + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)d" % locals()) + self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc(uint %%malloc.SizeU.%(cnt)d)" % locals()) + self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) + else: + self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) + + def getelementptr(self, targetvar, type, typevar, *indices): + res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals() + res += ", ".join(["%s %s" % (t, i) for t, i in indices]) + self.indent(res) def load(self, targetvar, targettype, ptr): self.indent("%(targetvar)s = load %(targettype)s* %(ptr)s" % locals()) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py Sun Jul 3 20:36:05 2005 @@ -1,21 +1,60 @@ from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.funcnode import FuncNode -from pypy.translator.llvm2.structnode import StructNode +from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode +from pypy.translator.llvm2.structnode import StructNode, StructTypeNode, StructVarsizeTypeNode +from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable log = log.database PRIMITIVES_TO_LLVM = {lltype.Signed: "int", - lltype.Bool: "bool"} + lltype.Char: "sbyte", + lltype.Unsigned: "uint", + lltype.Bool: "bool", + lltype.Float: "double", + lltype.Void: "void"} + +class NormalizingDict(object): + """ this is a helper dict for obj2node in order + to allow saner key-unification for Ptrs to functions + (and possibly other stuff in the future) + """ + def __init__(self): + self._dict = {} + def __repr__(self): + return repr(self._dict) + def dump(self): + for x,y in self._dict.items(): + print x, y + def _get(self, key): + if isinstance(key, Constant): + if isinstance(key.value, lltype._ptr): + key = key.value._obj + return key + def __getitem__(self, key): + key = self._get(key) + return self._dict[key] + def __contains__(self, key): + key = self._get(key) + return key in self._dict + def __setitem__(self, key, value): + key = self._get(key) + self._dict[key] = value + def __delitem__(self, key): + key = self._get(key) + del self._dict[key] + def values(self): + return self._dict.values() + def items(self): + return self._dict.items() class Database(object): def __init__(self, translator): self._translator = translator - self.obj2node = {} + self.obj2node = NormalizingDict() self._pendingsetup = [] self._tmpcount = 1 - + def addpending(self, key, node): assert key not in self.obj2node, ( "node with key %r already known!" %(key,)) @@ -24,16 +63,40 @@ self._pendingsetup.append(node) def prepare_repr_arg(self, const_or_var): + """if const_or_var is not already in a dictionary self.obj2node, + the appropriate node gets constructed and gets added to + self._pendingsetup and to self.obj2node""" if const_or_var in self.obj2node: return if isinstance(const_or_var, Constant): - if isinstance(const_or_var.concretetype, lltype.Primitive): - pass - #log.prepare(const_or_var, "(is primitive)") + + ct = const_or_var.concretetype + while isinstance(ct, lltype.Ptr): + ct = ct.TO + + if isinstance(ct, lltype.FuncType): + self.addpending(const_or_var, FuncNode(self, const_or_var)) else: - self.addpending(const_or_var, FuncNode(self, const_or_var)) + value = const_or_var.value + while hasattr(value, "_obj"): + value = value._obj + + if isinstance(ct, lltype.Struct): + self.addpending(const_or_var, StructNode(self, value)) + + elif isinstance(ct, lltype.Array): + self.addpending(const_or_var, ArrayNode(self, value)) + + elif isinstance(ct, lltype.Primitive): + log.prepare(const_or_var, "(is primitive)") + else: + log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var)) else: - log.prepare.ignore(const_or_var) + log.prepare(const_or_var, type(const_or_var)) #XXX dont checkin + + def prepare_repr_arg_multi(self, args): + for const_or_var in args: + self.prepare_repr_arg(const_or_var) def prepare_repr_arg_type(self, type_): if type_ in self.obj2node: @@ -42,24 +105,47 @@ pass elif isinstance(type_, lltype.Ptr): self.prepare_repr_arg_type(type_.TO) - elif isinstance(type_, lltype.Struct): - self.addpending(type_, StructNode(self, type_)) + + elif isinstance(type_, lltype.Struct): + if type_._arrayfld: + self.addpending(type_, StructVarsizeTypeNode(self, type_)) + else: + self.addpending(type_, StructTypeNode(self, type_)) + elif isinstance(type_, lltype.FuncType): + self.addpending(type_, FuncTypeNode(self, type_)) + + elif isinstance(type_, lltype.Array): + self.addpending(type_, ArrayTypeNode(self, type_)) + else: log.XXX("need to prepare typerepr", type_) + def prepare_repr_arg_type_multi(self, types): + for type_ in types: + self.prepare_repr_arg_type(type_) + def prepare_arg(self, const_or_var): log.prepare(const_or_var) - self.prepare_repr_arg(const_or_var) self.prepare_repr_arg_type(const_or_var.concretetype) + self.prepare_repr_arg(const_or_var) - def process(self): - if self._pendingsetup: - self._pendingsetup.pop().setup() - return bool(self._pendingsetup) - - def getobjects(self): - return self.obj2node.values() + def setup_all(self): + while self._pendingsetup: + x = self._pendingsetup.pop() + log.setup_all(x) + x.setup() + + def getobjects(self, subset_types=None): + res = [] + for v in self.obj2node.values(): + if subset_types is None or isinstance(v, subset_types): + res.append(v) + return res + + # __________________________________________________________ + # Representing variables and constants in LLVM source code + def repr_arg(self, arg): if (isinstance(arg, Constant) and isinstance(arg.concretetype, lltype.Primitive)): @@ -91,5 +177,3 @@ count = self._tmpcount self._tmpcount += 1 return "%tmp." + str(count) - - \ No newline at end of file Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py Sun Jul 3 20:36:05 2005 @@ -2,19 +2,49 @@ from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.objspace.flow.model import flatten, mkentrymap, traverse from pypy.rpython import lltype -from pypy.translator.llvm2.cfgtransform import prepare_graph +from pypy.translator.backendoptimization import remove_same_as +from pypy.translator.unsimplify import remove_double_links +from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.log import log log = log.funcnode -class FuncNode(object): + +class FuncTypeNode(LLVMNode): + func_type_node_counter = 0 + + def __init__(self, db, type_): + self.db = db + assert isinstance(type_, lltype.FuncType) + self.type_ = type_ + ref = '"ft.%s.%s"' % (type_, FuncTypeNode.func_type_node_counter) + self.ref = ref.replace(" ", "") + FuncTypeNode.func_type_node_counter += 1 + + def __str__(self): + return "" % self.ref + + def setup(self): + self.db.prepare_repr_arg_type(self.type_.RESULT) + self.db.prepare_repr_arg_type_multi(self.type_._trueargs()) + + def writedatatypedecl(self, codewriter): + returntype = self.db.repr_arg_type(self.type_.RESULT) + inputargtypes = self.db.repr_arg_type_multi(self.type_._trueargs()) + decl = "%s type %s (%s)*" % (self.ref, returntype, + ", ".join(inputargtypes)) + codewriter.funcdef(self.ref, returntype, inputargtypes) + + +class FuncNode(LLVMNode): _issetup = False def __init__(self, db, const_ptr_func): self.db = db self.ref = "%" + const_ptr_func.value._obj._name - self.graph = prepare_graph(const_ptr_func.value._obj.graph, - db._translator) - + self.graph = const_ptr_func.value._obj.graph + remove_same_as(self.graph) + remove_double_links(self.db._translator, self.graph) + def __str__(self): return "" %(self.ref,) @@ -28,21 +58,9 @@ for op in node.operations: map(self.db.prepare_arg, op.args) self.db.prepare_arg(op.result) + assert self.graph, "cannot traverse" traverse(visit, self.graph) self._issetup = True - - def getdecl(self): - assert self._issetup - startblock = self.graph.startblock - returnblock = self.graph.returnblock - inputargs = self.db.repr_arg_multi(startblock.inputargs) - inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) - returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) - result = "%s %s" % (returntype, self.ref) - args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] - result += "(%s)" % ", ".join(args) - return result - # ______________________________________________________________________ # main entry points from genllvm def writedecl(self, codewriter): @@ -72,6 +90,18 @@ # ______________________________________________________________________ # writing helpers for entry points + def getdecl(self): + assert self._issetup + startblock = self.graph.startblock + returnblock = self.graph.returnblock + inputargs = self.db.repr_arg_multi(startblock.inputargs) + inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) + returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) + result = "%s %s" % (returntype, self.ref) + args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] + result += "(%s)" % ", ".join(args) + return result + def write_block(self, codewriter, block): self.write_block_phi_nodes(codewriter, block) self.write_block_operations(codewriter, block) @@ -87,7 +117,8 @@ names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] - codewriter.phi(arg, type_, names, blocknames) + if type_ != "void": + codewriter.phi(arg, type_, names, blocknames) def write_block_branches(self, codewriter, block): if len(block.exits) == 1: @@ -100,11 +131,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: - meth = getattr(opwriter, op.opname, None) - assert meth is not None, "operation %r not found" %(op.opname,) - meth(op) - - + opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) self.write_block_branches(codewriter, block) @@ -114,54 +141,71 @@ self.write_block_phi_nodes(codewriter, block) inputargtype = self.db.repr_arg_type(block.inputargs[0]) inputarg = self.db.repr_arg(block.inputargs[0]) - codewriter.ret(inputargtype, inputarg) + if inputargtype != "void": + codewriter.ret(inputargtype, inputarg) + else: + codewriter.ret_void() class OpWriter(object): + binary_operations = {'int_mul': 'mul', + 'int_add': 'add', + 'int_sub': 'sub', + 'int_floordiv': 'div', + 'int_mod': 'rem', + 'int_lt': 'setlt', + 'int_le': 'setle', + 'int_eq': 'seteq', + 'int_ne': 'setne', + 'int_ge': 'setge', + 'int_gt': 'setgt', + + 'uint_mul': 'mul', + 'uint_add': 'add', + 'uint_sub': 'sub', + 'uint_floordiv': 'div', + 'uint_mod': 'rem', + 'uint_lt': 'setlt', + 'uint_le': 'setle', + 'uint_eq': 'seteq', + 'uint_ne': 'setne', + 'uint_ge': 'setge', + 'uint_gt': 'setgt', + + 'float_mul': 'mul', + 'float_add': 'add', + 'float_sub': 'sub', + 'float_truediv': 'div', + 'float_mod': 'rem', + 'float_lt': 'setlt', + 'float_le': 'setle', + 'float_eq': 'seteq', + 'float_ne': 'setne', + 'float_ge': 'setge', + 'float_gt': 'setgt', + } + def __init__(self, db, codewriter): self.db = db self.codewriter = codewriter - def binaryop(self, name, op): + def write_operation(self, op): + if op.opname in self.binary_operations: + self.binaryop(op) + else: + meth = getattr(self, op.opname, None) + assert meth is not None, "operation %r not found" %(op.opname,) + meth(op) + + def binaryop(self, op): + name = self.binary_operations[op.opname] assert len(op.args) == 2 self.codewriter.binaryop(name, self.db.repr_arg(op.result), self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), self.db.repr_arg(op.args[1])) - def int_mul(self, op): - self.binaryop('mul', op) - - def int_floordiv(self, op): - self.binaryop('div', op) - - def int_add(self, op): - self.binaryop('add', op) - - def int_sub(self, op): - self.binaryop('sub', op) - def int_mod(self, op): - self.binaryop('rem', op) - - def int_eq(self, op): - self.binaryop('seteq', op) - - def int_ne(self, op): - self.binaryop('setne', op) - - def int_lt(self, op): - self.binaryop('setlt', op) - - def int_le(self, op): - self.binaryop('setle', op) - - def int_gt(self, op): - self.binaryop('setgt', op) - - def int_ge(self, op): - self.binaryop('setge', op) - - def cast_bool_to_int(self, op): + def cast_primitive(self, op): #works for all primitives assert len(op.args) == 1 targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) @@ -169,7 +213,24 @@ fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) - int_is_true = cast_bool_to_int + cast_bool_to_int = cast_primitive + cast_bool_to_uint = uint_is_true = cast_primitive + + def int_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0") + + uint_is_true = int_is_true + + def float_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0.0") def direct_call(self, op): assert len(op.args) >= 1 @@ -178,8 +239,11 @@ functionref = self.db.repr_arg(op.args[0]) argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - self.codewriter.call(targetvar, returntype, functionref, argrefs, - argtypes) + if returntype != "void": + self.codewriter.call(targetvar, returntype, functionref, argrefs, + argtypes) + else: + self.codewriter.call_void(functionref, argrefs, argtypes) def malloc(self, op): targetvar = self.db.repr_arg(op.result) @@ -190,17 +254,38 @@ type = self.db.obj2node[arg.value].ref self.codewriter.malloc(targetvar, type) + def malloc_varsize(self, op): + targetvar = self.db.repr_arg(op.result) + arg_type = op.args[0] + assert (isinstance(arg_type, Constant) and + isinstance(arg_type.value, lltype.Array)) + #XXX unclean + struct_type = self.db.obj2node[arg_type.value].ref + struct_cons = self.db.obj2node[arg_type.value].constructor_ref + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) + self.codewriter.call(targetvar, struct_type + "*", struct_cons, + argrefs, argtypes) + def getfield(self, op): tmpvar = self.db.repr_tmpvar() - type = self.db.repr_arg_type(op.args[0]) - typevar = self.db.repr_arg(op.args[0]) + typ = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, type, typevar, index) - + self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) + targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - self.codewriter.load(targetvar, targettype, tmpvar) + assert targettype != "void" + #XXX This doesnt work - yet + #if isinstance(op.result.concretetype, lltype.Ptr): + # self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + #else: + # Moving to correct result variable + #self.codewriter.load(targetvar, targettype, tmpvar) + self.codewriter.load(targetvar, targettype, tmpvar) + getsubstruct = getfield def setfield(self, op): tmpvar = self.db.repr_tmpvar() @@ -208,8 +293,51 @@ typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, type, typevar, index) + self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index)) + valuevar = self.db.repr_arg(op.args[2]) + valuetype = self.db.repr_arg_type(op.args[2]) + assert valuetype != "void" + self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarrayitem(self, op): + var = self.db.repr_arg(op.args[0]) + vartype = self.db.repr_arg_type(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, vartype, var, + ("uint", 1), (indextype, index)) + + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + + # Ditto see getfield + if not isinstance(op.result.concretetype, lltype.Ptr): + self.codewriter.load(targetvar, targettype, tmpvar) + else: + # XXX noop + self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + + def setarrayitem(self, op): + array = self.db.repr_arg(op.args[0]) + arraytype = self.db.repr_arg_type(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarraysize(self, op): + var = self.db.repr_arg(op.args[0]) + vartype = self.db.repr_arg_type(op.args[0]) + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 0)) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + self.codewriter.load(targetvar, targettype, tmpvar) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py Sun Jul 3 20:36:05 2005 @@ -1,3 +1,6 @@ +from os.path import exists +use_boehm_gc = exists('/usr/lib/libgc.so') + import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database @@ -8,8 +11,10 @@ from pypy.rpython import lltype from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter +from pypy.translator.backendoptimization import remove_void def genllvm(translator): + remove_void(translator) func = translator.entrypoint db = Database(translator) @@ -17,18 +22,31 @@ c = inputconst(lltype.typeOf(ptr), ptr) db.prepare_repr_arg(c) assert c in db.obj2node - while db.process(): - pass + db.setup_all() entrynode = db.obj2node[c] codewriter = CodeWriter() - dbobjects = db.getobjects() - log.debug(dbobjects) - log.debug(db.obj2node) - for node in dbobjects: - node.writedecl(codewriter) - codewriter.startimpl() - for node in dbobjects: - node.writeimpl(codewriter) + comment = codewriter.comment + nl = codewriter.newline + + nl(); comment("Type Declarations"); nl() + for typ_decl in db.getobjects(): + typ_decl.writedatatypedecl(codewriter) + + nl(); comment("Global Data") ; nl() + for typ_decl in db.getobjects(): + typ_decl.writeglobalconstants(codewriter) + + nl(); comment("Function Prototypes") ; nl() + for typ_decl in db.getobjects(): + typ_decl.writedecl(codewriter) + + #import pdb ; pdb.set_trace() + nl(); comment("Function Implementation") + codewriter.startimpl() + for typ_decl in db.getobjects(): + typ_decl.writeimpl(codewriter) + + comment("End of file") ; nl() targetdir = udir llvmsource = targetdir.join(func.func_name).new(ext='.ll') Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py Sun Jul 3 20:36:05 2005 @@ -3,7 +3,11 @@ log = log.pyrex PRIMITIVES_TO_C = {lltype.Signed: "int", - lltype.Bool: "char"} + lltype.Unsigned: "unsigned int", + lltype.Bool: "char", + lltype.Float: "double", + lltype.Char: "char", + } def write_pyx_wrapper(funcgen, targetpath): def c_declaration(): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py Sun Jul 3 20:36:05 2005 @@ -1,36 +1,125 @@ import py from pypy.objspace.flow.model import Block, Constant, Variable, Link -from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.node import LLVMNode +from pypy.rpython import lltype + log = log.structnode -class StructNode(object): +class StructTypeNode(LLVMNode): _issetup = False struct_counter = 0 def __init__(self, db, struct): + assert isinstance(struct, lltype.Struct) self.db = db - self.struct = struct - self.ref = "%%st.%s.%s" % (struct._name, StructNode.struct_counter) - StructNode.struct_counter += 1 + self.struct = struct + self.name = "%s.%s" % (self.struct._name, StructTypeNode.struct_counter) + self.ref = "%%st.%s" % self.name + StructTypeNode.struct_counter += 1 def __str__(self): - return "" %(self.ref,) + return "" %(self.ref,) def setup(self): - log.XXX("setup", self) + # Recurse + for field in self.struct._flds: + self.db.prepare_repr_arg_type(field) self._issetup = True # ______________________________________________________________________ - # entry points from genllvm - # - def writedecl(self, codewriter): + # main entry points from genllvm + + def writedatatypedecl(self, codewriter): assert self._issetup - struct = self.struct - l = [] - for fieldname in struct._names: - type_ = getattr(struct, fieldname) - l.append(self.db.repr_arg_type(type_)) - codewriter.structdef(self.ref, l) + fields = [getattr(self.struct, name) for name in self.struct._names_without_voids()] + l = [self.db.repr_arg_type(field) for field in fields] + codewriter.structdef(self.ref, l) + +class StructVarsizeTypeNode(StructTypeNode): + + def __init__(self, db, struct): + super(StructVarsizeTypeNode, self).__init__(db, struct) + new_var_name = "%%new.st.var.%s" % self.name + self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + + def writedecl(self, codewriter): + # declaration for constructor + codewriter.declare(self.constructor_name) def writeimpl(self, codewriter): - assert self._issetup + log.writeimpl(self.ref) + codewriter.openfunc(self.constructor_name) + codewriter.label("block0") + indices_to_array = [("int", 0)] + s = self.struct + while isintance(s, lltypes.Struct): + last_pos = len(self.struct._names_without_voids()) - 1 + indices_to_array.append(("uint", last_pos)) + s = s._flds.values()[-1] + + # Into array and length + indices = indices_to_array + [("uint", 1), ("int", "%len")] + codewriter.getelementptr("%size", self.ref + "*", + "null", *indices) + + #XXX is this ok for 64bit? + codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") + codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") + codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") + + # remember the allocated length for later use. + indices = indices_to_array + [("uint", 0)] + codewriter.getelementptr("%size_ptr", self.ref + "*", + "%result", *indices) + + codewriter.cast("%signedsize", "uint", "%sizeu", "int") + codewriter.store("int", "%signedsize", "%size_ptr") + + codewriter.ret(self.ref + "*", "%result") + codewriter.closefunc() + +class StructNode(LLVMNode): + _issetup = False + struct_counter = 0 + + def __init__(self, db, value): + self.db = db + self.name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) + self.ref = "%%stinstance.%s" % self.name + self.value = value + StructNode.struct_counter += 1 + + def __str__(self): + return "" %(self.ref,) + + def setup(self): + for name in self.value._TYPE._names_without_voids(): + T = self.value._TYPE._flds[name] + assert T is not lltype.Void + if not isinstance(T, lltype.Primitive): + value = getattr(self.value, name) + # Create a dummy constant hack XXX + c = Constant(value, T) + self.db.prepare_arg(c) + + self._issetup = True + + def get_values(self): + res = [] + for name in self.value._TYPE._names_without_voids(): + T = self.value._TYPE._flds[name] + value = getattr(self.value, name) + if not isinstance(T, lltype.Primitive): + # Create a dummy constant hack XXX + value = self.db.repr_arg(Constant(value, T)) + else: + value = str(value) + res.append((self.db.repr_arg_type(T), value)) + return ", ".join(["%s %s" % (t, v) for t, v in res]) + + def writeglobalconstants(self, codewriter): + codewriter.globalinstance(self.ref, + self.db.repr_arg_type(self.value._TYPE), + self.get_values()) + Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 20:36:05 2005 @@ -5,10 +5,12 @@ from pypy.translator.translator import Translator from pypy.translator.llvm2.genllvm import genllvm +from pypy.translator.llvm2.genllvm import use_boehm_gc from pypy.translator.llvm2.test import llvmsnippet from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rarithmetic import r_uint py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) @@ -17,13 +19,32 @@ ## def setup_module(mod): ## mod.llvm_found = is_on_path("llvm-as") -def compile_function(function, annotate): +def compile_function(function, annotate, view=False): t = Translator(function) a = t.annotate(annotate) t.specialize() a.simplify() + if view: + t.view() return genllvm(t) +def test_GC_malloc(): + if not use_boehm_gc: + py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") + return + py.test.skip("test_GC_malloc skipped because test not yet correct (Boehm collector IS used anyway)") + return + def tuple_getitem(n): + x = 0 + i = 0 + while i < n: + l = (1,2,i,234,23,23,23,234,234,234,234) + x += l[2] + i += 1 + return x + f = compile_function(tuple_getitem, [int]) + t = 1024*1024*100 + f(t) #assert f(t) == t def test_return1(): def simple1(): @@ -31,6 +52,20 @@ f = compile_function(simple1, []) assert f() == 1 +def Xtest_simple_function_pointer(): + def f1(x): + return x + 1 + def f2(x): + return x + 2 + + l = [f1, f2] + + def pointersimple(i): + return l[i] + + f = compile_function(pointersimple, [int]) + assert f + def test_simple_branching(): def simple5(b): if b: @@ -59,6 +94,91 @@ assert f(1) == 1 assert f(2) == 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_uint_ops(): + def ops(i): + x = r_uint(0) + x += i < i + x += i <= i + x += i == i + x += i != i + x += i >= i + x += i > i + x += x % i + #x += i is not None + #x += i is None + return i + 1 * i // i - 1 + f = compile_function(ops, [r_uint]) + assert f(1) == 1 + assert f(2) == 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 += flt fs not None + #x += flt is None + return flt + 1 * flt / flt - 1 + f = compile_function(ops, [float]) + assert f(1) == 1 + assert f(2) == 2 + + def test_function_call(): def callee(): return 1 @@ -76,7 +196,7 @@ if m == 0: return ackermann(n - 1, 1) return ackermann(n - 1, ackermann(n, m - 1)) - f = compile_function(call_ackermann, [int, int]) + f = compile_function(call_ackermann, [int, int], view=False) assert f(0, 2) == 3 def test_tuple_getitem(): @@ -86,9 +206,89 @@ f = compile_function(tuple_getitem, [int]) assert f(1) == 2 -def test_nested_tuple(): +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 + assert f(4) == 4 + +def test_pbc_fns(): + 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 DONOT_test_simple_chars(): + 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(): + 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_basic_ops(): + 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 Xtest_string_getitem1(): + l = "Hello, World" + def string_test(i): + return l[i] + f = compile_function(string_test, [int], view=True) + assert f(0) == ord("H") + +def DONOT_test_string_getitem2(): + def string_test(i): + l = "Hello, World" + return l[i] + f = compile_function(string_test, [int]) + assert f(0) == ord("H") + +class TestException(Exception): + pass + +def DONOTtest_exception(): + def raise_(i): + if i: + raise TestException() + else: + return 1 + def catch(i): + try: + return raise_(i) + except TestException: + return 0 + f = compile_function(catch, [int]) Modified: pypy/branch/dist-2.4.1/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/tool/pygame/drawgraph.py Sun Jul 3 20:36:05 2005 @@ -116,56 +116,77 @@ rest = rest[3:] self.style, self.color = rest self.highlight = False + self.cachedbezierpoints = None + self.cachedarrowhead = None + self.cachedlimits = None def sethighlight(self, which): self.highlight = bool(which) - def bezierpoints(self, resolution=8): - result = [] - pts = self.points - for i in range(0, len(pts)-3, 3): - result += beziercurve(pts[i], pts[i+1], - pts[i+2], pts[i+3], resolution) + def limits(self): + result = self.cachedlimits + if result is None: + points = self.bezierpoints() + xs = [point[0] for point in points] + ys = [point[1] for point in points] + self.cachedlimits = result = (min(xs), max(ys), max(xs), min(ys)) + return result + + def bezierpoints(self): + result = self.cachedbezierpoints + if result is None: + result = [] + pts = self.points + for i in range(0, len(pts)-3, 3): + result += beziercurve(pts[i], pts[i+1], pts[i+2], pts[i+3]) + self.cachedbezierpoints = result return result def arrowhead(self): - bottom_up = self.points[0][1] > self.points[-1][1] - if (self.tail.y > self.head.y) != bottom_up: # reversed edge - head = 0 - dir = 1 - else: - head = -1 - dir = -1 - n = 1 - while True: - try: - x0, y0 = self.points[head] - x1, y1 = self.points[head+n*dir] - except IndexError: - return [] - vx = x0-x1 - vy = y0-y1 - try: - f = 0.12 / math.sqrt(vx*vx + vy*vy) - vx *= f - vy *= f - return [(x0 + 0.9*vx, y0 + 0.9*vy), - (x0 + 0.4*vy, y0 - 0.4*vx), - (x0 - 0.4*vy, y0 + 0.4*vx)] - except (ZeroDivisionError, ValueError): - n += 1 + result = self.cachedarrowhead + if result is None: + bottom_up = self.points[0][1] > self.points[-1][1] + if (self.tail.y > self.head.y) != bottom_up: # reversed edge + head = 0 + dir = 1 + else: + head = -1 + dir = -1 + n = 1 + while True: + try: + x0, y0 = self.points[head] + x1, y1 = self.points[head+n*dir] + except IndexError: + result = [] + break + vx = x0-x1 + vy = y0-y1 + try: + f = 0.12 / math.sqrt(vx*vx + vy*vy) + vx *= f + vy *= f + result = [(x0 + 0.9*vx, y0 + 0.9*vy), + (x0 + 0.4*vy, y0 - 0.4*vx), + (x0 - 0.4*vy, y0 + 0.4*vx)] + break + except (ZeroDivisionError, ValueError): + n += 1 + self.cachedarrowhead = result + return result def beziercurve((x0,y0), (x1,y1), (x2,y2), (x3,y3), resolution=8): result = [] f = 1.0/(resolution-1) + append = result.append for i in range(resolution): t = f*i t0 = (1-t)*(1-t)*(1-t) t1 = t *(1-t)*(1-t) * 3.0 t2 = t * t *(1-t) * 3.0 t3 = t * t * t - result.append((x0*t0 + x1*t1 + x2*t2 + x3*t3, - y0*t0 + y1*t1 + y2*t2 + y3*t3)) + append((x0*t0 + x1*t1 + x2*t2 + x3*t3, + y0*t0 + y1*t1 + y2*t2 + y3*t3)) return result def segmentdistance((x0,y0), (x1,y1), (x,y)): @@ -173,16 +194,16 @@ vx = x1-x0 vy = y1-y0 try: - l = math.sqrt(vx*vx+vy*vy) + l = math.hypot(vx, vy) vx /= l vy /= l dlong = vx*(x-x0) + vy*(y-y0) except (ZeroDivisionError, ValueError): dlong = -1 if dlong < 0.0: - return math.sqrt((x-x0)*(x-x0) + (y-y0)*(y-y0)) + return math.hypot(x-x0, y-y0) elif dlong > l: - return math.sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1)) + return math.hypot(x-x1, y-y1) else: return abs(vy*(x-x0) - vx*(y-y0)) @@ -209,6 +230,8 @@ self.textzones = [] self.highlightwords = graphlayout.links self.highlight_word = None + self.visiblenodes = [] + self.visibleedges = [] def wordcolor(self, word): if word == self.highlight_word: @@ -298,8 +321,26 @@ coordinates may sometimes become longs and cause OverflowErrors within pygame. """ - return (x1 < self.width-self.ofsx and x2 > -self.ofsx and - y1 < self.height-self.ofsy and y2 > -self.ofsy) + w, h = self.screen.get_size() + return x1 < w and x2 > 0 and y1 < h and y2 > 0 + + def computevisible(self): + del self.visiblenodes[:] + del self.visibleedges[:] + w, h = self.screen.get_size() + for node in self.graphlayout.nodes.values(): + x, y = self.map(node.x, node.y) + nw2 = int(node.w * self.scale)//2 + nh2 = int(node.h * self.scale)//2 + if x-nw2 < w and x+nw2 > 0 and y-nh2 < h and y+nh2 > 0: + self.visiblenodes.append(node) + for edge in self.graphlayout.edges: + x1, y1, x2, y2 = edge.limits() + x1, y1 = self.map(x1, y1) + if x1 < w and y1 < h: + x2, y2 = self.map(x2, y2) + if x2 > 0 and y2 > 0: + self.visibleedges.append(edge) def map(self, x, y): return (int(x*self.scale) - (self.ofsx - self.margin), @@ -382,6 +423,14 @@ def cmd(): pygame.draw.rect(self.screen, fgcolor, rect, 1) commands.append(cmd) + elif node.shape == 'ellipse': + rect = (x-1, y-1, boxwidth+2, boxheight+2) + def cmd(): + pygame.draw.ellipse(self.screen, bgcolor, rect, 0) + bkgndcommands.append(cmd) + def cmd(): + pygame.draw.ellipse(self.screen, fgcolor, rect, 1) + commands.append(cmd) elif node.shape == 'octagon': step = 1-math.sqrt(2)/2 points = [(int(x+boxwidth*fx), int(y+boxheight*fy)) @@ -400,14 +449,15 @@ def draw_commands(self): nodebkgndcmd = [] nodecmd = [] - for node in self.graphlayout.nodes.values(): + for node in self.visiblenodes: cmd1, cmd2 = self.draw_node_commands(node) nodebkgndcmd += cmd1 nodecmd += cmd2 edgebodycmd = [] edgeheadcmd = [] - for edge in self.graphlayout.edges: + for edge in self.visibleedges: + fgcolor = getcolor(edge.color, (0,0,0)) if edge.highlight: fgcolor = highlight_color(fgcolor) @@ -435,6 +485,8 @@ return edgebodycmd + nodebkgndcmd + edgeheadcmd + nodecmd def render(self): + self.computevisible() + bbox = self.getboundingbox() self.screen.fill((224, 255, 224), bbox) @@ -478,7 +530,7 @@ def node_at_position(self, (x, y)): """Return the Node under the cursor.""" x, y = self.revmap(x, y) - for node in self.graphlayout.nodes.itervalues(): + for node in self.visiblenodes: if 2.0*abs(x-node.x) <= node.w and 2.0*abs(y-node.y) <= node.h: return node return None @@ -489,7 +541,7 @@ distmax /= self.scale xy = self.revmap(x, y) closest_edge = None - for edge in self.graphlayout.edges: + for edge in self.visibleedges: pts = edge.bezierpoints() for i in range(1, len(pts)): d = segmentdistance(pts[i-1], pts[i], xy) From ludal at codespeak.net Sun Jul 3 20:44:19 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 20:44:19 +0200 (CEST) Subject: [pypy-svn] r14185 - pypy/dist/pypy/interpreter/test Message-ID: <20050703184419.0F56127B74@code1.codespeak.net> Author: ludal Date: Sun Jul 3 20:44:17 2005 New Revision: 14185 Modified: pypy/dist/pypy/interpreter/test/test_interpreter.py Log: * run tests also with PythonCompiler Modified: pypy/dist/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/dist/pypy/interpreter/test/test_interpreter.py Sun Jul 3 20:44:17 2005 @@ -1,4 +1,6 @@ import py +import sys +from pypy.interpreter.pycompiler import PythonCompiler class TestInterpreter: def codetest(self, source, functionname, args): @@ -13,7 +15,6 @@ w = space.wrap w_code = space.builtin.call('compile', w(source), w(''), w('exec'), w(0), w(0)) - ec = executioncontext.ExecutionContext(space) tempmodule = module.Module(space, w("__temp__")) w_glob = tempmodule.w_dict @@ -226,6 +227,23 @@ assert self.codetest(code, 'g', [12, {}]) == () assert self.codetest(code, 'g', [12, {3:1}]) == (3,) +class TestPyPyInterpreter(TestInterpreter): + """Runs the previous test with the pypy parser""" + def setup_class(klass): + sys.setrecursionlimit(10000) + + def setup_method(self,arg): + ec = self.space.getexecutioncontext() + self.saved_compiler = ec.compiler + ec.compiler = PythonCompiler(self.space) + + def teardown_method(self,arg): + ec = self.space.getexecutioncontext() + ec.compiler = self.saved_compiler + + def test_extended_arg(self): + py.test.skip("Probably hits a bug in the compiler module") + class AppTestInterpreter: def test_trivial(self): x = 42 @@ -258,3 +276,4 @@ def test_identity(self): def f(x): return x assert f(666) == 666 + From arigo at codespeak.net Sun Jul 3 20:44:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Jul 2005 20:44:59 +0200 (CEST) Subject: [pypy-svn] r14186 - in pypy/branch/pypy-translation-snapshot: module/__builtin__/test objspace objspace/std Message-ID: <20050703184459.2D1DD27B76@code1.codespeak.net> Author: arigo Date: Sun Jul 3 20:44:58 2005 New Revision: 14186 Modified: pypy/branch/pypy-translation-snapshot/module/__builtin__/test/test_builtin.py pypy/branch/pypy-translation-snapshot/objspace/descroperation.py pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Log: Merged r14079 and r14101 from the 2.4.1 branch to remove the icky-ness from the implementation of cmp. Modified: pypy/branch/pypy-translation-snapshot/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/pypy-translation-snapshot/module/__builtin__/test/test_builtin.py Sun Jul 3 20:44:58 2005 @@ -261,10 +261,10 @@ b = []; b.append(b) from UserList import UserList c = UserList(); c.append(c) - assert cmp(a, b) == 0 - assert cmp(b, c) == 0 - assert cmp(c, a) == 0 - assert cmp(a, c) == 0 + raises(RuntimeError, cmp, a, b) + raises(RuntimeError, cmp, b, c) + raises(RuntimeError, cmp, c, a) + raises(RuntimeError, cmp, a, c) # okay, now break the cycles a.pop(); b.pop(); c.pop() Modified: pypy/branch/pypy-translation-snapshot/objspace/descroperation.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/descroperation.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/descroperation.py Sun Jul 3 20:44:58 2005 @@ -64,10 +64,6 @@ class DescrOperation: _mixin_ = True - def setup_ec(space, ec): - ec._compare_nesting = 0 - ec._cmp_state = {} - def is_data_descr(space, w_obj): return space.lookup(w_obj, '__set__') is not None @@ -286,67 +282,24 @@ if w_del is not None: space.get_and_call_function(w_del, w_obj) - _NESTING_LIMIT = 20 - def cmp(space, w_v, w_w): - # Icky implementation trying to mimic python 2.3 semantics. if space.is_w(w_v, w_w): return space.wrap(0) - w_vt = space.type(w_v) - token = None - _inprogress_dict = None - - ec = space.getexecutioncontext() - ec._compare_nesting += 1 - _compare_nesting = ec._compare_nesting - - try: - # Try to do some magic to compare cyclic constructs. - if (_compare_nesting > space._NESTING_LIMIT and - # dont't be subtle the corresponding condition in CPython is always true for heaptypes - # (space.lookup(w_v, '__getitem__') is not None) and - not (space.is_w(w_vt, space.w_str) or - space.is_w(w_vt, space.w_tuple))): - try: - iv = space.int_w(space.id(w_v)) - iw = space.int_w(space.id(w_w)) - if iv <= iw: - t = (iv, iw, -1) - else: - t = (iw, iv, -1) - _inprogress_dict = ec._cmp_state - if t in _inprogress_dict: - # If we are allready trying to compare the arguments - # presume they are equal - return space.wrap(0) - else: - token = _inprogress_dict[t] = t - except: - return space.wrap(-1) - try: - # The real comparison - if space.is_w(space.type(w_v), space.type(w_w)): - # for object of the same type, prefer __cmp__ over rich comparison. - w_cmp = space.lookup(w_v, '__cmp__') - w_res = _invoke_binop(space, w_cmp, w_v, w_w) - if w_res is not None: - return w_res - # fall back to rich comparison. - if space.eq_w(w_v, w_w): - return space.wrap(0) - elif space.is_true(space.lt(w_v, w_w)): - return space.wrap(-1) - return space.wrap(1) - finally: - if token is not None: - try: - del _inprogress_dict[token] - except: - pass - finally: - ec._compare_nesting -= 1 + # The real comparison + if space.is_w(space.type(w_v), space.type(w_w)): + # for object of the same type, prefer __cmp__ over rich comparison. + w_cmp = space.lookup(w_v, '__cmp__') + w_res = _invoke_binop(space, w_cmp, w_v, w_w) + if w_res is not None: + return w_res + # fall back to rich comparison. + if space.eq_w(w_v, w_w): + return space.wrap(0) + elif space.is_true(space.lt(w_v, w_w)): + return space.wrap(-1) + return space.wrap(1) def coerce(space, w_obj1, w_obj2): w_typ1 = space.type(w_obj1) @@ -478,65 +431,25 @@ w_first = w_obj1 w_second = w_obj2 - token = None - _inprogress_dict = None - - ec = space.getexecutioncontext() - ec._compare_nesting += 1 - _compare_nesting = ec._compare_nesting - try: - # Try to do some magic to compare cyclic constructs. - if (_compare_nesting > space._NESTING_LIMIT and - # dont't be subtle the corresponding condition in CPython is always true for heaptypes - # (space.lookup(w_obj1, '__getitem__') is not None) and - not (space.is_w(w_typ1, space.w_str) or - space.is_w(w_typ1, space.w_tuple))): - i1 = space.int_w(space.id(w_obj1)) - i2 = space.int_w(space.id(w_obj2)) - if i1 <= i2: - t = (i1, i2, left) - else: - t = (i2, i1, right) - _inprogress_dict = ec._cmp_state - if t in _inprogress_dict: - # If we are allready trying to compare the arguments - # presume they are equal - if symbol == '==': - return space.w_True - elif symbol == '!=': - return space.w_False - else: - raise OperationError(space.w_ValueError, - space.wrap("can't order recursive values")) - else: - token = _inprogress_dict[t] = t + if space.is_true(space.is_(w_typ1, w_typ2)): + w_right_impl = None + else: + w_right_src, w_right_impl = space.lookup_where(w_obj2, right) + if space.is_true(space.issubtype(w_typ2, w_typ1)) and not space.is_w(w_right_src, w_left_src): + w_obj1, w_obj2 = w_obj2, w_obj1 + w_left_impl, w_right_impl = w_right_impl, w_left_impl - if space.is_true(space.is_(w_typ1, w_typ2)): - w_right_impl = None - else: - w_right_src, w_right_impl = space.lookup_where(w_obj2, right) - if space.is_true(space.issubtype(w_typ2, w_typ1)) and not space.is_w(w_right_src, w_left_src): - w_obj1, w_obj2 = w_obj2, w_obj1 - w_left_impl, w_right_impl = w_right_impl, w_left_impl + w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) + if w_res is not None: + return w_res + w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) + if w_res is not None: + return w_res + # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... + w_res = _cmp(space, w_first, w_second) + res = space.int_w(w_res) + return space.wrap(op(res, 0)) - w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) - if w_res is not None: - return w_res - w_res = _invoke_binop(space, w_right_impl, w_obj2, w_obj1) - if w_res is not None: - return w_res - # fallback: lt(a, b) <= lt(cmp(a, b), 0) ... - w_res = _cmp(space, w_first, w_second) - res = space.int_w(w_res) - return space.wrap(op(res, 0)) - finally: - ec._compare_nesting -= 1 - if token is not None: - try: - del _inprogress_dict[token] - except: - pass - return func_with_new_name(comparison_impl, 'comparison_%s_impl'%left.strip('_')) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Sun Jul 3 20:44:58 2005 @@ -174,7 +174,6 @@ def createexecutioncontext(self): # add space specific fields to execution context ec = ObjSpace.createexecutioncontext(self) - DescrOperation.setup_ec(self, ec) ec._py_repr = self.newdict([]) return ec From tismer at codespeak.net Sun Jul 3 20:50:34 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 3 Jul 2005 20:50:34 +0200 (CEST) Subject: [pypy-svn] r14188 - pypy/dist/pypy/objspace/std Message-ID: <20050703185034.3479D27B7B@code1.codespeak.net> Author: tismer Date: Sun Jul 3 20:50:33 2005 New Revision: 14188 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: basic signed division works Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Sun Jul 3 20:50:33 2005 @@ -847,46 +847,37 @@ return a, rem -##def _divrem(a, b) -## size_a = len(a.digits) * 2 -## size_b = len(b.digits) * 2 -## PyLongObject *z; -## -## if (size_b == 0) { -## PyErr_SetString(PyExc_ZeroDivisionError, -## "long division or modulo by zero"); -## return -1; -## } -## if (size_a < size_b || -## (size_a == size_b && -## a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { -## /* |a| < |b|. */ -## *pdiv = _PyLong_New(0); -## Py_INCREF(a); -## *prem = (PyLongObject *) a; -## return 0; -## } -## if (size_b == 1) { -## digit rem = 0; -## z = divrem1(a, b->ob_digit[0], &rem); -## if (z == NULL) -## return -1; -## *prem = (PyLongObject *) PyLong_FromLong((long)rem); -## } -## else { -## z = x_divrem(a, b, prem); -## if (z == NULL) -## return -1; -## } -## /* Set the signs. -## The quotient z has the sign of a*b; -## the remainder r has the sign of a, -## so a = b*z + r. */ -## if ((a->ob_size < 0) != (b->ob_size < 0)) -## z->ob_size = -(z->ob_size); -## if (a->ob_size < 0 && (*prem)->ob_size != 0) -## (*prem)->ob_size = -((*prem)->ob_size); -## *pdiv = z; -## return 0; +def _divrem(space, a, b): + """ Long division with remainder, top-level routine """ + size_a = len(a.digits) * 2 + size_b = len(b.digits) * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + if b._getshort(size_b-1) == 0: + size_b -= 1 -## XXXX + if size_b == 0: + raise OperationError(w_longobj.space.w_ZeroDivisionError, + w_longobj.space.wrap("long division or modulo by zero")) + + if (size_a < size_b or + (size_a == size_b and + a._getshort(size_a-1) < b._getshort(size_b-1))): + # |a| < |b| + z = W_LongObject(space, [r_uint(0)], 0) + rem = a + return z, rem + if size_b == 1: + z, urem = divrem1(a, b._getshort(0)) + rem = W_LongObject(space, [urem], int(urem != 0)) + else: + z, rem = _x_divrem(a, b) + # Set the signs. + # The quotient z has the sign of a*b; + # the remainder r has the sign of a, + # so a = b*z + r. + if a.sign != b.sign: + z.sign = - z.sign + if z.sign < 0 and rem.sign != 0: + rem.sign = - rem.sign + return z, rem From ludal at codespeak.net Sun Jul 3 20:54:59 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Sun, 3 Jul 2005 20:54:59 +0200 (CEST) Subject: [pypy-svn] r14189 - pypy/dist/pypy/interpreter/stablecompiler Message-ID: <20050703185459.7713E27B70@code1.codespeak.net> Author: ludal Date: Sun Jul 3 20:54:58 2005 New Revision: 14189 Added: pypy/dist/pypy/interpreter/stablecompiler/ - copied from r14188, pypy/dist/pypy/interpreter/astcompiler/ Log: * yet another copy of the compiler module stablecompiler : original 2.4.1 compiler module used with --pyparse option with bugfixes only astcompiler : development version intended to be fully annotatable From ericvrp at codespeak.net Sun Jul 3 21:01:41 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 3 Jul 2005 21:01:41 +0200 (CEST) Subject: [pypy-svn] r14191 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050703190141.76A1527B7B@code1.codespeak.net> Author: ericvrp Date: Sun Jul 3 21:01:40 2005 New Revision: 14191 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: test GC Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 21:01:40 2005 @@ -32,9 +32,8 @@ if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") return - py.test.skip("test_GC_malloc skipped because test not yet correct (Boehm collector IS used anyway)") - return def tuple_getitem(n): + start_heap_size = GC_get_heap_size() x = 0 i = 0 while i < n: @@ -43,8 +42,13 @@ i += 1 return x f = compile_function(tuple_getitem, [int]) - t = 1024*1024*100 - f(t) #assert f(t) == t + heap_size_start = get_heap_size_wrapper() + for i in range(0,10): + f(10000) + heap_size_used = get_heap_size() - heap_size_start + print 'heap_size_used=%d' % heap_size_used + assert heap_size_used < 5000 + def test_return1(): def simple1(): From ericvrp at codespeak.net Sun Jul 3 21:07:24 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 3 Jul 2005 21:07:24 +0200 (CEST) Subject: [pypy-svn] r14192 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050703190724.305EC27B80@code1.codespeak.net> Author: ericvrp Date: Sun Jul 3 21:07:23 2005 New Revision: 14192 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py Log: Beginning of code to supply the GC with hints about what data contains (or not) pointers Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 3 21:07:23 2005 @@ -45,7 +45,7 @@ "null", *indices) fromtype = self.db.repr_arg_type(self.array.OF) codewriter.cast("%usize", fromtype + "*", "%size", "uint") - codewriter.malloc("%ptr", "sbyte", "%usize") + codewriter.malloc("%ptr", "sbyte", "%usize", atomic=False) codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) codewriter.store("int", "%len", "%arraylength") Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 3 21:07:23 2005 @@ -10,7 +10,9 @@ class CodeWriter(object): def __init__(self): self._lines = [] - self.append('declare sbyte* %GC_malloc(uint)') + self.declare('sbyte* %GC_malloc(uint)') + self.declare('sbyte* %GC_malloc_atomic(uint)') + self.declare('sbyte* %GC_realloc(sbyte*, uint)') def append(self, line): if show_line_numbers: @@ -94,12 +96,16 @@ self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) - def malloc(self, targetvar, type_, size=1): + def malloc(self, targetvar, type_, size=1, atomic=False): if use_boehm_gc: cnt = count() - self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)d" % locals()) + if atomic: + atomicString = '_atomic' + else: + atomicString = '' + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)s" % locals()) self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) - self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc(uint %%malloc.SizeU.%(cnt)d)" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc%(atomicString)s(uint %%malloc.SizeU.%(cnt)d)" % locals()) self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) else: self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 3 21:07:23 2005 @@ -252,7 +252,7 @@ isinstance(arg.value, lltype.Struct)) #XXX unclean type = self.db.obj2node[arg.value].ref - self.codewriter.malloc(targetvar, type) + self.codewriter.malloc(targetvar, type, atomic=False) def malloc_varsize(self, op): targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sun Jul 3 21:07:23 2005 @@ -65,7 +65,7 @@ #XXX is this ok for 64bit? codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") + codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=False) codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") # remember the allocated length for later use. From bert at codespeak.net Sun Jul 3 21:27:00 2005 From: bert at codespeak.net (bert at codespeak.net) Date: Sun, 3 Jul 2005 21:27:00 +0200 (CEST) Subject: [pypy-svn] r14193 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050703192700.DC16227B84@code1.codespeak.net> Author: bert Date: Sun Jul 3 21:26:59 2005 New Revision: 14193 Modified: pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: added GC_get_heap_size to be able to test the boehm GC in llvm2 backend Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jul 3 21:26:59 2005 @@ -1,5 +1,5 @@ from os.path import exists -use_boehm_gc = exists('/usr/lib/libgc.so') +use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') import py from pypy.translator.llvm2 import build_llvm_module @@ -60,8 +60,7 @@ pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') write_pyx_wrapper(entrynode, pyxsource) - mod = build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) - return getattr(mod, func.func_name + "_wrapper") + return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) def llvm_is_on_path(): try: Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sun Jul 3 21:26:59 2005 @@ -1,5 +1,6 @@ from pypy.translator.llvm2.log import log from pypy.rpython import lltype +from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.pyrex PRIMITIVES_TO_C = {lltype.Signed: "int", @@ -23,6 +24,11 @@ inputargs = funcgen.db.repr_arg_multi(funcgen.graph.startblock.inputargs) inputargs = [x.strip("%") for x in inputargs] append("cdef extern " + c_declaration()) + if use_boehm_gc: + append("cdef extern int GC_get_heap_size()") + append("") + append("def GC_get_heap_size_wrapper():") + append(" return GC_get_heap_size()") append("") append("def %s_wrapper(%s):" % (funcgen.ref.strip("%"), ", ".join(inputargs))) append(" return %s(%s)" % (funcgen.ref.strip("%"), ", ".join(inputargs))) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 3 21:26:59 2005 @@ -19,7 +19,7 @@ ## def setup_module(mod): ## mod.llvm_found = is_on_path("llvm-as") -def compile_function(function, annotate, view=False): +def compile_module(function, annotate, view=False): t = Translator(function) a = t.annotate(annotate) t.specialize() @@ -28,12 +28,20 @@ t.view() return genllvm(t) +def compile_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + return getattr(mod, function.func_name + "_wrapper") + +def compile_module_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + f = getattr(mod, function.func_name + "_wrapper") + return mod, f + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") return def tuple_getitem(n): - start_heap_size = GC_get_heap_size() x = 0 i = 0 while i < n: @@ -41,14 +49,14 @@ x += l[2] i += 1 return x - f = compile_function(tuple_getitem, [int]) - heap_size_start = get_heap_size_wrapper() + mod,f = compile_module_function(tuple_getitem, [int]) + get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") + heap_size_start = get_heap_size() for i in range(0,10): f(10000) heap_size_used = get_heap_size() - heap_size_start print 'heap_size_used=%d' % heap_size_used - assert heap_size_used < 5000 - + assert heap_size_used < 100000 def test_return1(): def simple1(): From quest at codespeak.net Sun Jul 3 22:31:27 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Sun, 3 Jul 2005 22:31:27 +0200 (CEST) Subject: [pypy-svn] r14194 - in pypy/branch/dist-2.4.1: lib-python/modified-2.4.1/test pypy/lib Message-ID: <20050703203127.9A6C527B8A@code1.codespeak.net> Author: quest Date: Sun Jul 3 22:31:26 2005 New Revision: 14194 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_deque.py - copied, changed from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_deque.py pypy/branch/dist-2.4.1/pypy/lib/collections.py Log: Naive collections implementation. Two tests not working. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_deque.py (from r14137, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_deque.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_deque.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_deque.py Sun Jul 3 22:31:26 2005 @@ -1,14 +1,14 @@ from collections import deque import unittest from test import test_support -from weakref import proxy +#from weakref import proxy import copy import cPickle as pickle from cStringIO import StringIO import random import os -BIG = 100000 +BIG = 10 def fail(): raise SyntaxError @@ -69,7 +69,7 @@ self.assertRaises(SyntaxError, d.extendleft, fail()) def test_getitem(self): - n = 200 + n = 10 d = deque(xrange(n)) l = range(n) for i in xrange(n): @@ -89,7 +89,7 @@ self.assertRaises(IndexError, d.__getitem__, -1) def test_setitem(self): - n = 200 + n = 10 d = deque(xrange(n)) for i in xrange(n): d[i] = 10 * i @@ -225,7 +225,7 @@ self.assertRaises(TypeError, hash, deque('abc')) def test_long_steadystate_queue_popleft(self): - for size in (0, 1, 2, 100, 1000): + for size in (0, 1, 2, 9): d = deque(xrange(size)) append, pop = d.append, d.popleft for i in xrange(size, BIG): @@ -236,7 +236,7 @@ self.assertEqual(list(d), range(BIG-size, BIG)) def test_long_steadystate_queue_popright(self): - for size in (0, 1, 2, 100, 1000): + for size in (0, 1, 2, 9): d = deque(reversed(xrange(size))) append, pop = d.appendleft, d.pop for i in xrange(size, BIG): @@ -504,12 +504,12 @@ d = DequeWithBadIter('abc') self.assertRaises(TypeError, pickle.dumps, d) - def test_weakref(self): - d = deque('gallahad') - p = proxy(d) - self.assertEqual(str(p), str(d)) - d = None - self.assertRaises(ReferenceError, str, p) +# def test_weakref(self): +# d = deque('gallahad') +# p = proxy(d) +# self.assertEqual(str(p), str(d)) +# d = None +# self.assertRaises(ReferenceError, str, p) def test_strange_subclass(self): class X(deque): Added: pypy/branch/dist-2.4.1/pypy/lib/collections.py ============================================================================== --- (empty file) +++ pypy/branch/dist-2.4.1/pypy/lib/collections.py Sun Jul 3 22:31:26 2005 @@ -0,0 +1,56 @@ +# Naive collections implementation + +class deque(list): + def __init__(self, iter=None): + # Do not run init on list, as it will empty list; deque test_basic does: + # d = deque(xrange(100)) + # d.__init__(xrange(100, 200)) + if iter is not None: + self.extend(iter) + + def appendleft(self, item): + self.insert(0, item) + + def clear(self): + del self[:] + + def extendleft(self, other): + self[0:0] = [x for x in other][::-1] + + def popleft(self): + x = self[0] + del self[0] + return x + + def rotate(self, step=1): + if len(self) == 0: + return + step %= len(self) + for i in range(step): + self.appendleft(self.pop()) + + def __repr__(self): + return "%s(%s)" % (type(self).__name__, list.__repr__(self)) + + def __reduce_ex__(self, proto): + return type(self), (), self.__dict__, iter(self), None + + # We want to hide the fact that this deque is a subclass of list: + # should not be equal to + def __eq__(self, other): + return isinstance(other, deque) and list.__eq__(self, other) + + def __ne__(self, other): + return not isinstance(other, deque) or list.__ne__(self, other) + + def __lt__(self, other): + return isinstance(other, deque) and list.__lt__(self, other) + + def __le__(self, other): + return isinstance(other, deque) and list.__le__(self, other) + + def __ge__(self, other): + return isinstance(other, deque) and list.__ge__(self, other) + + def __gt__(self, other): + return isinstance(other, deque) and list.__gt__(self, other) From rxe at codespeak.net Mon Jul 4 11:43:32 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 4 Jul 2005 11:43:32 +0200 (CEST) Subject: [pypy-svn] r14195 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050704094332.7293A27B49@code1.codespeak.net> Author: rxe Date: Mon Jul 4 11:43:31 2005 New Revision: 14195 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py Log: Fix getarrayitem and getfield to only load pointers and primitives in to registers. Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Mon Jul 4 11:43:31 2005 @@ -273,18 +273,16 @@ typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) - + self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" - #XXX This doesnt work - yet - #if isinstance(op.result.concretetype, lltype.Ptr): - # self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - #else: - # Moving to correct result variable - #self.codewriter.load(targetvar, targettype, tmpvar) - self.codewriter.load(targetvar, targettype, tmpvar) + if isinstance(op.result.concretetype, lltype.ContainerType): + # noop + self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + else: + self.codewriter.load(targetvar, targettype, tmpvar) + getsubstruct = getfield def setfield(self, op): @@ -304,20 +302,16 @@ vartype = self.db.repr_arg_type(op.args[0]) index = self.db.repr_arg(op.args[1]) indextype = self.db.repr_arg_type(op.args[1]) - tmpvar = self.db.repr_tmpvar() self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 1), (indextype, index)) - targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - - # Ditto see getfield - if not isinstance(op.result.concretetype, lltype.Ptr): - self.codewriter.load(targetvar, targettype, tmpvar) - else: - # XXX noop + if isinstance(op.result.concretetype, lltype.ContainerType): + # noop self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + else: + self.codewriter.load(targetvar, targettype, tmpvar) def setarrayitem(self, op): array = self.db.repr_arg(op.args[0]) From rxe at codespeak.net Mon Jul 4 11:59:32 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 4 Jul 2005 11:59:32 +0200 (CEST) Subject: [pypy-svn] r14196 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050704095932.6AC3327B49@code1.codespeak.net> Author: rxe Date: Mon Jul 4 11:59:31 2005 New Revision: 14196 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Add two new goal tests for today. Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 11:59:31 2005 @@ -208,7 +208,7 @@ if m == 0: return ackermann(n - 1, 1) return ackermann(n - 1, ackermann(n, m - 1)) - f = compile_function(call_ackermann, [int, int], view=False) + f = compile_function(call_ackermann, [int, int]) assert f(0, 2) == 3 def test_tuple_getitem(): @@ -258,6 +258,21 @@ assert f(1) == 2 assert f(2) == 3 +def Xtest_list_list_getitem(): + def list_list_getitem(): + l = [[1]] + return l[0][0] + f = compile_function(list_list_getitem, []) + assert f() == 2 + +def Xtest_list_getitem_pbc(): + l = [1,2] + def list_getitem(i): + return l[i] + f = compile_function(list_getitem, [int], view=True) + assert f(0) == 1 + assert f(1) == 2 + def test_list_basic_ops(): def list_basic_ops(i, j): l = [1,2,3] From ludal at codespeak.net Mon Jul 4 12:16:40 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Mon, 4 Jul 2005 12:16:40 +0200 (CEST) Subject: [pypy-svn] r14198 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704101640.BFD8527B41@code1.codespeak.net> Author: ludal Date: Mon Jul 4 12:16:39 2005 New Revision: 14198 Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py Log: use an helper class to provide parser services Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Mon Jul 4 12:16:39 2005 @@ -13,6 +13,38 @@ import os import grammar + +class PythonParser(object): + """Wrapper class for python grammar""" + def __init__(self, grammar_builder ): + self.items = grammar_builder.items + self.rules = grammar_builder.rules + # Build first sets for each rule (including anonymous ones) + grammar.build_first_sets( self.items ) + + def parse_source( self, textsrc, goal, builder=None ): + """Parse a python source according to goal""" + lines = [line + '\n' for line in textsrc.split('\n')] + + return self.parse_lines( lines, goal, builder ) + + def parse_lines( self, lines, goal, builder=None ): + target = self.rules[goal] + src = Source(lines) + + if builder is None: + builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) + result = target.match(src, builder) + # XXX find a clean way to process encoding declarations + builder.source_encoding = src.encoding + # + if not result: + # raising a SyntaxError here is not annotable, and it can + # probably be handled in an other way + # raise SyntaxError("at %s" % src.debug() ) + return None + return builder + # parse the python grammar corresponding to our CPython version _ver = ".".join([str(i) for i in sys.version_info[:2]]) PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) @@ -23,9 +55,7 @@ grammar.DEBUG = 0 gram = ebnfparse.parse_grammar( file(PYTHON_GRAMMAR) ) grammar.DEBUG = level - # Build first sets for each rule (including anonymous ones) - grammar.build_first_sets(gram.items) - return gram + return PythonParser(gram) debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar() @@ -38,32 +68,18 @@ self.offset = -1 self.msg = "SyntaxError at line %d: %r" % (self.lineno, self.line) -def parse_python_source(textsrc, gram, goal, builder=None): +def parse_python_source( textlines, gram, goal, builder=None ): """Parse a python source according to goal""" - target = gram.rules[goal] - src = Source(textsrc) - if builder is None: - builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) - result = target.match(src, builder) - # XXX find a clean way to process encoding declarations - builder.source_encoding = src.encoding - # - if not result: - # raising a SyntaxError here is not annotable, and it can - # probably be handled in an other way - line, lineno = src.debug() - raise BuilderError(line, lineno) - # return None - return builder + return gram.parse_lines( textlines, goal, builder ) def parse_file_input(pyf, gram, builder=None): """Parse a python file""" - return parse_python_source( pyf.read(), gram, "file_input", builder ) + return gram.parse_source( pyf.read(), "file_input", builder ) def parse_single_input(textsrc, gram, builder=None): """Parse a python single statement""" - return parse_python_source( textsrc, gram, "single_input", builder ) + return gram.parse_source( textsrc, "single_input", builder ) def parse_eval_input(textsrc, gram, builder=None): """Parse a python expression""" - return parse_python_source( textsrc, gram, "eval_input", builder ) + return gram.parse_source( textsrc, "eval_input", builder ) From ericvrp at codespeak.net Mon Jul 4 12:17:29 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 12:17:29 +0200 (CEST) Subject: [pypy-svn] r14199 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050704101729.7063227B41@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 12:17:28 2005 New Revision: 14199 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: improved gc test Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 12:17:28 2005 @@ -50,13 +50,13 @@ i += 1 return x mod,f = compile_module_function(tuple_getitem, [int]) + assert f(10000) == 49995000 get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") heap_size_start = get_heap_size() for i in range(0,10): - f(10000) - heap_size_used = get_heap_size() - heap_size_start - print 'heap_size_used=%d' % heap_size_used - assert heap_size_used < 100000 + assert f(10000) == 49995000 + heap_size_inc = get_heap_size() - heap_size_start + assert heap_size_inc < 100000 def test_return1(): def simple1(): From rxe at codespeak.net Mon Jul 4 12:30:55 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 4 Jul 2005 12:30:55 +0200 (CEST) Subject: [pypy-svn] r14200 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050704103055.46A4A27B41@code1.codespeak.net> Author: rxe Date: Mon Jul 4 12:30:54 2005 New Revision: 14200 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Make arrays work with non primitive types. Unfortunately to set ref we need to wait until the dependent nodes have been setup. This is an intermediate checkin while it is decided how we should make the framework more flexible. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Mon Jul 4 12:30:54 2005 @@ -13,16 +13,32 @@ self.db = db assert isinstance(array, lltype.Array) self.array = array - ref_template = "%%array.%s." % array.OF c = count() - self.ref = ref_template + str(c) + self.ref_template = "%%array.%s." + str(c) + self.ref = self.getref() self.constructor_ref = "%%new.array.%s" % c - self.constructor_decl = "%s * %s(int %%len)" % ( - self.ref, self.constructor_ref) + + def __str__(self): + return "" % self.ref + + def getref(self): + try: + arrayname = self.db.repr_arg_type(self.array.OF) + except KeyError: + arrayname = str(self.array.OF) + arrayname = arrayname.replace("%", "") + arrayname = arrayname.replace("*", "PTR") + return self.ref_template % arrayname + def get_structure_decl(self): + if not hasattr(self, "constructor_decl"): + self.constructor_decl = "%s * %s(int %%len)" % \ + (self.ref, self.constructor_ref) + return self.constructor_decl + def writedecl(self, codewriter): # declaration for constructor - codewriter.declare(self.constructor_decl) + codewriter.declare(self.get_structure_decl()) def writeimpl(self, codewriter): """ this function generates a LLVM function like the following: @@ -39,7 +55,7 @@ ret %array* %result }""" log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_decl) + codewriter.openfunc(self.get_structure_decl()) indices = [("uint", 1), ("int", "%len")] codewriter.getelementptr("%size", self.ref + "*", "null", *indices) @@ -52,9 +68,6 @@ codewriter.ret(self.ref+"*", "%result") codewriter.closefunc() - def __str__(self): - return "" % self.ref - def setup(self): self.db.prepare_repr_arg_type(self.array.OF) self._issetup = True @@ -113,5 +126,5 @@ lenitems = len(self.value.items) lenstr = ".%s" % lenitems codewriter.globalinstance(self.ref, - self.db.repr_arg_type() + lenstr, + self.db.repr_arg_type(self.value._TYPE), self.get_values()) Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Mon Jul 4 12:30:54 2005 @@ -1,6 +1,9 @@ class LLVMNode(object): def _get_ref(self): - return self._ref + if callable(self._ref): + return self._ref() + else: + return self._ref def _set_ref(self, ref): if hasattr(self, "_ref"): raise TypeError, ("can only set ref once! currently: %s" % Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 12:30:54 2005 @@ -258,12 +258,12 @@ assert f(1) == 2 assert f(2) == 3 -def Xtest_list_list_getitem(): +def test_list_list_getitem(): def list_list_getitem(): l = [[1]] return l[0][0] f = compile_function(list_list_getitem, []) - assert f() == 2 + assert f() == 1 def Xtest_list_getitem_pbc(): l = [1,2] From ericvrp at codespeak.net Mon Jul 4 12:51:13 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 12:51:13 +0200 (CEST) Subject: [pypy-svn] r14201 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050704105113.82F3227B41@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 12:51:12 2005 New Revision: 14201 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py Log: cleaned up llvm code-generator in case boeg gc is not used Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Mon Jul 4 12:51:12 2005 @@ -10,9 +10,10 @@ class CodeWriter(object): def __init__(self): self._lines = [] - self.declare('sbyte* %GC_malloc(uint)') - self.declare('sbyte* %GC_malloc_atomic(uint)') - self.declare('sbyte* %GC_realloc(sbyte*, uint)') + if use_boehm_gc: + self.declare('sbyte* %GC_malloc(uint)') + self.declare('sbyte* %GC_malloc_atomic(uint)') + self.declare('sbyte* %GC_realloc(sbyte*, uint)') def append(self, line): if show_line_numbers: From adim at codespeak.net Mon Jul 4 13:01:55 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:01:55 +0200 (CEST) Subject: [pypy-svn] r14202 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704110155.854E127B45@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:01:54 2005 New Revision: 14202 Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py Log: - small cleanups - ast_input don't instantiate a Transfomer instance anymore because we don't want to expliclity import it from a predefined version of the compiler package (compiler / stablecompiler / astcompiler / etc.) - small fixes in the new wrapper class Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Mon Jul 4 13:01:54 2005 @@ -16,24 +16,28 @@ class PythonParser(object): """Wrapper class for python grammar""" - def __init__(self, grammar_builder ): + def __init__(self, grammar_builder): self.items = grammar_builder.items self.rules = grammar_builder.rules # Build first sets for each rule (including anonymous ones) - grammar.build_first_sets( self.items ) + grammar.build_first_sets(self.items) - def parse_source( self, textsrc, goal, builder=None ): + def parse_source(self, textsrc, goal, builder=None): """Parse a python source according to goal""" lines = [line + '\n' for line in textsrc.split('\n')] + if textsrc == '\n': + lines.pop() + else: + last_line = lines[-1] + lines[-1] = last_line[:-1] + return self.parse_lines(lines, goal, builder) - return self.parse_lines( lines, goal, builder ) - - def parse_lines( self, lines, goal, builder=None ): + def parse_lines(self, lines, goal, builder=None): target = self.rules[goal] src = Source(lines) if builder is None: - builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) + builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) result = target.match(src, builder) # XXX find a clean way to process encoding declarations builder.source_encoding = src.encoding @@ -41,8 +45,9 @@ if not result: # raising a SyntaxError here is not annotable, and it can # probably be handled in an other way - # raise SyntaxError("at %s" % src.debug() ) - return None + line, lineno = src.debug() + raise BuilderError(line, lineno) + # return None return builder # parse the python grammar corresponding to our CPython version @@ -68,10 +73,6 @@ self.offset = -1 self.msg = "SyntaxError at line %d: %r" % (self.lineno, self.line) -def parse_python_source( textlines, gram, goal, builder=None ): - """Parse a python source according to goal""" - return gram.parse_lines( textlines, goal, builder ) - def parse_file_input(pyf, gram, builder=None): """Parse a python file""" return gram.parse_source( pyf.read(), "file_input", builder ) From adim at codespeak.net Mon Jul 4 13:02:46 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:02:46 +0200 (CEST) Subject: [pypy-svn] r14203 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704110246.2AB6B27B45@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:02:45 2005 New Revision: 14203 Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py Log: cleanup the pythonutil's functions to use the new wrapper class Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Mon Jul 4 13:02:45 2005 @@ -1,7 +1,6 @@ __all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", - "ast_eval_input" ] + "ast_eval_input"] -from compiler.transformer import Transformer import parser import symbol @@ -63,24 +62,11 @@ nested tuples """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - # finalize the last line - if not source.endswith('\n'): - last_line = strings[-1] - strings[-1] = last_line[:-1] - else: - strings.pop() target_rule = TARGET_DICT[mode] - pythonparse.parse_python_source(strings, PYTHON_PARSER, - target_rule, builder) -## if builder.error_occured(): -## line, lineno, offset, filename = builder.get_error() -## raise SyntaxError(line, lineno, offset, filename) -## # stack_element is a tuplerbuilder.StackElement's instance + PYTHON_PARSER.parse_source(source, target_rule, builder) stack_element = builder.stack[-1] - # convert the stack element into nested tuples - # XXX : the annotator can't follow this call + # convert the stack element into nested tuples (caution, the annotator + # can't follow this call) nested_tuples = stack_element.as_tuple(lineno) if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) @@ -88,14 +74,23 @@ return nested_tuples ## convenience functions for computing AST objects using recparser -def ast_from_input(input, mode): +def ast_from_input(input, mode, transformer): + """converts a source input into an AST + + - input : the source to be converted + - mode : 'exec', 'eval' or 'single' + - transformer : the transfomer instance to use to convert + the nested tuples into the AST + XXX: transformer could be instantiated here but we don't want + here to explicitly import compiler or stablecompiler or + etc. This is to be fixed in a clean way + """ tuples = pypy_parse(input, mode, True) - transformer = Transformer() ast = transformer.compile_node(tuples) return ast ## TARGET FOR ANNOTATORS ############################################# -def annotateme(strings): +def annotateme(source): """This function has no other role than testing the parser's annotation annotateme() is basically the same code that pypy_parse(), but with the @@ -108,7 +103,7 @@ """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + PYTHON_PARSER.parse_source(source, 'file_input', builder) nested_tuples = builder.stack[-1] if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) From adim at codespeak.net Mon Jul 4 13:03:55 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:03:55 +0200 (CEST) Subject: [pypy-svn] r14204 - pypy/dist/pypy/interpreter Message-ID: <20050704110355.327D127B45@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:03:54 2005 New Revision: 14204 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: - instantiate the transformer here rather than in pypparser because here, we know which compiler package should be used - removed unused imports Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Mon Jul 4 13:03:54 2005 @@ -173,10 +173,11 @@ from compiler.pycodegen import ModuleCodeGenerator from compiler.pycodegen import InteractiveCodeGenerator from compiler.pycodegen import ExpressionCodeGenerator -from pyparser.pythonparse import parse_python_source, PYTHON_PARSER -from pyparser.tuplebuilder import TupleBuilder +from compiler.transformer import Transformer from pyparser.pythonutil import ast_from_input import compiler +# XXX compatibility +# compiler = stablecompiler class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler @@ -190,7 +191,8 @@ flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: - tree = ast_from_input(source, mode) + transformer = Transformer() + tree = ast_from_input(source, mode, transformer) compiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) From adim at codespeak.net Mon Jul 4 13:05:48 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:05:48 +0200 (CEST) Subject: [pypy-svn] r14205 - pypy/dist/pypy/translator/goal Message-ID: <20050704110548.7FF4627B45@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:05:46 2005 New Revision: 14205 Modified: pypy/dist/pypy/translator/goal/targetparser.py Log: pyparser.annoteme() now takes a simple string rather than a list of strings Modified: pypy/dist/pypy/translator/goal/targetparser.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetparser.py (original) +++ pypy/dist/pypy/translator/goal/targetparser.py Mon Jul 4 13:05:46 2005 @@ -14,8 +14,7 @@ # _____ Define and setup target ___ def target(): - s_list_of_strings = SomeList(ListDef(None, SomeString())) - return entry_point, [s_list_of_strings] + return entry_point, [str] # _____ Run translated _____ def run(c_entry_point): From rxe at codespeak.net Mon Jul 4 13:17:37 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 4 Jul 2005 13:17:37 +0200 (CEST) Subject: [pypy-svn] r14206 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050704111737.9CBEE27B45@code1.codespeak.net> Author: rxe Date: Mon Jul 4 13:17:36 2005 New Revision: 14206 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/node.py Log: Revert previous hacks for arrays with non primitive types and just wrap the name in inverted commas. Thanks cfbolz! Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Mon Jul 4 13:17:36 2005 @@ -14,31 +14,21 @@ assert isinstance(array, lltype.Array) self.array = array c = count() - self.ref_template = "%%array.%s." + str(c) - self.ref = self.getref() - self.constructor_ref = "%%new.array.%s" % c + ref_template = "%%array.%s." + str(c) + ref_template = '"%s"' % ref_template + arrayname = str(self.array.OF) + self.ref = ref_template % arrayname + constructor_ref = "%%new.array.%s" % c + self.constructor_ref = '"%s"' % constructor_ref + self.constructor_decl = "%s * %s(int %%len)" % \ + (self.ref, self.constructor_ref) def __str__(self): return "" % self.ref - - def getref(self): - try: - arrayname = self.db.repr_arg_type(self.array.OF) - except KeyError: - arrayname = str(self.array.OF) - arrayname = arrayname.replace("%", "") - arrayname = arrayname.replace("*", "PTR") - return self.ref_template % arrayname - def get_structure_decl(self): - if not hasattr(self, "constructor_decl"): - self.constructor_decl = "%s * %s(int %%len)" % \ - (self.ref, self.constructor_ref) - return self.constructor_decl - def writedecl(self, codewriter): # declaration for constructor - codewriter.declare(self.get_structure_decl()) + codewriter.declare(self.constructor_decl) def writeimpl(self, codewriter): """ this function generates a LLVM function like the following: @@ -55,7 +45,7 @@ ret %array* %result }""" log.writeimpl(self.ref) - codewriter.openfunc(self.get_structure_decl()) + codewriter.openfunc(self.constructor_decl) indices = [("uint", 1), ("int", "%len")] codewriter.getelementptr("%size", self.ref + "*", "null", *indices) @@ -88,8 +78,9 @@ def __init__(self, db, value): self.db = db - self.name = "%s.%s" % (value._TYPE.OF, ArrayNode.array_counter) - self.ref = "%%stinstance.%s" % self.name + name = "%s.%s" % (value._TYPE.OF, ArrayNode.array_counter) + self.ref = "%%stinstance.%s" % name + self.dataref = self.ref + ".tmp" self.value = value ArrayNode.array_counter += 1 @@ -127,4 +118,7 @@ lenstr = ".%s" % lenitems codewriter.globalinstance(self.ref, self.db.repr_arg_type(self.value._TYPE), - self.get_values()) + "null") + #codewriter.globalinstance(self.dataref, + # self.db.repr_arg_type(self.value._TYPE), + # self.get_values()) Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Mon Jul 4 13:17:36 2005 @@ -1,9 +1,6 @@ class LLVMNode(object): def _get_ref(self): - if callable(self._ref): - return self._ref() - else: - return self._ref + return self._ref def _set_ref(self, ref): if hasattr(self, "_ref"): raise TypeError, ("can only set ref once! currently: %s" % From ericvrp at codespeak.net Mon Jul 4 13:34:55 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 13:34:55 +0200 (CEST) Subject: [pypy-svn] r14207 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050704113455.2D01427B45@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 13:34:53 2005 New Revision: 14207 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Fixed a bug in codewriter.malloc function, was using wrong size type. Fixed name of a testcase (I will now try to instuct distutils to not work make-like) Moved GC_malloc declarations to a saner location. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Mon Jul 4 13:34:53 2005 @@ -10,10 +10,6 @@ class CodeWriter(object): def __init__(self): self._lines = [] - if use_boehm_gc: - self.declare('sbyte* %GC_malloc(uint)') - self.declare('sbyte* %GC_malloc_atomic(uint)') - self.declare('sbyte* %GC_realloc(sbyte*, uint)') def append(self, line): if show_line_numbers: @@ -104,7 +100,7 @@ atomicString = '_atomic' else: atomicString = '' - self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)s" % locals()) + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, uint %(size)s" % locals()) self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc%(atomicString)s(uint %%malloc.SizeU.%(cnt)d)" % locals()) self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Mon Jul 4 13:34:53 2005 @@ -37,6 +37,10 @@ typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() + if use_boehm_gc: + codewriter.declare('sbyte* %GC_malloc(uint)') + codewriter.declare('sbyte* %GC_malloc_atomic(uint)') + codewriter.declare('sbyte* %GC_realloc(sbyte*, uint)') for typ_decl in db.getobjects(): typ_decl.writedecl(codewriter) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 13:34:53 2005 @@ -41,7 +41,7 @@ if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") return - def tuple_getitem(n): + def tuple_getitem2(n): x = 0 i = 0 while i < n: @@ -49,7 +49,7 @@ x += l[2] i += 1 return x - mod,f = compile_module_function(tuple_getitem, [int]) + mod,f = compile_module_function(tuple_getitem2, [int]) assert f(10000) == 49995000 get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") heap_size_start = get_heap_size() From adim at codespeak.net Mon Jul 4 13:35:22 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:35:22 +0200 (CEST) Subject: [pypy-svn] r14208 - pypy/dist/pypy/interpreter/stablecompiler Message-ID: <20050704113522.8352827B47@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:35:20 2005 New Revision: 14208 Modified: pypy/dist/pypy/interpreter/stablecompiler/future.py pypy/dist/pypy/interpreter/stablecompiler/pyassem.py pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py pypy/dist/pypy/interpreter/stablecompiler/symbols.py pypy/dist/pypy/interpreter/stablecompiler/syntax.py pypy/dist/pypy/interpreter/stablecompiler/transformer.py pypy/dist/pypy/interpreter/stablecompiler/visitor.py Log: changed all original imports from compiler to pypy.interpreter.stablecompiler Modified: pypy/dist/pypy/interpreter/stablecompiler/future.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/future.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/future.py Mon Jul 4 13:35:20 2005 @@ -2,7 +2,7 @@ """ -from compiler import ast, walk +from pypy.interpreter.stablecompiler import ast, walk def is_future(stmt): """Return true if statement is a well-formed future statement""" @@ -61,7 +61,7 @@ if __name__ == "__main__": import sys - from compiler import parseFile, walk + from pypy.interpreter.stablecompiler import parseFile, walk for file in sys.argv[1:]: print file Modified: pypy/dist/pypy/interpreter/stablecompiler/pyassem.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/pyassem.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/pyassem.py Mon Jul 4 13:35:20 2005 @@ -5,8 +5,8 @@ import sys import types -from compiler import misc -from compiler.consts \ +from pypy.interpreter.stablecompiler import misc +from pypy.interpreter.stablecompiler.consts \ import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS class FlowGraph: Modified: pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py Mon Jul 4 13:35:20 2005 @@ -6,12 +6,13 @@ import types from cStringIO import StringIO -from compiler import ast, parse, walk, syntax -from compiler import pyassem, misc, future, symbols -from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL -from compiler.consts import CO_VARARGS, CO_VARKEYWORDS, CO_NEWLOCALS,\ - CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION -from compiler.pyassem import TupleArg +from pypy.interpreter.stablecompiler import ast, parse, walk, syntax +from pypy.interpreter.stablecompiler import pyassem, misc, future, symbols +from pypy.interpreter.stablecompiler.consts import SC_LOCAL, SC_GLOBAL, \ + SC_FREE, SC_CELL +from pypy.interpreter.stablecompiler.consts import CO_VARARGS, CO_VARKEYWORDS, \ + CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION +from pypy.interpreter.stablecompiler.pyassem import TupleArg # XXX The version-specific code can go, since this code only works with 2.x. # Do we have Python 1.x or Python 2.x? Modified: pypy/dist/pypy/interpreter/stablecompiler/symbols.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/symbols.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/symbols.py Mon Jul 4 13:35:20 2005 @@ -1,8 +1,9 @@ """Module symbol-table generator""" -from compiler import ast -from compiler.consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN -from compiler.misc import mangle +from pypy.interpreter.stablecompiler import ast +from pypy.interpreter.stablecompiler.consts import SC_LOCAL, SC_GLOBAL, \ + SC_FREE, SC_CELL, SC_UNKNOWN +from pypy.interpreter.stablecompiler.misc import mangle import types @@ -419,7 +420,7 @@ if __name__ == "__main__": import sys - from compiler import parseFile, walk + from pypy.interpreter.stablecompiler import parseFile, walk import symtable def get_names(syms): Modified: pypy/dist/pypy/interpreter/stablecompiler/syntax.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/syntax.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/syntax.py Mon Jul 4 13:35:20 2005 @@ -9,7 +9,7 @@ errors. """ -from compiler import ast, walk +from pypy.interpreter.stablecompiler import ast, walk def check(tree, multi=None): v = SyntaxErrorChecker(multi) Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Mon Jul 4 13:35:20 2005 @@ -25,7 +25,7 @@ # http://www.opensource.org/licenses/bsd-license.html # and replace OWNER, ORGANIZATION, and YEAR as appropriate. -from compiler.ast import * +from pypy.interpreter.stablecompiler.ast import * import parser import symbol import token Modified: pypy/dist/pypy/interpreter/stablecompiler/visitor.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/visitor.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/visitor.py Mon Jul 4 13:35:20 2005 @@ -1,4 +1,4 @@ -from compiler import ast +from pypy.interpreter.stablecompiler import ast # XXX should probably rename ASTVisitor to ASTWalker # XXX can it be made even more generic? From adim at codespeak.net Mon Jul 4 13:35:45 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:35:45 +0200 (CEST) Subject: [pypy-svn] r14209 - pypy/dist/pypy/interpreter Message-ID: <20050704113545.3E50827B47@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:35:44 2005 New Revision: 14209 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: use stablecompiler instead of compiler Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Mon Jul 4 13:35:44 2005 @@ -169,15 +169,12 @@ ######## -# from compiler.transformer import Transformer -from compiler.pycodegen import ModuleCodeGenerator -from compiler.pycodegen import InteractiveCodeGenerator -from compiler.pycodegen import ExpressionCodeGenerator -from compiler.transformer import Transformer +from pypy.interpreter import stablecompiler +from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator +from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator +from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator +from pypy.interpreter.stablecompiler.transformer import Transformer from pyparser.pythonutil import ast_from_input -import compiler -# XXX compatibility -# compiler = stablecompiler class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler @@ -193,7 +190,7 @@ try: transformer = Transformer() tree = ast_from_input(source, mode, transformer) - compiler.misc.set_filename(filename, tree) + stablecompiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) elif mode == 'single': From ericvrp at codespeak.net Mon Jul 4 13:49:20 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 13:49:20 +0200 (CEST) Subject: [pypy-svn] r14211 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050704114920.6ECC627B45@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 13:49:19 2005 New Revision: 14211 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py Log: Force distutils to create outputfiles regardless of timestamps. This is required because all our testcases are build in the same directory. Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Mon Jul 4 13:49:19 2005 @@ -33,7 +33,7 @@ libraries = %(library_files)s, extra_objects = %(object_files)s)]) ''' % locals()))) - cmd = "python %s_setup.py build_ext --inplace" % module + cmd = "python %s_setup.py build_ext --inplace --force" % module if debug: print cmd cmdexec(cmd) From adim at codespeak.net Mon Jul 4 13:52:30 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 13:52:30 +0200 (CEST) Subject: [pypy-svn] r14212 - pypy/dist/pypy/interpreter/stablecompiler Message-ID: <20050704115230.8F84B27B45@code1.codespeak.net> Author: adim Date: Mon Jul 4 13:52:28 2005 New Revision: 14212 Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: fixed the silly WalkerEror/WalkerError bug of the stdlib's compiler package Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Mon Jul 4 13:52:28 2005 @@ -89,7 +89,7 @@ print nodes[kind], len(args), args raise else: - raise WalkerEror, "Can't find appropriate Node type: %s" % str(args) + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) #return apply(ast.Node, args) class Transformer: @@ -165,11 +165,10 @@ if n == symbol.classdef: return self.classdef(node[1:]) - raise WalkerEror, ('unexpected node type', n) + raise WalkerError, ('unexpected node type', n) def single_input(self, node): ### do we want to do anything about being "interactive" ? - # NEWLINE | simple_stmt | compound_stmt NEWLINE n = node[0][0] if n != token.NEWLINE: @@ -314,31 +313,31 @@ return Stmt(stmts) def parameters(self, nodelist): - raise WalkerEror + raise WalkerError def varargslist(self, nodelist): - raise WalkerEror + raise WalkerError def fpdef(self, nodelist): - raise WalkerEror + raise WalkerError def fplist(self, nodelist): - raise WalkerEror + raise WalkerError def dotted_name(self, nodelist): - raise WalkerEror + raise WalkerError def comp_op(self, nodelist): - raise WalkerEror + raise WalkerError def trailer(self, nodelist): - raise WalkerEror + raise WalkerError def sliceop(self, nodelist): - raise WalkerEror + raise WalkerError def argument(self, nodelist): - raise WalkerEror + raise WalkerError # -------------------------------------------------------------- # From jacob at codespeak.net Mon Jul 4 15:50:48 2005 From: jacob at codespeak.net (jacob at codespeak.net) Date: Mon, 4 Jul 2005 15:50:48 +0200 (CEST) Subject: [pypy-svn] r14215 - in pypy/dist/lib-python/modified-2.3.4: . test Message-ID: <20050704135048.1471527B45@code1.codespeak.net> Author: jacob Date: Mon Jul 4 15:50:46 2005 New Revision: 14215 Added: pypy/dist/lib-python/modified-2.3.4/binhex.py pypy/dist/lib-python/modified-2.3.4/test/test_binhex.py Log: Pypy uses a stricter check on arguments in the struct module. We therefore have to change the 'h' param to 'H' since the argument is unsigned. Added: pypy/dist/lib-python/modified-2.3.4/binhex.py ============================================================================== --- (empty file) +++ pypy/dist/lib-python/modified-2.3.4/binhex.py Mon Jul 4 15:50:46 2005 @@ -0,0 +1,531 @@ +"""Macintosh binhex compression/decompression. + +easy interface: +binhex(inputfilename, outputfilename) +hexbin(inputfilename, outputfilename) +""" + +# +# Jack Jansen, CWI, August 1995. +# +# The module is supposed to be as compatible as possible. Especially the +# easy interface should work "as expected" on any platform. +# XXXX Note: currently, textfiles appear in mac-form on all platforms. +# We seem to lack a simple character-translate in python. +# (we should probably use ISO-Latin-1 on all but the mac platform). +# XXXX The simple routines are too simple: they expect to hold the complete +# files in-core. Should be fixed. +# XXXX It would be nice to handle AppleDouble format on unix +# (for servers serving macs). +# XXXX I don't understand what happens when you get 0x90 times the same byte on +# input. The resulting code (xx 90 90) would appear to be interpreted as an +# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety... +# +import sys +import os +import struct +import binascii + +__all__ = ["binhex","hexbin","Error"] + +class Error(Exception): + pass + +# States (what have we written) +[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3) + +# Various constants +REASONABLY_LARGE=32768 # Minimal amount we pass the rle-coder +LINELEN=64 +RUNCHAR=chr(0x90) # run-length introducer + +# +# This code is no longer byte-order dependent + +# +# Workarounds for non-mac machines. +if os.name == 'mac': + import macfs + import MacOS + try: + openrf = MacOS.openrf + except AttributeError: + # Backward compatibility + openrf = open + + def FInfo(): + return macfs.FInfo() + + def getfileinfo(name): + finfo = macfs.FSSpec(name).GetFInfo() + dir, file = os.path.split(name) + # XXXX Get resource/data sizes + fp = open(name, 'rb') + fp.seek(0, 2) + dlen = fp.tell() + fp = openrf(name, '*rb') + fp.seek(0, 2) + rlen = fp.tell() + return file, finfo, dlen, rlen + + def openrsrc(name, *mode): + if not mode: + mode = '*rb' + else: + mode = '*' + mode[0] + return openrf(name, mode) + +else: + # + # Glue code for non-macintosh usage + # + + class FInfo: + def __init__(self): + self.Type = '????' + self.Creator = '????' + self.Flags = 0 + + def getfileinfo(name): + finfo = FInfo() + # Quick check for textfile + fp = open(name) + data = open(name).read(256) + for c in data: + if not c.isspace() and (c<' ' or ord(c) > 0x7f): + break + else: + finfo.Type = 'TEXT' + fp.seek(0, 2) + dsize = fp.tell() + fp.close() + dir, file = os.path.split(name) + file = file.replace(':', '-', 1) + return file, finfo, dsize, 0 + + class openrsrc: + def __init__(self, *args): + pass + + def read(self, *args): + return '' + + def write(self, *args): + pass + + def close(self): + pass + +class _Hqxcoderengine: + """Write data to the coder in 3-byte chunks""" + + def __init__(self, ofp): + self.ofp = ofp + self.data = '' + self.hqxdata = '' + self.linelen = LINELEN-1 + + def write(self, data): + self.data = self.data + data + datalen = len(self.data) + todo = (datalen//3)*3 + data = self.data[:todo] + self.data = self.data[todo:] + if not data: + return + self.hqxdata = self.hqxdata + binascii.b2a_hqx(data) + self._flush(0) + + def _flush(self, force): + first = 0 + while first <= len(self.hqxdata)-self.linelen: + last = first + self.linelen + self.ofp.write(self.hqxdata[first:last]+'\n') + self.linelen = LINELEN + first = last + self.hqxdata = self.hqxdata[first:] + if force: + self.ofp.write(self.hqxdata + ':\n') + + def close(self): + if self.data: + self.hqxdata = \ + self.hqxdata + binascii.b2a_hqx(self.data) + self._flush(1) + self.ofp.close() + del self.ofp + +class _Rlecoderengine: + """Write data to the RLE-coder in suitably large chunks""" + + def __init__(self, ofp): + self.ofp = ofp + self.data = '' + + def write(self, data): + self.data = self.data + data + if len(self.data) < REASONABLY_LARGE: + return + rledata = binascii.rlecode_hqx(self.data) + self.ofp.write(rledata) + self.data = '' + + def close(self): + if self.data: + rledata = binascii.rlecode_hqx(self.data) + self.ofp.write(rledata) + self.ofp.close() + del self.ofp + +class BinHex: + def __init__(self, (name, finfo, dlen, rlen), ofp): + if type(ofp) == type(''): + ofname = ofp + ofp = open(ofname, 'w') + if os.name == 'mac': + fss = macfs.FSSpec(ofname) + fss.SetCreatorType('BnHq', 'TEXT') + ofp.write('(This file must be converted with BinHex 4.0)\n\n:') + hqxer = _Hqxcoderengine(ofp) + self.ofp = _Rlecoderengine(hqxer) + self.crc = 0 + if finfo is None: + finfo = FInfo() + self.dlen = dlen + self.rlen = rlen + self._writeinfo(name, finfo) + self.state = _DID_HEADER + + def _writeinfo(self, name, finfo): + name = name + nl = len(name) + if nl > 63: + raise Error, 'Filename too long' + d = chr(nl) + name + '\0' + d2 = finfo.Type + finfo.Creator + + # Force all structs to be packed with big-endian + d3 = struct.pack('>h', finfo.Flags) + d4 = struct.pack('>ii', self.dlen, self.rlen) + info = d + d2 + d3 + d4 + self._write(info) + self._writecrc() + + def _write(self, data): + self.crc = binascii.crc_hqx(data, self.crc) + self.ofp.write(data) + + def _writecrc(self): + # XXXX Should this be here?? + # self.crc = binascii.crc_hqx('\0\0', self.crc) + self.ofp.write(struct.pack('>H', self.crc)) + self.crc = 0 + + def write(self, data): + if self.state != _DID_HEADER: + raise Error, 'Writing data at the wrong time' + self.dlen = self.dlen - len(data) + self._write(data) + + def close_data(self): + if self.dlen != 0: + raise Error, 'Incorrect data size, diff='+`self.rlen` + self._writecrc() + self.state = _DID_DATA + + def write_rsrc(self, data): + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Writing resource data at the wrong time' + self.rlen = self.rlen - len(data) + self._write(data) + + def close(self): + if self.state < _DID_DATA: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Close at the wrong time' + if self.rlen != 0: + raise Error, \ + "Incorrect resource-datasize, diff="+`self.rlen` + self._writecrc() + self.ofp.close() + self.state = None + del self.ofp + +def binhex(inp, out): + """(infilename, outfilename) - Create binhex-encoded copy of a file""" + finfo = getfileinfo(inp) + ofp = BinHex(finfo, out) + + ifp = open(inp, 'rb') + # XXXX Do textfile translation on non-mac systems + while 1: + d = ifp.read(128000) + if not d: break + ofp.write(d) + ofp.close_data() + ifp.close() + + ifp = openrsrc(inp, 'rb') + while 1: + d = ifp.read(128000) + if not d: break + ofp.write_rsrc(d) + ofp.close() + ifp.close() + +class _Hqxdecoderengine: + """Read data via the decoder in 4-byte chunks""" + + def __init__(self, ifp): + self.ifp = ifp + self.eof = 0 + + def read(self, totalwtd): + """Read at least wtd bytes (or until EOF)""" + decdata = '' + wtd = totalwtd + # + # The loop here is convoluted, since we don't really now how + # much to decode: there may be newlines in the incoming data. + while wtd > 0: + if self.eof: return decdata + wtd = ((wtd+2)//3)*4 + data = self.ifp.read(wtd) + # + # Next problem: there may not be a complete number of + # bytes in what we pass to a2b. Solve by yet another + # loop. + # + while 1: + try: + decdatacur, self.eof = \ + binascii.a2b_hqx(data) + break + except binascii.Incomplete: + pass + newdata = self.ifp.read(1) + if not newdata: + raise Error, \ + 'Premature EOF on binhex file' + data = data + newdata + decdata = decdata + decdatacur + wtd = totalwtd - len(decdata) + if not decdata and not self.eof: + raise Error, 'Premature EOF on binhex file' + return decdata + + def close(self): + self.ifp.close() + +class _Rledecoderengine: + """Read data via the RLE-coder""" + + def __init__(self, ifp): + self.ifp = ifp + self.pre_buffer = '' + self.post_buffer = '' + self.eof = 0 + + def read(self, wtd): + if wtd > len(self.post_buffer): + self._fill(wtd-len(self.post_buffer)) + rv = self.post_buffer[:wtd] + self.post_buffer = self.post_buffer[wtd:] + return rv + + def _fill(self, wtd): + self.pre_buffer = self.pre_buffer + self.ifp.read(wtd+4) + if self.ifp.eof: + self.post_buffer = self.post_buffer + \ + binascii.rledecode_hqx(self.pre_buffer) + self.pre_buffer = '' + return + + # + # Obfuscated code ahead. We have to take care that we don't + # end up with an orphaned RUNCHAR later on. So, we keep a couple + # of bytes in the buffer, depending on what the end of + # the buffer looks like: + # '\220\0\220' - Keep 3 bytes: repeated \220 (escaped as \220\0) + # '?\220' - Keep 2 bytes: repeated something-else + # '\220\0' - Escaped \220: Keep 2 bytes. + # '?\220?' - Complete repeat sequence: decode all + # otherwise: keep 1 byte. + # + mark = len(self.pre_buffer) + if self.pre_buffer[-3:] == RUNCHAR + '\0' + RUNCHAR: + mark = mark - 3 + elif self.pre_buffer[-1] == RUNCHAR: + mark = mark - 2 + elif self.pre_buffer[-2:] == RUNCHAR + '\0': + mark = mark - 2 + elif self.pre_buffer[-2] == RUNCHAR: + pass # Decode all + else: + mark = mark - 1 + + self.post_buffer = self.post_buffer + \ + binascii.rledecode_hqx(self.pre_buffer[:mark]) + self.pre_buffer = self.pre_buffer[mark:] + + def close(self): + self.ifp.close() + +class HexBin: + def __init__(self, ifp): + if type(ifp) == type(''): + ifp = open(ifp) + # + # Find initial colon. + # + while 1: + ch = ifp.read(1) + if not ch: + raise Error, "No binhex data found" + # Cater for \r\n terminated lines (which show up as \n\r, hence + # all lines start with \r) + if ch == '\r': + continue + if ch == ':': + break + if ch != '\n': + dummy = ifp.readline() + + hqxifp = _Hqxdecoderengine(ifp) + self.ifp = _Rledecoderengine(hqxifp) + self.crc = 0 + self._readheader() + + def _read(self, len): + data = self.ifp.read(len) + self.crc = binascii.crc_hqx(data, self.crc) + return data + + def _checkcrc(self): + filecrc = struct.unpack('>h', self.ifp.read(2))[0] & 0xffff + #self.crc = binascii.crc_hqx('\0\0', self.crc) + # XXXX Is this needed?? + self.crc = self.crc & 0xffff + if filecrc != self.crc: + raise Error, 'CRC error, computed %x, read %x' \ + %(self.crc, filecrc) + self.crc = 0 + + def _readheader(self): + len = self._read(1) + fname = self._read(ord(len)) + rest = self._read(1+4+4+2+4+4) + self._checkcrc() + + type = rest[1:5] + creator = rest[5:9] + flags = struct.unpack('>h', rest[9:11])[0] + self.dlen = struct.unpack('>l', rest[11:15])[0] + self.rlen = struct.unpack('>l', rest[15:19])[0] + + self.FName = fname + self.FInfo = FInfo() + self.FInfo.Creator = creator + self.FInfo.Type = type + self.FInfo.Flags = flags + + self.state = _DID_HEADER + + def read(self, *n): + if self.state != _DID_HEADER: + raise Error, 'Read data at wrong time' + if n: + n = n[0] + n = min(n, self.dlen) + else: + n = self.dlen + rv = '' + while len(rv) < n: + rv = rv + self._read(n-len(rv)) + self.dlen = self.dlen - n + return rv + + def close_data(self): + if self.state != _DID_HEADER: + raise Error, 'close_data at wrong time' + if self.dlen: + dummy = self._read(self.dlen) + self._checkcrc() + self.state = _DID_DATA + + def read_rsrc(self, *n): + if self.state == _DID_HEADER: + self.close_data() + if self.state != _DID_DATA: + raise Error, 'Read resource data at wrong time' + if n: + n = n[0] + n = min(n, self.rlen) + else: + n = self.rlen + self.rlen = self.rlen - n + return self._read(n) + + def close(self): + if self.rlen: + dummy = self.read_rsrc(self.rlen) + self._checkcrc() + self.state = _DID_RSRC + self.ifp.close() + +def hexbin(inp, out): + """(infilename, outfilename) - Decode binhexed file""" + ifp = HexBin(inp) + finfo = ifp.FInfo + if not out: + out = ifp.FName + if os.name == 'mac': + ofss = macfs.FSSpec(out) + out = ofss.as_pathname() + + ofp = open(out, 'wb') + # XXXX Do translation on non-mac systems + while 1: + d = ifp.read(128000) + if not d: break + ofp.write(d) + ofp.close() + ifp.close_data() + + d = ifp.read_rsrc(128000) + if d: + ofp = openrsrc(out, 'wb') + ofp.write(d) + while 1: + d = ifp.read_rsrc(128000) + if not d: break + ofp.write(d) + ofp.close() + + if os.name == 'mac': + nfinfo = ofss.GetFInfo() + nfinfo.Creator = finfo.Creator + nfinfo.Type = finfo.Type + nfinfo.Flags = finfo.Flags + ofss.SetFInfo(nfinfo) + + ifp.close() + +def _test(): + if os.name == 'mac': + fss, ok = macfs.PromptGetFile('File to convert:') + if not ok: + sys.exit(0) + fname = fss.as_pathname() + else: + fname = sys.argv[1] + binhex(fname, fname+'.hqx') + hexbin(fname+'.hqx', fname+'.viahqx') + #hexbin(fname, fname+'.unpacked') + sys.exit(1) + +if __name__ == '__main__': + _test() Added: pypy/dist/lib-python/modified-2.3.4/test/test_binhex.py ============================================================================== --- (empty file) +++ pypy/dist/lib-python/modified-2.3.4/test/test_binhex.py Mon Jul 4 15:50:46 2005 @@ -0,0 +1,48 @@ +#! /usr/bin/env python +"""Test script for the binhex C module + + Uses the mechanism of the python binhex module + Based on an original test by Roger E. Masse. +""" +import unittest +from test import test_support +import binhex +import os + +class BinHexTestCase(unittest.TestCase): + + def setUp(self): + self.fname1 = test_support.TESTFN + "1" + self.fname2 = test_support.TESTFN + "2" + + def tearDown(self): + try: os.unlink(self.fname1) + except OSError: pass + + try: os.unlink(self.fname2) + except OSError: pass + + DATA = 'Jack is my hero' + + def test_binhex(self): + f = open(self.fname1, 'w') + f.write(self.DATA) + f.close() + + binhex.binhex(self.fname1, self.fname2) + + binhex.hexbin(self.fname2, self.fname1) + + f = open(self.fname1, 'r') + finish = f.readline() + f.close() + + self.assertEqual(self.DATA, finish) + + +def test_main(): + test_support.run_unittest(BinHexTestCase) + + +if __name__ == "__main__": + test_main() From jacob at codespeak.net Mon Jul 4 15:52:47 2005 From: jacob at codespeak.net (jacob at codespeak.net) Date: Mon, 4 Jul 2005 15:52:47 +0200 (CEST) Subject: [pypy-svn] r14216 - pypy/dist/pypy/lib Message-ID: <20050704135247.5A23627B47@code1.codespeak.net> Author: jacob Date: Mon Jul 4 15:52:46 2005 New Revision: 14216 Modified: pypy/dist/pypy/lib/struct.py Log: Fixed spelling. Modified: pypy/dist/pypy/lib/struct.py ============================================================================== --- pypy/dist/pypy/lib/struct.py (original) +++ pypy/dist/pypy/lib/struct.py Mon Jul 4 15:52:46 2005 @@ -108,7 +108,7 @@ if not isinstance(number, (int,long)): raise StructError,"argument for i,I,l,L,q,Q,h,H must be integer" if number > 2**(8*size-1)-1 or number < -1*2**(8*size-1): - raise OverflowError,"Number:%i to large to convert" % number + raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) def pack_unsigned_int(number,size,le): @@ -117,7 +117,7 @@ if number < 0: raise TypeError,"can't convert negative long to unsigned" if number > 2**(8*size)-1: - raise OverflowError,"Number:%i to large to convert" % number + raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) def pack_char(char,size,le): From jacob at codespeak.net Mon Jul 4 15:53:21 2005 From: jacob at codespeak.net (jacob at codespeak.net) Date: Mon, 4 Jul 2005 15:53:21 +0200 (CEST) Subject: [pypy-svn] r14217 - pypy/dist/pypy/lib Message-ID: <20050704135321.0839427B4A@code1.codespeak.net> Author: jacob Date: Mon Jul 4 15:53:20 2005 New Revision: 14217 Modified: pypy/dist/pypy/lib/binascii.py Log: Now passes the binhex test. Refactoring done. Modified: pypy/dist/pypy/lib/binascii.py ============================================================================== --- pypy/dist/pypy/lib/binascii.py (original) +++ pypy/dist/pypy/lib/binascii.py Mon Jul 4 15:53:20 2005 @@ -1,64 +1,66 @@ class Error(Exception): pass +class Apa(Exception): + pass + class Incomplete(Exception): pass def a2b_uu(s): length = (ord(s[0]) - 0x20) % 64 - a = quadruplets(s[1:].rstrip()) + + def quadruplets_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) + except IndexError: + s += ' ' + yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) + return + s = s[4:] + try: result = [''.join( [chr((A - 0x20) << 2 | (((B - 0x20) >> 4) & 0x3)), - chr(((B - 0x20) & 0xF) << 4 | (((C - 0x20) >> 2) & 0xF)), - chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3F)) - ]) for A, B, C, D in a] + chr(((B - 0x20) & 0xf) << 4 | (((C - 0x20) >> 2) & 0xf)), + chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3f)) + ]) for A, B, C, D in quadruplets_gen(s[1:].rstrip())] except ValueError: - raise Error, 'Illegal char' + raise Error('Illegal char') result = ''.join(result) trailingdata = result[length:] if trailingdata.strip('\x00'): - raise Error, 'Trailing garbage' + raise Error('Trailing garbage') result = result[:length] if len(result) < length: result += ((length - len(result)) * '\x00') return result -def quadruplets(s): - while s: - try: - a, b, c, d = s[0], s[1], s[2], s[3] - except IndexError: - s += ' ' - yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) - return - s = s[4:] - yield ord(a), ord(b), ord(c), ord(d) def b2a_uu(s): length = len(s) if length > 45: - raise Error, 'At most 45 bytes at once' + raise Error('At most 45 bytes at once') + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + s += '\0\0' + yield ord(s[0]), ord(s[1]), ord(s[2]) + return + s = s[3:] - a = triples(s) result = [''.join( [chr(0x20 + (( A >> 2 ) & 0x3F)), chr(0x20 + (((A << 4) | ((B >> 4) & 0xF)) & 0x3F)), chr(0x20 + (((B << 2) | ((C >> 6) & 0x3)) & 0x3F)), - chr(0x20 + (( C ) & 0x3F))]) for A, B, C in a] + chr(0x20 + (( C ) & 0x3F))]) + for A, B, C in triples_gen(s)] return chr(ord(' ') + (length & 077)) + ''.join(result) + '\n' -def triples(s): - while s: - try: - a, b, c = s[0], s[1], s[2] - except IndexError: - s += '\0\0' - yield ord(s[0]), ord(s[1]), ord(s[2]) - return - s = s[3:] - yield ord(a), ord(b), ord(c) - table_a2b_base64 = { 'A': 0, @@ -127,11 +129,6 @@ '/': 63, } -def quadruplets_base64(s): - while s: - a, b, c, d = table_a2b_base64[s[0]], table_a2b_base64[s[1]], table_a2b_base64[s[2]], table_a2b_base64[s[3]] - s = s[4:] - yield a, b, c, d def a2b_base64(s): s = s.rstrip() @@ -145,12 +142,19 @@ if len(s) % 4: s = s + ('=' * (4 - len(s) % 4)) - a = quadruplets_base64(s[:-4]) + def quadruplets_gen(s): + while s: + yield (table_a2b_base64[s[0]], + table_a2b_base64[s[1]], + table_a2b_base64[s[2]], + table_a2b_base64[s[3]]) + s = s[4:] + result = [ chr(A << 2 | ((B >> 4) & 0x3)) + - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) + chr((C & 0x3) << 6 | D ) - for A, B, C, D in a] + for A, B, C, D in quadruplets_gen(s[:-4])] if s: final = s[-4:] @@ -163,14 +167,14 @@ B = table_a2b_base64[final[1]] C = table_a2b_base64[final[2]] snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) else: A = table_a2b_base64[final[0]] B = table_a2b_base64[final[1]] C = table_a2b_base64[final[2]] D = table_a2b_base64[final[3]] snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + \ + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) + \ chr((C & 0x3) << 6 | D ) result.append(snippet) @@ -182,8 +186,19 @@ def b2a_base64(s): length = len(s) final_length = length % 3 + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + s += '\0\0' + yield ord(s[0]), ord(s[1]), ord(s[2]) + return + s = s[3:] + - a = triples(s[ :length - final_length]) + a = triples_gen(s[ :length - final_length]) result = [''.join( [table_b2a_base64[( A >> 2 ) & 0x3F], @@ -278,19 +293,20 @@ else: sign = '' arr = [] - for nibble in hexgen(n): + + def hex_gen(n): + """ Yield a nibble at a time. """ + while n: + yield n % 0x10 + n = n / 0x10 + + for nibble in hex_gen(n): arr = [hex_numbers[nibble]] + arr return sign + ''.join(arr) def two_hex_digits(n): return hex_numbers[n / 0x10] + hex_numbers[n % 0x10] -def hexgen(n): - """ Yield a nibble at a time. """ - while n: - remainder = n % 0x10 - n = n / 0x10 - yield remainder def strhex_to_int(s): i = 0 @@ -299,46 +315,115 @@ return i hqx_encoding = '!"#$%&\'()*+,-012345689 at ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr' -# Make a fast lookup dictionary for decoding hqx -hqx_decoding = {} -for i, c in enumerate(hqx_encoding): - hqx_decoding[c] = i + +DONE = 0x7f +SKIP = 0x7e +FAIL = 0x7d -def unpadded_quadruples(s): - while s: - yield s[:4] - s = s[4:] +table_a2b_hqx = [ + #^@ ^A ^B ^C ^D ^E ^F ^G + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + #\b \t \n ^K ^L \r ^N ^O + FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL, + #^P ^Q ^R ^S ^T ^U ^V ^W + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + #^X ^Y ^Z ^[ ^\ ^] ^^ ^_ + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + # ! " # $ % & ' + FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + #( ) * + , - . / + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL, + #0 1 2 3 4 5 6 7 + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL, + #8 9 : ; < = > ? + 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL, + #@ A B C D E F G + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + #H I J K L M N O + 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL, + #P Q R S T U V W + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL, + #X Y Z [ \ ] ^ _ + 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL, + #` a b c d e f g + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL, + #h i j k l m n o + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL, + #p q r s t u v w + 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL, + #x y z { | } ~ ^? + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +] def a2b_hqx(s): - decoded = [] - for c in s: - decoded.append(hqx_decoding[c]) - gen = unpadded_quadruples(decoded) result = [] - for snippet in gen: - length = len(snippet) - if length == 4: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - result.append(chr((snippet[2] << 6) | (snippet[3]))) - elif length == 3: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - elif length == 2: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - else: - raise TypeError('Wrong number of characters.') - return ''.join(result) -def unpadded_triples(s): - while s: - yield [ord(c) for c in s[:3]] - s = s[3:] + def quadruples_gen(s): + t = [] + for c in s: + res = table_a2b_hqx[ord(c)] + if res == SKIP: + continue + elif res == FAIL: + raise Error('Illegal character') + elif res == DONE: + yield t + print 'raising' + raise Apa + else: + t.append(res) + if len(t) == 4: + yield t + t = [] + yield t + + done = 0 + try: + for snippet in quadruples_gen(s): + length = len(snippet) + if length == 4: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2))) + result.append(chr(((snippet[2] & 0x03) << 6) | (snippet[3]))) + elif length == 3: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2))) + elif length == 2: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + except Apa: + done = 1 + except Error: + raise + return (''.join(result), done) def b2a_hqx(s): result =[] - gen = unpadded_triples(s) - for snippet in gen: + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + yield tuple([ord(c) for c in s]) + s = s[3:] + + for snippet in triples_gen(s): length = len(snippet) if length == 3: result.append( @@ -399,11 +484,16 @@ def crc_hqx(s, crc): for c in s: - crc=((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ c] + crc = ((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ ord(c)] return crc def rlecode_hqx(s): + """ + Run length encoding for binhex4. + The CPython implementation does not do run length encoding + of \x90 characters. This implementation does. + """ result = [] prev = s[0] count = 1 @@ -558,16 +648,14 @@ def pairs_gen(s): while s: try: - a, b = s[0], s[1] + yield table_hex[ord(s[0])], table_hex[ord(s[1])] except IndexError: if len(s): raise TypeError('Odd-length string') return s = s[2:] - yield table_hex[ord(a)], table_hex[ord(b)] - pairs = pairs_gen(t) - for a, b in pairs: + for a, b in pairs_gen(t): if a < 0 or b < 0: raise TypeError('Non-hexadecimal digit found') result.append(chr((a << 4) + b)) From adim at codespeak.net Mon Jul 4 15:56:47 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 15:56:47 +0200 (CEST) Subject: [pypy-svn] r14218 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050704135647.5639E27B4F@code1.codespeak.net> Author: adim Date: Mon Jul 4 15:56:46 2005 New Revision: 14218 Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: single inputs must be processed as exec statements Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Mon Jul 4 15:56:46 2005 @@ -11,7 +11,7 @@ TARGET_DICT = { 'exec' : "file_input", 'eval' : "eval_input", - 'single' : "single_input", + 'single' : "file_input", } ## convenience functions around CPython's parser functions @@ -27,11 +27,11 @@ """parse python source using CPython's parser module and return nested tuples """ - if mode == 'exec': - tp = parser.suite(source) - else: + if mode == 'eval': tp = parser.expr(source) - return tp.totuple() + else: + tp = parser.suite(source) + return parser.ast2tuple(tp, line_info=lineno) ## convenience functions around recparser functions def pypy_parsefile(filename, lineno=False): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Mon Jul 4 15:56:46 2005 @@ -100,6 +100,12 @@ for snippet in snippets: yield check_parse_input, snippet, 'exec' +def test_single_inputs(): + snippets = ['a=1', 'True', 'def f(a):\n return a+1\n\n'] + for snippet in snippets: + yield check_parse_input, snippet, 'single' + + def test_bad_inputs(): inputs = ['x = (', 'x = (\n', 'x = (\n\n'] for inp in inputs: From adim at codespeak.net Mon Jul 4 16:14:48 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 16:14:48 +0200 (CEST) Subject: [pypy-svn] r14220 - pypy/dist/pypy/interpreter/test Message-ID: <20050704141448.7C6F927B55@code1.codespeak.net> Author: adim Date: Mon Jul 4 16:14:47 2005 New Revision: 14220 Modified: pypy/dist/pypy/interpreter/test/test_compiler.py Log: added test to make sure single inputs are correctly handled Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Mon Jul 4 16:14:47 2005 @@ -48,6 +48,16 @@ flags2 = self.compiler.getcodeflags(code2) assert flags == flags2 + def test_interactivemode(self): + code = self.compiler.compile('a = 1', '', 'single', 0) + assert isinstance(code, PyCode) + assert code.co_filename == '' + space = self.space + w_globals = space.newdict([]) + code.exec_code(space, w_globals, w_globals) + w_a = space.getitem(w_globals, space.wrap('a')) + assert space.int_w(w_a) == 1 + class TestECCompiler(BaseTestCompiler): def setup_method(self, method): @@ -64,3 +74,4 @@ class SkippedForNowTestPyPyCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = PyPyCompiler(self.space) + From adim at codespeak.net Mon Jul 4 16:39:19 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 16:39:19 +0200 (CEST) Subject: [pypy-svn] r14224 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20050704143919.5D08927B56@code1.codespeak.net> Author: adim Date: Mon Jul 4 16:39:18 2005 New Revision: 14224 Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py Log: fixed the WalkerEror bug in astcompiler also Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/transformer.py Mon Jul 4 16:39:18 2005 @@ -89,7 +89,7 @@ print nodes[kind], len(args), args raise else: - raise WalkerEror, "Can't find appropriate Node type: %s" % str(args) + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) #return apply(ast.Node, args) class Transformer: @@ -165,7 +165,7 @@ if n == symbol.classdef: return self.classdef(node[1:]) - raise WalkerEror, ('unexpected node type', n) + raise WalkerError, ('unexpected node type', n) def single_input(self, node): ### do we want to do anything about being "interactive" ? @@ -314,31 +314,31 @@ return Stmt(stmts) def parameters(self, nodelist): - raise WalkerEror + raise WalkerError def varargslist(self, nodelist): - raise WalkerEror + raise WalkerError def fpdef(self, nodelist): - raise WalkerEror + raise WalkerError def fplist(self, nodelist): - raise WalkerEror + raise WalkerError def dotted_name(self, nodelist): - raise WalkerEror + raise WalkerError def comp_op(self, nodelist): - raise WalkerEror + raise WalkerError def trailer(self, nodelist): - raise WalkerEror + raise WalkerError def sliceop(self, nodelist): - raise WalkerEror + raise WalkerError def argument(self, nodelist): - raise WalkerEror + raise WalkerError # -------------------------------------------------------------- # From ac at codespeak.net Mon Jul 4 17:28:43 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 4 Jul 2005 17:28:43 +0200 (CEST) Subject: [pypy-svn] r14227 - pypy/branch/dist-2.4.1/pypy/objspace/std Message-ID: <20050704152843.15BE827B45@code1.codespeak.net> Author: ac Date: Mon Jul 4 17:28:42 2005 New Revision: 14227 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py Log: str.center() should not return a unicode string unless the fillchar is unicode. Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py Mon Jul 4 17:28:42 2005 @@ -639,6 +639,7 @@ return _strip_none(space, w_self, left=1, right=0) + def str_center__String_ANY_ANY(space, w_self, w_arg, w_fillchar): u_self = w_self._value u_arg = space.int_w(w_arg) @@ -656,6 +657,11 @@ u_centered = u_self return W_StringObject(space, u_centered) + +# This is so that str_center__String_ANY_Unicode in unicodeobject +# won't convert a String fillchar +def str_center__String_ANY_String(space, w_self, w_arg, w_fillchar): + return str_center__String_ANY_ANY(space, w_self, w_arg, w_fillchar) def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py Mon Jul 4 17:28:42 2005 @@ -916,6 +916,7 @@ 'rsplit', w_delim, w_maxsplit) def str_center__String_ANY_Unicode(space, w_self, w_width, w_fillchar): + print 'Centering a string with unicode.' return space.call_method(space.call_function(space.w_unicode, w_self), 'center', w_width, w_fillchar) From ericvrp at codespeak.net Mon Jul 4 17:40:01 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 17:40:01 +0200 (CEST) Subject: [pypy-svn] r14228 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050704154001.E4A2027B45@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 17:40:00 2005 New Revision: 14228 Added: pypy/dist/pypy/translator/llvm2/atomic.py Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py Log: Added notion of atomic structures Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Mon Jul 4 17:40:00 2005 @@ -44,6 +44,8 @@ store int %len, int* %arraylength ret %array* %result }""" + from pypy.translator.llvm2.atomic import is_atomic + log.writeimpl(self.ref) codewriter.openfunc(self.constructor_decl) indices = [("uint", 1), ("int", "%len")] @@ -51,7 +53,7 @@ "null", *indices) fromtype = self.db.repr_arg_type(self.array.OF) codewriter.cast("%usize", fromtype + "*", "%size", "uint") - codewriter.malloc("%ptr", "sbyte", "%usize", atomic=False) + codewriter.malloc("%ptr", "sbyte", "%usize", atomic=is_atomic(self)) codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) codewriter.store("int", "%len", "%arraylength") Added: pypy/dist/pypy/translator/llvm2/atomic.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/atomic.py Mon Jul 4 17:40:00 2005 @@ -0,0 +1,16 @@ +from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.structnode import StructTypeNode +from pypy.translator.llvm2.arraynode import ArrayTypeNode + +log = log.atomic + +def is_atomic(node): + if isinstance(node, StructTypeNode): + fields = str([getattr(node.struct, name) for name in node.struct._names_without_voids()]) + if '*' not in fields: + return True #non-pointers only + return False #contains pointer(s) + elif isinstance(node, ArrayTypeNode): + return False #because they actually are arrays of pointers + log("unknown type %s, assuming non-atomic" % str(type(node))) + return False Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Mon Jul 4 17:40:00 2005 @@ -5,6 +5,7 @@ from pypy.translator.backendoptimization import remove_same_as from pypy.translator.unsimplify import remove_double_links from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log log = log.funcnode @@ -251,8 +252,9 @@ assert (isinstance(arg, Constant) and isinstance(arg.value, lltype.Struct)) #XXX unclean - type = self.db.obj2node[arg.value].ref - self.codewriter.malloc(targetvar, type, atomic=False) + node = self.db.obj2node[arg.value] + type_ = node.ref + self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) def malloc_varsize(self, op): targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Mon Jul 4 17:40:00 2005 @@ -48,6 +48,8 @@ codewriter.declare(self.constructor_name) def writeimpl(self, codewriter): + from pypy.translator.llvm2.atomic import is_atomic + log.writeimpl(self.ref) codewriter.openfunc(self.constructor_name) codewriter.label("block0") @@ -65,7 +67,7 @@ #XXX is this ok for 64bit? codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=False) + codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=is_atomic(self)) codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") # remember the allocated length for later use. From adim at codespeak.net Mon Jul 4 17:54:33 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 17:54:33 +0200 (CEST) Subject: [pypy-svn] r14229 - in pypy/dist/pypy/interpreter: . pyparser Message-ID: <20050704155433.D591727B47@code1.codespeak.net> Author: adim Date: Mon Jul 4 17:54:32 2005 New Revision: 14229 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Log: quick (hack) fix for using incomplete inputs in interactive interpreter when using the '--pyparse' option Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Mon Jul 4 17:54:32 2005 @@ -68,7 +68,7 @@ if not err2.match(space, space.w_SyntaxError): raise - if space.eq_w(err1.w_value, err2.w_value): + if mode != 'single' and space.eq_w(err1.w_value, err2.w_value): raise # twice the same error, re-raise return None # two different errors, expect more Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Mon Jul 4 17:54:32 2005 @@ -288,10 +288,12 @@ tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) - + lnum += 1 + ## adim - token_list.append((Token('NEWLINE', ''), line, lnum, 0)) + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) ## + lnum += 1 tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) From rxe at codespeak.net Mon Jul 4 18:05:17 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 4 Jul 2005 18:05:17 +0200 (CEST) Subject: [pypy-svn] r14231 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050704160517.7D2CD27B45@code1.codespeak.net> Author: rxe Date: Mon Jul 4 18:05:16 2005 New Revision: 14231 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: A first iteration at getting pbc to work. Tests pass. Clean up time. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Mon Jul 4 18:05:16 2005 @@ -2,11 +2,15 @@ from pypy.rpython import lltype from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode +from pypy.objspace.flow.model import Constant import itertools log = log.structnode count = itertools.count().next +def wrapstr(s): + return '"%s"' % s + class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): @@ -14,12 +18,10 @@ assert isinstance(array, lltype.Array) self.array = array c = count() - ref_template = "%%array.%s." + str(c) - ref_template = '"%s"' % ref_template - arrayname = str(self.array.OF) - self.ref = ref_template % arrayname - constructor_ref = "%%new.array.%s" % c - self.constructor_ref = '"%s"' % constructor_ref + ref_template = wrapstr("%%array.%s." + str(c)) + + self.ref = ref_template % array.OF + self.constructor_ref = wrapstr("%%new.array.%s" % c) self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -80,9 +82,8 @@ def __init__(self, db, value): self.db = db - name = "%s.%s" % (value._TYPE.OF, ArrayNode.array_counter) - self.ref = "%%stinstance.%s" % name - self.dataref = self.ref + ".tmp" + name = '"%%arrayinstance.%s.%s"' % (value._TYPE.OF, ArrayNode.array_counter) + self.ref = name self.value = value ArrayNode.array_counter += 1 @@ -93,14 +94,15 @@ T = self.value._TYPE.OF for item in self.value.items: if not isinstance(T, lltype.Primitive): - value = getattr(self.value, name) # Create a dummy constant hack XXX - c = Constant(value, T) + c = Constant(item, T) self.db.prepare_arg(c) self._issetup = True - def get_values(self): + def getall(self): + arraylen = len(self.value.items) + res = [] T = self.value._TYPE.OF @@ -113,14 +115,17 @@ value = repr(value) res.append((typval, value)) - return ", ".join(["%s %s" % (t, v) for t, v in res]) + arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) + type_ = "{ int, [%s x %s] }" % (len(self.value.items), + self.db.repr_arg_type(self.value._TYPE.OF)) + + value = "int %s, [%s x %s] [ %s ]" % (arraylen, + arraylen, + typval, + arrayvalues) + return type_, value + def writeglobalconstants(self, codewriter): - lenitems = len(self.value.items) - lenstr = ".%s" % lenitems - codewriter.globalinstance(self.ref, - self.db.repr_arg_type(self.value._TYPE), - "null") - #codewriter.globalinstance(self.dataref, - # self.db.repr_arg_type(self.value._TYPE), - # self.get_values()) + type_, values = self.getall() + codewriter.globalinstance(self.ref, type_, values) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Mon Jul 4 18:05:16 2005 @@ -1,6 +1,7 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode -from pypy.translator.llvm2.structnode import StructNode, StructTypeNode, StructVarsizeTypeNode +from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ + StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -82,7 +83,11 @@ value = value._obj if isinstance(ct, lltype.Struct): - self.addpending(const_or_var, StructNode(self, value)) + if ct._arrayfld: + assert False, "HERE" + self.addpending(const_or_var, StructVarsizeNode(self, value)) + else: + self.addpending(const_or_var, StructNode(self, value)) elif isinstance(ct, lltype.Array): self.addpending(const_or_var, ArrayNode(self, value)) @@ -141,7 +146,6 @@ if subset_types is None or isinstance(v, subset_types): res.append(v) return res - # __________________________________________________________ # Representing variables and constants in LLVM source code Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Mon Jul 4 18:05:16 2005 @@ -42,6 +42,9 @@ super(StructVarsizeTypeNode, self).__init__(db, struct) new_var_name = "%%new.st.var.%s" % self.name self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + + def __str__(self): + return "" %(self.ref,) def writedecl(self, codewriter): # declaration for constructor @@ -81,14 +84,22 @@ codewriter.ret(self.ref + "*", "%result") codewriter.closefunc() + +def cast_global(toptr, from_, name): + s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, + from_, + name, + toptr) + return s + class StructNode(LLVMNode): _issetup = False struct_counter = 0 def __init__(self, db, value): self.db = db - self.name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) - self.ref = "%%stinstance.%s" % self.name + name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) + self.ref = "%%stinstance.%s" % name self.value = value StructNode.struct_counter += 1 @@ -107,9 +118,40 @@ self._issetup = True - def get_values(self): + def getall(self): res = [] - for name in self.value._TYPE._names_without_voids(): + type_ = self.value._TYPE + for name in type_._names_without_voids(): + T = type_._flds[name] + value = getattr(self.value, name) + if not isinstance(T, lltype.Primitive): + # Create a dummy constant hack XXX + c = Constant(value, T) + x = self.db.obj2node[c] + value = self.db.repr_arg(c) + t, v = x.getall() + value = cast_global(self.db.repr_arg_type(T), t, value) + + else: + value = str(value) + res.append((self.db.repr_arg_type(T), value)) + + typestr = self.db.repr_arg_type(type_) + values = ", ".join(["%s %s" % (t, v) for t, v in res]) + return typestr, values + + def writeglobalconstants(self, codewriter): + type_, values = self.getall() + codewriter.globalinstance(self.ref, type_, values) + +class StructVarsizeNode(StructNode): + def __str__(self): + return "" %(self.ref,) + + def getall(self): + + res = [] + for name in self.value._TYPE._names_without_voids()[:-1]: T = self.value._TYPE._flds[name] value = getattr(self.value, name) if not isinstance(T, lltype.Primitive): @@ -118,10 +160,18 @@ else: value = str(value) res.append((self.db.repr_arg_type(T), value)) - return ", ".join(["%s %s" % (t, v) for t, v in res]) - - def writeglobalconstants(self, codewriter): - codewriter.globalinstance(self.ref, - self.db.repr_arg_type(self.value._TYPE), - self.get_values()) + # Special case for varsized arrays + self.value._TYPE._names_without_voids()[-1] + x = self.db.obj2node[Constant(value, T)] + t, v = x.get_values() + res.append((t, "{%s}" % v)) + + s = self.value._TYPE + fields = [getattr(s, name) for name in s._names_without_voids()[-1]] + l = [self.db.repr_arg_type(field) for field in fields] + l += t + typestr = "{ %s }" % ", ".join(l) + values = ", ".join(["%s %s" % (t, v) for t, v in res]) + return typestr, values + Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 18:05:16 2005 @@ -240,7 +240,7 @@ assert f(-1) == 3 assert f(0) == 5 -def DONOT_test_simple_chars(): +def Xtest_simple_chars(): def char_constant2(s): s = s + s + s return len(s + '.') @@ -265,14 +265,22 @@ f = compile_function(list_list_getitem, []) assert f() == 1 -def Xtest_list_getitem_pbc(): +def test_list_getitem_pbc(): l = [1,2] - def list_getitem(i): + def list_getitem_pbc(i): return l[i] - f = compile_function(list_getitem, [int], view=True) + f = compile_function(list_getitem_pbc, [int]) assert f(0) == 1 assert f(1) == 2 +def test_list_list_getitem_pbc(): + 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(): def list_basic_ops(i, j): l = [1,2,3] From arigo at codespeak.net Mon Jul 4 18:16:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Jul 2005 18:16:14 +0200 (CEST) Subject: [pypy-svn] r14233 - pypy/branch/dist-2.4.1/pypy/lib Message-ID: <20050704161614.2135227B45@code1.codespeak.net> Author: arigo Date: Mon Jul 4 18:16:12 2005 New Revision: 14233 Modified: pypy/branch/dist-2.4.1/pypy/lib/collections.py Log: Rewrote the collections module, mostly by copying it from the sandbox of CPython and then fixing a few bugs and adding missing methods. Pending: do we want to detect changes to the deque while it is being iterated over and raise RuntimeError, like CPython does? Modified: pypy/branch/dist-2.4.1/pypy/lib/collections.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/collections.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/collections.py Mon Jul 4 18:16:12 2005 @@ -1,56 +1,266 @@ -# Naive collections implementation +"""High performance data structures +""" +# +# Copied and completed from the sandbox of CPython +# (nondist/sandbox/collections/pydeque.py rev 1.1, Raymond Hettinger) +# -class deque(list): - def __init__(self, iter=None): - # Do not run init on list, as it will empty list; deque test_basic does: - # d = deque(xrange(100)) - # d.__init__(xrange(100, 200)) - if iter is not None: - self.extend(iter) +import operator +try: + from thread import get_ident as _thread_ident +except ImportError: + def _thread_ident(): + return -1 - def appendleft(self, item): - self.insert(0, item) + +n = 30 +LFTLNK = n +RGTLNK = n+1 +BLOCKSIZ = n+2 + +class deque(object): + + def __new__(cls, iterable=()): + self = super(deque, cls).__new__(cls) + self.clear() + return self + + def __init__(self, iterable=()): + add = self.append + for elem in iterable: + add(elem) def clear(self): - del self[:] + self.right = self.left = [None] * BLOCKSIZ + self.rightndx = n//2 # points to last written element + self.leftndx = n//2+1 + + def append(self, x): + self.rightndx += 1 + if self.rightndx == n: + newblock = [None] * BLOCKSIZ + self.right[RGTLNK] = newblock + newblock[LFTLNK] = self.right + self.right = newblock + self.rightndx = 0 + self.right[self.rightndx] = x + + def appendleft(self, x): + self.leftndx -= 1 + if self.leftndx == -1: + newblock = [None] * BLOCKSIZ + self.left[LFTLNK] = newblock + newblock[RGTLNK] = self.left + self.left = newblock + self.leftndx = n-1 + self.left[self.leftndx] = x + + def extend(self, iterable): + for elem in iterable: + self.append(elem) - def extendleft(self, other): - self[0:0] = [x for x in other][::-1] + def extendleft(self, iterable): + for elem in iterable: + self.appendleft(elem) + + def pop(self): + if self.left is self.right and self.leftndx > self.rightndx: + raise IndexError, "pop from an empty deque" + x = self.right[self.rightndx] + self.right[self.rightndx] = None + self.rightndx -= 1 + if self.rightndx == -1: + prevblock = self.right[LFTLNK] + if prevblock is None: + # the deque has become empty; recenter instead of freeing block + self.rightndx = n//2 + self.leftndx = n//2+1 + else: + prevblock[RGTLNK] = None + self.right[LFTLNK] = None + self.right = prevblock + self.rightndx = n-1 + return x def popleft(self): - x = self[0] - del self[0] + if self.left is self.right and self.leftndx > self.rightndx: + raise IndexError, "pop from an empty deque" + x = self.left[self.leftndx] + self.left[self.leftndx] = None + self.leftndx += 1 + if self.leftndx == n: + prevblock = self.left[RGTLNK] + if prevblock is None: + # the deque has become empty; recenter instead of freeing block + self.rightndx = n//2 + self.leftndx = n//2+1 + else: + prevblock[LFTLNK] = None + self.left[RGTLNK] = None + self.left = prevblock + self.leftndx = 0 return x - def rotate(self, step=1): - if len(self) == 0: + def remove(self, value): + del self[operator.indexOf(self, value)] + + def rotate(self, n=1): + length = len(self) + if length == 0: return - step %= len(self) - for i in range(step): + halflen = (length+1) >> 1 + if n > halflen or n < -halflen: + n %= length + if n > halflen: + n -= length + elif n < -halflen: + n += length + while n > 0: self.appendleft(self.pop()) + n -= 1 + while n < 0: + self.append(self.popleft()) + n += 1 def __repr__(self): - return "%s(%s)" % (type(self).__name__, list.__repr__(self)) + threadlocalattr = '__repr' + str(_thread_ident()) + if threadlocalattr in self.__dict__: + return 'deque([...])' + else: + self.__dict__[threadlocalattr] = True + try: + return 'deque(%r)' % (list(self),) + finally: + del self.__dict__[threadlocalattr] + + def __iter__(self): + block = self.left + while block: + l, r = 0, n + if block is self.left: + l = self.leftndx + if block is self.right: + r = self.rightndx + 1 + for elem in block[l:r]: + yield elem + block = block[RGTLNK] + + def __reversed__(self): + block = self.right + while block: + l, r = 0, n + if block is self.left: + l = self.leftndx + if block is self.right: + r = self.rightndx + 1 + for elem in reversed(block[l:r]): + yield elem + block = block[LFTLNK] + + def __len__(self): + sum = 0 + block = self.left + while block: + sum += n + block = block[RGTLNK] + return sum + self.rightndx - self.leftndx + 1 - n + + def __getref(self, index): + if index >= 0: + block = self.left + while block: + l, r = 0, n + if block is self.left: + l = self.leftndx + if block is self.right: + r = self.rightndx + 1 + span = r-l + if index < span: + return block, l+index + index -= span + block = block[RGTLNK] + else: + block = self.right + while block: + l, r = 0, n + if block is self.left: + l = self.leftndx + if block is self.right: + r = self.rightndx + 1 + negative_span = l-r + if index >= negative_span: + return block, r+index + index -= negative_span + block = block[LFTLNK] + raise IndexError("deque index out of range") + + def __getitem__(self, index): + block, index = self.__getref(index) + return block[index] + + def __setitem__(self, index, value): + block, index = self.__getref(index) + block[index] = value + + def __delitem__(self, index): + length = len(self) + if index >= 0: + if index >= length: + raise IndexError("deque index out of range") + self.rotate(-index) + self.popleft() + self.rotate(index) + else: + index = ~index + if index >= length: + raise IndexError("deque index out of range") + self.rotate(index) + self.pop() + self.rotate(-index) def __reduce_ex__(self, proto): return type(self), (), self.__dict__, iter(self), None - # We want to hide the fact that this deque is a subclass of list: - # should not be equal to + def __hash__(self): + raise TypeError, "deque objects are unhashable" + + def __copy__(self): + return self.__class__(self) + + # XXX make comparison more efficient def __eq__(self, other): - return isinstance(other, deque) and list.__eq__(self, other) - + if isinstance(other, deque): + return list(self) == list(other) + else: + return NotImplemented + def __ne__(self, other): - return not isinstance(other, deque) or list.__ne__(self, other) - + if isinstance(other, deque): + return list(self) != list(other) + else: + return NotImplemented + def __lt__(self, other): - return isinstance(other, deque) and list.__lt__(self, other) - + if isinstance(other, deque): + return list(self) < list(other) + else: + return NotImplemented + def __le__(self, other): - return isinstance(other, deque) and list.__le__(self, other) - - def __ge__(self, other): - return isinstance(other, deque) and list.__ge__(self, other) - + if isinstance(other, deque): + return list(self) <= list(other) + else: + return NotImplemented + def __gt__(self, other): - return isinstance(other, deque) and list.__gt__(self, other) + if isinstance(other, deque): + return list(self) > list(other) + else: + return NotImplemented + + def __ge__(self, other): + if isinstance(other, deque): + return list(self) >= list(other) + else: + return NotImplemented + From ludal at codespeak.net Mon Jul 4 18:36:54 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Mon, 4 Jul 2005 18:36:54 +0200 (CEST) Subject: [pypy-svn] r14234 - pypy/dist/pypy/interpreter/stablecompiler Message-ID: <20050704163654.1915E27B41@code1.codespeak.net> Author: ludal Date: Mon Jul 4 18:36:53 2005 New Revision: 14234 Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: make stable compiler run on python 2.3 Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Mon Jul 4 18:36:53 2005 @@ -31,6 +31,14 @@ import token import sys + +if not hasattr(symbol,'testlist_gexp'): + # python 2.3 + symbols = symbol.sym_name.keys() + symbols.sort() + symbol.testlist_gexp = symbols[-1] + 1 + symbol.sym_name[symbol.testlist_gexp] = "testlist_gexp" + class WalkerError(StandardError): pass From ludal at codespeak.net Mon Jul 4 19:55:10 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Mon, 4 Jul 2005 19:55:10 +0200 (CEST) Subject: [pypy-svn] r14238 - in pypy/dist/pypy/interpreter: stablecompiler test Message-ID: <20050704175510.347B627B42@code1.codespeak.net> Author: ludal Date: Mon Jul 4 19:55:08 2005 New Revision: 14238 Modified: pypy/dist/pypy/interpreter/stablecompiler/pyassem.py pypy/dist/pypy/interpreter/test/test_interpreter.py Log: fixed bug of 2.4 compiler which wouldn't generate EXTENDED_ARG at all Modified: pypy/dist/pypy/interpreter/stablecompiler/pyassem.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/pyassem.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/pyassem.py Mon Jul 4 19:55:08 2005 @@ -81,6 +81,9 @@ i.e. each node appears before all of its successors """ + # TODO: What we need here is a topological sort that + + # XXX make sure every node that doesn't have an explicit next # is set so that next points to exit for b in self.blocks.elements(): @@ -244,7 +247,7 @@ op = inst[0] if op[:4] == 'JUMP': self.outEdges.add(inst[1]) - self.insts.append(inst) + self.insts.append( list(inst) ) def getInstructions(self): return self.insts @@ -343,6 +346,7 @@ if isinstance(var, TupleArg): self.varnames[i] = var.getName() self.stage = RAW + self.orderedblocks = [] def setDocstring(self, doc): self.docstring = doc @@ -366,10 +370,10 @@ """Get a Python code object""" if self.stage == RAW: self.computeStackDepth() - self.flattenGraph() - if self.stage == FLAT: self.convertArgs() if self.stage == CONV: + self.flattenGraph() + if self.stage == FLAT: self.makeByteCode() if self.stage == DONE: return self.newCodeObject() @@ -425,35 +429,64 @@ def flattenGraph(self): """Arrange the blocks in order and resolve jumps""" - assert self.stage == RAW + assert self.stage == CONV self.insts = insts = [] pc = 0 begin = {} end = {} - for b in self.getBlocksInOrder(): + forward_refs = [] + for b in self.orderedblocks: begin[b] = pc for inst in b.getInstructions(): - insts.append(inst) if len(inst) == 1: + insts.append(inst) pc = pc + 1 elif inst[0] != "SET_LINENO": - # arg takes 2 bytes - pc = pc + 3 + opname, arg = inst + if self.hasjrel.has_elt(opname): + # relative jump - no extended arg + forward_refs.append( (arg, inst, pc ) ) + insts.append(inst) + pc = pc + 3 + elif self.hasjabs.has_elt(opname): + # absolute jump - can be extended if backward + if arg in begin: + # can only extend argument if backward + offset = begin[arg] + hi, lo = divmod(offset,65536) + if hi>0: + # extended argument + insts.append( ["EXTENDED_ARG", hi ] ) + pc = pc + 3 + inst[1] = lo + else: + forward_refs.append( (arg, inst, pc ) ) + insts.append(inst) + pc = pc + 3 + else: + # numerical arg + assert type(arg)==int + hi,lo = divmod(arg,65536) + if hi>0: + # extended argument + insts.append( ["EXTENDED_ARG", hi ] ) + inst[1] = lo + pc = pc + 3 + insts.append(inst) + pc = pc + 3 + else: + insts.append(inst) end[b] = pc pc = 0 - for i in range(len(insts)): - inst = insts[i] - if len(inst) == 1: - pc = pc + 1 - elif inst[0] != "SET_LINENO": - pc = pc + 3 - opname = inst[0] + + for arg, inst, pc in forward_refs: + opname, block = inst + abspos = begin[block] if self.hasjrel.has_elt(opname): - oparg = inst[1] - offset = begin[oparg] - pc - insts[i] = opname, offset - elif self.hasjabs.has_elt(opname): - insts[i] = opname, begin[inst[1]] + offset = abspos - pc - 3 + inst[1] = offset + else: + inst[1] = abspos self.stage = FLAT hasjrel = misc.Set() @@ -465,16 +498,18 @@ def convertArgs(self): """Convert arguments from symbolic to concrete form""" - assert self.stage == FLAT + assert self.stage == RAW + self.orderedblocks = self.getBlocksInOrder() self.consts.insert(0, self.docstring) self.sort_cellvars() - for i in range(len(self.insts)): - t = self.insts[i] - if len(t) == 2: - opname, oparg = t - conv = self._converters.get(opname, None) - if conv: - self.insts[i] = opname, conv(self, oparg) + + for b in self.orderedblocks: + for inst in b.getInstructions(): + if len(inst) == 2: + opname, oparg = inst + conv = self._converters.get(opname, None) + if conv: + inst[1] = conv(self, oparg) self.stage = CONV def sort_cellvars(self): @@ -563,10 +598,15 @@ del name, obj, opname def makeByteCode(self): - assert self.stage == CONV + assert self.stage == FLAT self.lnotab = lnotab = LineAddrTable() for t in self.insts: opname = t[0] + if self._debug: + if len(t)==1: + print "x",opname + else: + print "x",opname, t[1] if len(t) == 1: lnotab.addCode(self.opnum[opname]) else: Modified: pypy/dist/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/dist/pypy/interpreter/test/test_interpreter.py Mon Jul 4 19:55:08 2005 @@ -241,9 +241,6 @@ ec = self.space.getexecutioncontext() ec.compiler = self.saved_compiler - def test_extended_arg(self): - py.test.skip("Probably hits a bug in the compiler module") - class AppTestInterpreter: def test_trivial(self): x = 42 From ludal at codespeak.net Mon Jul 4 20:41:30 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Mon, 4 Jul 2005 20:41:30 +0200 (CEST) Subject: [pypy-svn] r14241 - in pypy/dist/pypy: interpreter/pyparser interpreter/pyparser/test interpreter/stablecompiler tool Message-ID: <20050704184130.5382427B42@code1.codespeak.net> Author: ludal Date: Mon Jul 4 20:41:28 2005 New Revision: 14241 Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/test/test_samples.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py pypy/dist/pypy/interpreter/stablecompiler/transformer.py pypy/dist/pypy/tool/option.py Log: * make using 2.4 grammar the default, mostly because the compiler has incompatibilities with 2.3 grammar * skip tests that are known to fail when we use python2.3 and 2.4 grammar mostly because they parse differently * revert change in transformer that are fixed by exporting the symbols of the 2.4 grammar in the symbol module Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Mon Jul 4 20:41:28 2005 @@ -6,13 +6,14 @@ using file_input, single_input and eval_input targets """ from pypy.interpreter.error import OperationError, debug_print +from pypy.tool.option import Options from pythonlexer import Source import ebnfparse import sys import os import grammar - +import symbol class PythonParser(object): """Wrapper class for python grammar""" @@ -49,21 +50,63 @@ raise BuilderError(line, lineno) # return None return builder - -# parse the python grammar corresponding to our CPython version -_ver = ".".join([str(i) for i in sys.version_info[:2]]) -PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) -def python_grammar(): - """returns a """ +PYTHON_VERSION = ".".join([str(i) for i in sys.version_info[:2]]) +def get_grammar_file( version ): + """returns the python grammar corresponding to our CPython version""" + if version == "native": + _ver = PYTHON_VERSION + elif version in ("2.3","2.4"): + _ver = version + return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver + +# unfortunately the command line options are not parsed yet +PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( Options.version ) + +def python_grammar(fname): + """returns a PythonParser build from the specified grammar file""" level = grammar.DEBUG grammar.DEBUG = 0 - gram = ebnfparse.parse_grammar( file(PYTHON_GRAMMAR) ) + gram = ebnfparse.parse_grammar( file(fname) ) grammar.DEBUG = level return PythonParser(gram) debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -PYTHON_PARSER = python_grammar() +PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) +_symbols = symbol.sym_name.keys() +_symbols.sort() + +def add_symbol( sym ): + if not hasattr(symbol, sym): + nextval = _symbols[-1] + 1 + setattr(symbol, sym, nextval) + _symbols.append(nextval) + symbol.sym_name[nextval] = sym + return nextval + return 0 + +def reload_grammar( version ): + """helper function to test with pypy different grammars""" + global PYTHON_GRAMMAR, PYTHON_PARSER, PYPY_VERSION + PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( version ) + debug_print( "Reloading grammar %s" % PYTHON_GRAMMAR ) + PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) + for rule in PYTHON_PARSER.rules: + add_symbol( rule ) + + +for rule in PYTHON_PARSER.rules: + add_symbol( rule ) + + +SYMBOLS = {} +# copies the numerical mapping between symbol name and symbol value +# into SYMBOLS +for k, v in symbol.sym_name.items(): + SYMBOLS[v] = k +SYMBOLS['UNKNOWN'] = -1 + + class BuilderError(SyntaxError): def __init__(self, line, lineno): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Mon Jul 4 20:41:28 2005 @@ -9,8 +9,19 @@ pypy_parsefile, python_parse, pypy_parse from pypy.interpreter.pyparser import grammar from pypy.interpreter.pyparser.pythonlexer import TokenError +from pypy.interpreter.pyparser.pythonparse import PYTHON_VERSION, PYPY_VERSION grammar.DEBUG = False + +# these samples are skipped if the native version of Python does not match +# the version of the grammar we use +GRAMMAR_MISMATCH = PYTHON_VERSION != PYPY_VERSION +SKIP_IF_NOT_NATIVE = [ + "snippet_samples.py", + "snippet_import_statements.py", +] + + def name(elt): return "%s[%s]"% (sym_name.get(elt,elt),elt) @@ -56,6 +67,9 @@ if not fname.endswith('.py'): # if fname != 'snippet_simple_assignment.py': continue + if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE: + print "Skipping", fname + continue abspath = osp.join(samples_dir, fname) yield check_parse, abspath Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Mon Jul 4 20:41:28 2005 @@ -1,6 +1,7 @@ from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET +from syntaxtree import TOKEN_MAP # , NT_OFFSET +from pythonparse import SYMBOLS class StackElement: """wraps TupleBuilder's tuples""" Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Mon Jul 4 20:41:28 2005 @@ -32,13 +32,6 @@ import sys -if not hasattr(symbol,'testlist_gexp'): - # python 2.3 - symbols = symbol.sym_name.keys() - symbols.sort() - symbol.testlist_gexp = symbols[-1] + 1 - symbol.sym_name[symbol.testlist_gexp] = "testlist_gexp" - class WalkerError(StandardError): pass Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Mon Jul 4 20:41:28 2005 @@ -15,6 +15,7 @@ compiler = "cpython" # "cpython" # "pyparse" pypy parser, cpython compiler # "pycomp" pypy parser and compiler (TBD) + version = "2.4" # "native" / "2.3" / "2.4" def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server @@ -51,6 +52,11 @@ '--parsermodule', action="store",type="string", dest="useparsermodule", help="select the parser module to use", metavar="[cpython|recparser|parser]")) +## for this to work the option module need to be loaded before the grammar! +## options.append(make_option( +## '--version', action="store",type="string", dest="version", +## help="select the Python version to emulate", +## metavar="[native|2.3|2.4]")) return options From adim at codespeak.net Mon Jul 4 20:49:11 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 20:49:11 +0200 (CEST) Subject: [pypy-svn] r14243 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704184911.5FF1127B42@code1.codespeak.net> Author: adim Date: Mon Jul 4 20:49:08 2005 New Revision: 14243 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Log: fixed some linenos management bugs added the syntactically incorrect line in the TokenError Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Mon Jul 4 20:49:08 2005 @@ -2,6 +2,7 @@ it obeys the TokenSource interface defined for the grammar analyser in grammar.py """ +import symbol from grammar import TokenSource, Token # Don't import string for that ... @@ -72,10 +73,13 @@ class TokenError(SyntaxError): """Raised when EOF is found prematuerly""" - def __init__(self, msg, strstart, token_stack): + def __init__(self, msg, line, strstart, token_stack): self.lineno, self.offset = strstart - self.text = "XXX" - self.msg = "TokenError at pos (%d, %d)" % (self.lineno, self.offset) + self.text = line + self.errlabel = msg + self.msg = "TokenError at pos (%d, %d) in %r" % (self.lineno, + self.offset, + line) self.token_stack = token_stack def generate_tokens(lines): @@ -119,7 +123,7 @@ if contstr: # continued string if not line: - raise TokenError("EOF in multi-line string", strstart, + raise TokenError("EOF in multi-line string", line, strstart, token_list) endmatch = endDFA.recognize(line) if -1 != endmatch: @@ -189,7 +193,7 @@ else: # continued statement if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0), token_list) + raise TokenError("EOF in multi-line statement", line, (lnum, 0), token_list) continued = 0 while pos < max: @@ -283,17 +287,16 @@ # (lnum, pos), (lnum, pos+1), line)) pos = pos + 1 - last_comment = '' + lnum -= 1 for indent in indents[1:]: # pop remaining indent levels tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) - lnum += 1 - ## adim - token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + ## adim: this can't be (only) that, can it ? + if token_list and token_list[-1] != symbol.file_input: + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) ## - lnum += 1 tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) @@ -326,6 +329,9 @@ """Returns the current line being parsed""" return self._current_line + def current_lineno(self): + return self._lineno + def context(self): """Returns an opaque context object for later restore""" return self.stack_pos @@ -368,7 +374,7 @@ NAMED_LIST = [tokenmod.OP, ] def token_from_values(tok_type, tok_string): - """XXX Compatibility layer between both parsers""" + """Compatibility layer between both parsers""" if tok_type in NONE_LIST: return Token(tokenmod.tok_name[tok_type], None) if tok_type in NAMED_LIST: From adim at codespeak.net Mon Jul 4 20:51:03 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 20:51:03 +0200 (CEST) Subject: [pypy-svn] r14244 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704185103.4D60A27B42@code1.codespeak.net> Author: adim Date: Mon Jul 4 20:51:01 2005 New Revision: 14244 Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Log: linenos should always be present in Terminal objects. The fact that we sometimes don't want linenos in the nested tuples must be an option of as_tuple() and nothing else. Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Mon Jul 4 20:51:01 2005 @@ -88,14 +88,11 @@ def token(self, name, value, source): num = TOKEN_MAP.get(name, -1) - lineno = source.current_line() + lineno = source.current_lineno() if value is None: if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): value = name else: value = '' - if self.lineno: - self.stack.append( Terminal(num, value, lineno) ) - else: - self.stack.append( Terminal(num, value, -1) ) + self.stack.append( Terminal(num, value, lineno) ) return True From adim at codespeak.net Mon Jul 4 20:53:32 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 20:53:32 +0200 (CEST) Subject: [pypy-svn] r14246 - in pypy/dist/pypy/interpreter/pyparser/test: . samples Message-ID: <20050704185332.921FB27B42@code1.codespeak.net> Author: adim Date: Mon Jul 4 20:53:29 2005 New Revision: 14246 Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_multiline.py Modified: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Log: - added a new snippet to the samples directory - now compares nested_tuples generation with and without linenos Modified: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py Mon Jul 4 20:53:29 2005 @@ -1,2 +1,3 @@ # -*- coding: ISO-8859-1 -*- -a = 1 # keep this statement for now (see test_only_one_comment.py) +a = 1 +# keep this statement for now (see test_only_one_comment.py) Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_multiline.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_multiline.py Mon Jul 4 20:53:29 2005 @@ -0,0 +1,7 @@ +from foo import bar, \ + baz + +if True and \ + False \ + and True: + print "excellent !" Modified: pypy/dist/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_samples.py Mon Jul 4 20:53:29 2005 @@ -61,11 +61,11 @@ def test_samples(): samples_dir = osp.join(osp.dirname(__file__), 'samples') + # samples_dir = osp.dirname(os.__file__) for use_lookahead in (True, False): grammar.USE_LOOKAHEAD = use_lookahead for fname in os.listdir(samples_dir): if not fname.endswith('.py'): - # if fname != 'snippet_simple_assignment.py': continue if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE: print "Skipping", fname @@ -92,9 +92,9 @@ _check_tuples_equality(pypy_tuples, python_tuples, filepath) -def check_parse_input(snippet, mode): - pypy_tuples = pypy_parse(snippet, mode) - python_tuples = python_parse(snippet, mode) +def check_parse_input(snippet, mode, lineno=False): + pypy_tuples = pypy_parse(snippet, mode, lineno) + python_tuples = python_parse(snippet, mode, lineno) _check_tuples_equality(pypy_tuples, python_tuples, snippet) def test_eval_inputs(): @@ -104,7 +104,8 @@ 'True and False', ] for snippet in snippets: - yield check_parse_input, snippet, 'eval' + yield check_parse_input, snippet, 'eval', True + yield check_parse_input, snippet, 'eval', False def test_exec_inputs(): snippets = [ @@ -112,12 +113,14 @@ 'print 6*7', 'if 1:\n x\n', ] for snippet in snippets: - yield check_parse_input, snippet, 'exec' + yield check_parse_input, snippet, 'exec', True + yield check_parse_input, snippet, 'exec', False def test_single_inputs(): snippets = ['a=1', 'True', 'def f(a):\n return a+1\n\n'] for snippet in snippets: - yield check_parse_input, snippet, 'single' + yield check_parse_input, snippet, 'single', True + yield check_parse_input, snippet, 'single', False def test_bad_inputs(): From ericvrp at codespeak.net Mon Jul 4 20:57:54 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Jul 2005 20:57:54 +0200 (CEST) Subject: [pypy-svn] r14247 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050704185754.2D37027B42@code1.codespeak.net> Author: ericvrp Date: Mon Jul 4 20:57:52 2005 New Revision: 14247 Modified: pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Fixed import problem that occured when tested functions have identical names in different tests. In this case only the first test was used. Fixed some typos Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Mon Jul 4 20:57:52 2005 @@ -13,6 +13,8 @@ from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void +function_count = {} + def genllvm(translator): remove_void(translator) func = translator.entrypoint @@ -51,17 +53,24 @@ typ_decl.writeimpl(codewriter) comment("End of file") ; nl() + + if func.func_name in function_count: + postfix = '_%d' % function_count[func.func_name] + function_count[func.func_name] += 1 + else: + postfix = '' + function_count[func.func_name] = 1 targetdir = udir - llvmsource = targetdir.join(func.func_name).new(ext='.ll') + llvmsource = targetdir.join(func.func_name+postfix).new(ext='.ll') content = str(codewriter) llvmsource.write(content) log.source(content) if not llvm_is_on_path(): py.test.skip("llvm not found") # XXX not good to call py.test.skip here - - pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') + + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+postfix+'.pyx') write_pyx_wrapper(entrynode, pyxsource) return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Mon Jul 4 20:57:52 2005 @@ -58,7 +58,7 @@ codewriter.label("block0") indices_to_array = [("int", 0)] s = self.struct - while isintance(s, lltypes.Struct): + while isinstance(s, lltype.Struct): last_pos = len(self.struct._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) s = s._flds.values()[-1] Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 4 20:57:52 2005 @@ -41,22 +41,24 @@ if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") return - def tuple_getitem2(n): - x = 0 + def tuple_getitem(n): + x = 666 i = 0 while i < n: - l = (1,2,i,234,23,23,23,234,234,234,234) + l = (1,2,i,4,5,6,7,8,9,10,11) x += l[2] i += 1 return x - mod,f = compile_module_function(tuple_getitem2, [int]) - assert f(10000) == 49995000 + mod,f = compile_module_function(tuple_getitem, [int]) + n = 5000 + result = tuple_getitem(n) + assert f(n) == result get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") heap_size_start = get_heap_size() - for i in range(0,10): - assert f(10000) == 49995000 + for i in range(0,25): + assert f(n) == result heap_size_inc = get_heap_size() - heap_size_start - assert heap_size_inc < 100000 + assert heap_size_inc < 500000 def test_return1(): def simple1(): @@ -213,10 +215,10 @@ def test_tuple_getitem(): def tuple_getitem(i): - l = (1,2,i) + l = (4,5,i) return l[1] f = compile_function(tuple_getitem, [int]) - assert f(1) == 2 + assert f(1) == tuple_getitem(1) def test_nested_tuple(): def nested_tuple(i): From adim at codespeak.net Mon Jul 4 20:58:18 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 20:58:18 +0200 (CEST) Subject: [pypy-svn] r14248 - pypy/dist/pypy/interpreter/pyparser/test/samples Message-ID: <20050704185818.8288F27B42@code1.codespeak.net> Author: adim Date: Mon Jul 4 20:58:17 2005 New Revision: 14248 Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.py - copied unchanged from r14241, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED Removed: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED Modified: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py Log: no need to disable this test anymore Modified: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_encoding_declaration.py Mon Jul 4 20:58:17 2005 @@ -1,3 +1,2 @@ # -*- coding: ISO-8859-1 -*- -a = 1 -# keep this statement for now (see test_only_one_comment.py) +a = 1 # keep this statement for now (see test_only_one_comment.py) Deleted: /pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED ============================================================================== --- /pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED Mon Jul 4 20:58:17 2005 +++ (empty file) @@ -1 +0,0 @@ -# only one comment From ludal at codespeak.net Mon Jul 4 21:03:10 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Mon, 4 Jul 2005 21:03:10 +0200 (CEST) Subject: [pypy-svn] r14249 - pypy/dist/pypy/interpreter/stablecompiler Message-ID: <20050704190310.159D227B42@code1.codespeak.net> Author: ludal Date: Mon Jul 4 21:03:09 2005 New Revision: 14249 Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: make sure we import the parser with the correct grammar before instanciating Transformer Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Mon Jul 4 21:03:09 2005 @@ -30,7 +30,8 @@ import symbol import token import sys - +# make sure we import the parser with the correct grammar +import pypy.interpreter.pyparser.pythonparse class WalkerError(StandardError): pass From pedronis at codespeak.net Mon Jul 4 21:18:09 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 4 Jul 2005 21:18:09 +0200 (CEST) Subject: [pypy-svn] r14251 - pypy/dist/pypy/documentation Message-ID: <20050704191809.3C1E727B42@code1.codespeak.net> Author: pedronis Date: Mon Jul 4 21:18:08 2005 New Revision: 14251 Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt Log: updated matching our current thinking. Modified: pypy/dist/pypy/documentation/ext-functions-draft.txt ============================================================================== --- pypy/dist/pypy/documentation/ext-functions-draft.txt (original) +++ pypy/dist/pypy/documentation/ext-functions-draft.txt Mon Jul 4 21:18:08 2005 @@ -15,8 +15,10 @@ * rtyper will replace the calls with for testing or dummy lowlevel functions (ll_os_open for os.open), specified somehow trough the - table (issue: how to annotate these helper calls avoiding making - copies as in the usual case, so that the backends can recognize them) + table. The usual specialisation for low-level helpers will happem + but the original function will be attached as _callable to the + function pointer such that backends can recognize the original + function as from the table. * the backends will have implementations for these helper functions (to allow writing such implementations we will need a way to assign From tismer at codespeak.net Mon Jul 4 21:35:21 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 4 Jul 2005 21:35:21 +0200 (CEST) Subject: [pypy-svn] r14252 - pypy/dist/pypy/objspace/std Message-ID: <20050704193521.BE18B27B45@code1.codespeak.net> Author: tismer Date: Mon Jul 4 21:35:20 2005 New Revision: 14252 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: long true divide and longfloor divide are ready, also conversions to float. missing: repr, str, long from float, and, or, xor, hex, oct, hash, pow :-( heelp Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Mon Jul 4 21:35:20 2005 @@ -91,9 +91,9 @@ return W_LongObject(w_intobj.space, digits, sign) # long-to-float delegation -def delegate_Long2Float(w_longobj): #YYYYYY +def delegate_Long2Float(w_longobj): try: - return W_FloatObject(w_longobj.space, float(w_longobj.longval())) + return W_FloatObject(w_longobj.space, _AsDouble(w_longobj)) except OverflowError: raise OperationError(w_longobj.space.w_OverflowError, w_longobj.space.wrap("long int too large to convert to float")) @@ -127,9 +127,9 @@ #subtypes of long are converted to long! return long__Long(space, w_value) -def float__Long(space, w_longobj): #YYYYYY +def float__Long(space, w_longobj): try: - return space.newfloat(float(w_longobj.longval())) + return space.newfloat(_AsDouble(w_longobj)) except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to float")) @@ -253,30 +253,15 @@ result.sign = w_long1.sign * w_long2.sign return result -def truediv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - try: - z = operator.truediv(x, y) - except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("long/long too large for a float")) - return space.newfloat(float(z)) +def truediv__Long_Long(space, w_long1, w_long2): + return _long_true_divide(space, w_long1, w_long2) -def floordiv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - z = x // y - return W_LongObject(space, *args_from_long(z)) +def floordiv__Long_Long(space, w_long1, w_long2): + div, rem = _divrem(space, w_long1, w_long2) + return div old_style_div = 1 / 2 == 1 // 2 -def div__Long_Long(space, w_long1, w_long2): #YYYYYY +def div__Long_Long(space, w_long1, w_long2): # Select the proper div if old_style_div: return floordiv__Long_Long(space, w_long1, w_long2) @@ -284,25 +269,13 @@ return truediv__Long_Long(space, w_long1, w_long2) -def mod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z = x % y - return W_LongObject(space, *args_from_long(z)) +def mod__Long_Long(space, w_long1, w_long2): + div, rem = _divrem(space, w_long1, w_long2) + return rem -def divmod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z1, z2 = divmod(x, y) - w_result1 = W_LongObject(space, *args_from_long(z1)) - w_result2 = W_LongObject(space, *args_from_long(z2)) - return space.newtuple([w_result1, w_result2]) +def divmod__Long_Long(space, w_long1, w_long2): + div, rem = _divrem(space, w_long1, w_long2) + return space.newtuple([div, rem]) # helper for pow() #YYYYYY: still needs longval if second argument is negative def _impl_long_long_pow(space, lv, lw, lz=None): @@ -868,10 +841,10 @@ rem = a return z, rem if size_b == 1: - z, urem = divrem1(a, b._getshort(0)) + z, urem = _divrem1(space, a, b._getshort(0)) rem = W_LongObject(space, [urem], int(urem != 0)) else: - z, rem = _x_divrem(a, b) + z, rem = _x_divrem(space, a, b) # Set the signs. # The quotient z has the sign of a*b; # the remainder r has the sign of a, @@ -881,3 +854,86 @@ if z.sign < 0 and rem.sign != 0: rem.sign = - rem.sign return z, rem + +# ______________ conversions to double _______________ + +def _AsScaledDouble(v): + """ + NBITS_WANTED should be > the number of bits in a double's precision, + but small enough so that 2**NBITS_WANTED is within the normal double + range. nbitsneeded is set to 1 less than that because the most-significant + Python digit contains at least 1 significant bit, but we don't want to + bother counting them (catering to the worst case cheaply). + + 57 is one more than VAX-D double precision; I (Tim) don't know of a double + format with more precision than that; it's 1 larger so that we add in at + least one round bit to stand in for the ignored least-significant bits. + """ + NBITS_WANTED = 57 + multiplier = float(1 << SHORT_BIT) + if v.sign == 0: + return 0.0, 0 + i = len(v.digits) * 2 - 1 + if v._getshort(i) == 0: + i -= 1 + sign = v.sign + x = float(v._getshort(i)) + nbitsneeded = NBITS_WANTED - 1 + # Invariant: i Python digits remain unaccounted for. + while i > 0 and nbitsneeded > 0: + i -= 1 + x = x * multiplier + float(v._getshort(i)) + nbitsneeded -= SHORT_BIT + # There are i digits we didn't shift in. Pretending they're all + # zeroes, the true value is x * 2**(i*SHIFT). + exponent = i + assert x > 0.0 + return x * sign, exponent + +# XXX make ldexp and isinf a builtin float support function + +def isinf(x): + return x*2 == x + +def ldexp(x, exp): + assert type(x) is float + lb1 = LONG_BIT - 1 + multiplier = float(r_uint(1) << lb1) + while exp >= lb1: + x *= multiplier + exp -= lb1 + if exp: + x *= float(r_uint(1) << exp) + return x + +def _AsDouble(v): + """ Get a C double from a long int object. """ + x, e = _AsScaledDouble(v) + if e <= sys.maxint / SHORT_BIT: + x = ldexp(x, e * SHORT_BIT) + if not isinf(x): + return x + raise OverflowError# sorry, "long int too large to convert to float" + +def _long_true_divide(space, a, b): + try: + ad, aexp = _AsScaledDouble(a) + bd, bexp = _AsScaledDouble(b) + if bd == 0.0: + 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 + aexp -= bexp + if aexp > sys.maxint / SHORT_BIT: + raise OverflowError + elif aexp < -(sys.maxint / SHORT_BIT): + return 0.0 # underflow to 0 + ad = ldexp(ad, aexp * SHORT_BIT) + if isinf(ad): # ignore underflow to 0.0 + raise OverflowError + return space.newfloat(ad) + except OverflowError: + raise OperationError(space.w_OverflowError, + space.wrap("long/long too large for a float")) From tismer at codespeak.net Mon Jul 4 21:35:41 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 4 Jul 2005 21:35:41 +0200 (CEST) Subject: [pypy-svn] r14253 - pypy/dist/pypy/objspace/std/test Message-ID: <20050704193541.A387427B49@code1.codespeak.net> Author: tismer Date: Mon Jul 4 21:35:40 2005 New Revision: 14253 Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py Log: long true divide and longfloor divide are ready, also conversions to float. missing: repr, str, long from float, and, or, xor, hex, oct, hash, pow :-( heelp 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 Mon Jul 4 21:35:40 2005 @@ -68,6 +68,50 @@ div, rem = lobj._divrem1(self.space, f1, f2) assert (div.longval(), rem) == divmod(x, y) + def test__muladd1(self): + x = 1238585838347L + y = 3 + z = 42 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + f3 = r_uint(z) + prod = lobj._muladd1(self.space, f1, f2, f3) + assert prod.longval() == x * y + z + + def test__x_divrem(self): + x = 12345678901234567890L + for i in range(100): + 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)) + div, rem = lobj._x_divrem(self.space, f1, f2) + assert div.longval(), rem.longval() == divmod(x, y) + + def test__divrem(self): + x = 12345678901234567890L + for i in range(100): + y = long(randint(0, 1 << 30)) + y <<= 30 + y += randint(0, 1 << 30) + 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)) + div, rem = lobj._x_divrem(self.space, 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)) + d = lobj._AsDouble(f1) + assert d == float(x) + x = x ** 100 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + assert raises(OverflowError, lobj._AsDouble, f1) + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L @@ -220,10 +264,18 @@ def test_sub(self): assert int(58543L - 12332L) == 58543 - 12332 assert 237123838281233L * 12 == 237123838281233L * 12L - + def test_mul(self): assert 363L * 2 ** 40 == 363L << 40 + def test_truediv(self): + exec "from __future__ import division; a = 31415926L / 10000000L" + assert a == 3.1415926 + + def test_floordiv(self): + a = 31415926L // 10000000L + assert a == 3L + def test_conversion(self): class long2(long): pass From tismer at codespeak.net Mon Jul 4 21:37:58 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 4 Jul 2005 21:37:58 +0200 (CEST) Subject: [pypy-svn] r14254 - pypy/dist/pypy/objspace/std Message-ID: <20050704193758.D491F27B4B@code1.codespeak.net> Author: tismer Date: Mon Jul 4 21:37:58 2005 New Revision: 14254 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: don't return wrapped things in helpers if not needed, but wrap the result late. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Mon Jul 4 21:37:58 2005 @@ -254,7 +254,8 @@ return result def truediv__Long_Long(space, w_long1, w_long2): - return _long_true_divide(space, 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, rem = _divrem(space, w_long1, w_long2) @@ -402,7 +403,7 @@ w_result._normalize() return w_result -def rshift__Long_Long(space, w_long1, w_long2): #YYYYYY +def rshift__Long_Long(space, w_long1, w_long2): if w_long2.sign < 0: raise OperationError(space.w_ValueError, space.wrap("negative shift count")) @@ -933,7 +934,7 @@ ad = ldexp(ad, aexp * SHORT_BIT) if isinf(ad): # ignore underflow to 0.0 raise OverflowError - return space.newfloat(ad) + return ad except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("long/long too large for a float")) From adim at codespeak.net Mon Jul 4 21:47:56 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 4 Jul 2005 21:47:56 +0200 (CEST) Subject: [pypy-svn] r14255 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050704194756.AFF8327B4F@code1.codespeak.net> Author: adim Date: Mon Jul 4 21:47:55 2005 New Revision: 14255 Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/pytokenize.py Log: small cleanups Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Mon Jul 4 21:47:55 2005 @@ -8,7 +8,10 @@ punct=['>=', '<>', '!=', '<', '>', '<=', '==', '\\*=', '//=', '%=', '^=', '<<=', '\\*\\*=', '\\', '=', - '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', '@', '\\[', '\\]', '`', '\\{', '\\}'] + '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', + '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', + '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', + '@', '\\[', '\\]', '`', '\\{', '\\}'] py_punct = re.compile(r""" >=|<>|!=|<|>|<=|==|~| @@ -77,17 +80,16 @@ self.items = [] self.terminals['NAME'] = NameToken() - def new_name( self ): + def new_name(self): rule_name = ":%s_%s" % (self.current_rule, self.current_subrule) self.current_subrule += 1 return rule_name - def new_item( self, itm ): - self.items.append( itm ) + def new_item(self, itm): + self.items.append(itm) return itm - def visit_grammar( self, node ): - # print "Grammar:" + def visit_grammar(self, node): for rule in node.nodes: rule.visit(self) # the rules are registered already @@ -103,23 +105,23 @@ # XXX .keywords also contains punctuations self.terminals['NAME'].keywords = self.tokens.keys() - def visit_rule( self, node ): + def visit_rule(self, node): symdef = node.nodes[0].value self.current_rule = symdef self.current_subrule = 0 alt = node.nodes[1] rule = alt.visit(self) - if not isinstance( rule, Token ): + if not isinstance(rule, Token): rule.name = symdef self.rules[symdef] = rule - def visit_alternative( self, node ): - items = [ node.nodes[0].visit(self) ] + def visit_alternative(self, node): + items = [node.nodes[0].visit(self)] items += node.nodes[1].visit(self) if len(items) == 1 and items[0].name.startswith(':'): return items[0] - alt = Alternative( self.new_name(), items ) - return self.new_item( alt ) + alt = Alternative(self.new_name(), items) + return self.new_item(alt) def visit_sequence( self, node ): """ """ @@ -181,11 +183,14 @@ rule_name = self.new_name() tok = star_opt.nodes[0].nodes[0] if tok.value == '+': - return self.new_item( KleenStar( rule_name, _min=1, rule = myrule ) ) + item = KleenStar(rule_name, _min=1, rule=myrule) + return self.new_item(item) elif tok.value == '*': - return self.new_item( KleenStar( rule_name, _min=0, rule = myrule ) ) + item = KleenStar(rule_name, _min=0, rule=myrule) + return self.new_item(item) else: - raise SyntaxError("Got symbol star_opt with value='%s'" % tok.value ) + raise SyntaxError("Got symbol star_opt with value='%s'" + % tok.value) return myrule rules = None Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Mon Jul 4 21:47:55 2005 @@ -78,8 +78,9 @@ class BaseGrammarBuilder(object): """Base/default class for a builder""" def __init__(self, rules=None, debug=0): - self.rules = rules or {} # a dictionary of grammar rules for debug/reference - # XXX This attribute is here for convenience + # a dictionary of grammar rules for debug/reference + self.rules = rules or {} + # This attribute is here for convenience self.source_encoding = None self.debug = debug self.stack = [] @@ -166,8 +167,8 @@ """ if not USE_LOOKAHEAD: return self._match(source, builder, level) - pos1 = -1 # XXX make the annotator happy - pos2 = -1 # XXX make the annotator happy + pos1 = -1 # make the annotator happy + pos2 = -1 # make the annotator happy token = source.peek() if self._trace: pos1 = source.get_pos() @@ -242,9 +243,10 @@ def debug_return(self, ret, *args ): # FIXME: use a wrapper of match() methods instead of debug_return() # to prevent additional indirection - if ret and DEBUG>0: + if ret and DEBUG > 0: sargs = ",".join( [ str(i) for i in args ] ) - print "matched %s (%s): %s" % (self.__class__.__name__, sargs, self.display() ) + print "matched %s (%s): %s" % (self.__class__.__name__, + sargs, self.display() ) return ret @@ -268,8 +270,9 @@ return other in self.first_set def reorder_rule(self): - """Called after the computation of first set to allow rules to be reordered - to avoid ambiguities""" + """Called after the computation of first set to allow rules to be + reordered to avoid ambiguities + """ pass class Alternative(GrammarElement): @@ -285,7 +288,7 @@ """If any of the rules in self.args matches returns the object built from the first rules that matches """ - if DEBUG>1: + if DEBUG > 1: print "try alt:", self.display() tok = source.peek() # Here we stop at the first match we should @@ -304,7 +307,7 @@ return 0 def display(self, level=0): - if level==0: + if level == 0: name = self.name + " -> " elif not self.name.startswith(":"): return self.name @@ -344,12 +347,13 @@ # a same alternative for token in rule.first_set: if token is not EmptyToken and token in tokens_set: - print "Warning, token %s in\n\t%s's first set is part " \ - "of a previous rule's first set in alternative\n\t" \ - "%s" % (token, rule, self) + print "Warning, token %s in\n\t%s's first set is " \ + " part of a previous rule's first set in " \ + " alternative\n\t%s" % (token, rule, self) tokens_set.append(token) if len(empty_set) > 1 and not self._reordered: - print "Warning: alternative %s has more than one rule matching Empty" % self + print "Warning: alternative %s has more than one rule " \ + "matching Empty" % self self._reordered = True self.args[:] = not_empty_set self.args.extend( empty_set ) @@ -365,7 +369,7 @@ def _match(self, source, builder, level=0): """matches all of the symbols in order""" - if DEBUG>1: + if DEBUG > 1: print "try seq:", self.display() ctx = source.context() bctx = builder.context() @@ -381,7 +385,7 @@ return self.debug_return( ret ) def display(self, level=0): - if level == 0: + if level == 0: name = self.name + " -> " elif not self.name.startswith(":"): return self.name @@ -431,9 +435,11 @@ # self.first_set[EmptyToken] = 1 def _match(self, source, builder, level=0): - """matches a number of times self.args[0]. the number must be comprised - between self._min and self._max inclusive. -1 is used to represent infinity""" - if DEBUG>1: + """matches a number of times self.args[0]. the number must be + comprised between self._min and self._max inclusive. -1 is used to + represent infinity + """ + if DEBUG > 1: print "try kle:", self.display() ctx = source.context() bctx = builder.context() @@ -507,7 +513,6 @@ """ ctx = source.context() tk = source.next() - # XXX: match_token if tk.name == self.name: if self.value is None: ret = builder.token( tk.name, tk.value, source ) @@ -515,7 +520,7 @@ elif self.value == tk.value: ret = builder.token( tk.name, tk.value, source ) return self.debug_return( ret, tk.name, tk.value ) - if DEBUG>1: + if DEBUG > 1: print "tried tok:", self.display() source.restore( ctx ) return 0 @@ -534,9 +539,6 @@ must be equal - a tuple, such as those yielded by the Python lexer, in which case the comparison algorithm is similar to the one in match() - XXX: - 1/ refactor match and __eq__ ? - 2/ make source.next and source.peek return a Token() instance """ if not isinstance(other, Token): raise RuntimeError("Unexpected token type %r" % other) Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Mon Jul 4 21:47:55 2005 @@ -4,7 +4,7 @@ """ import symbol -from grammar import TokenSource, Token +from pypy.interpreter.pyparser.grammar import TokenSource, Token # Don't import string for that ... NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' NUMCHARS = '0123456789' @@ -113,10 +113,13 @@ last_comment = '' encoding = None strstart = (0, 0) + # make the annotator happy pos = -1 lines.append('') # XXX HACK probably not needed - endDFA = automata.DFA([], []) # XXX Make the translator happy - line = '' # XXX Make the translator happy + # make the annotator happy + endDFA = automata.DFA([], []) + # make the annotator happy + line = '' for line in lines: lnum = lnum + 1 pos, max = 0, len(line) @@ -173,9 +176,6 @@ last_comment = '' # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line, lnum, pos)) - # token_list.append(((NL, COMMENT)[line[pos] == '#'], - # line[pos:], - # (lnum, pos), (lnum, len(line)), line)) continue if column > indents[-1]: # count indents or dedents @@ -183,17 +183,15 @@ tok = token_from_values(tokenmod.INDENT, line[:pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((INDENT, line[:pos],(lnum, 0),(lnum,pos),line)) while column < indents[-1]: indents = indents[:-1] tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((DEDENT, '', (lnum, pos),(lnum,pos),line)) - else: # continued statement if not line: - raise TokenError("EOF in multi-line statement", line, (lnum, 0), token_list) + raise TokenError("EOF in multi-line statement", line, + (lnum, 0), token_list) continued = 0 while pos < max: @@ -213,7 +211,6 @@ tok = token_from_values(tokenmod.NUMBER, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((NUMBER, token, spos, epos, line)) elif initial in '\r\n': if parenlev > 0: tok = token_from_values(tokenmod.NL, token) @@ -225,7 +222,6 @@ tok.value = last_comment token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) elif initial == '#': tok = token_from_values(tokenmod.COMMENT, token) last_comment = token @@ -244,7 +240,6 @@ tok = token_from_values(tokenmod.STRING, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((STRING, token, spos, (lnum, pos), line)) else: strstart = (lnum, start) # multiple lines contstr = line[start:] @@ -269,29 +264,26 @@ tok = token_from_values(tokenmod.NAME, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((NAME, token, spos, epos, line)) elif initial == '\\': # continued stmt continued = 1 else: - if initial in '([{': parenlev = parenlev + 1 - elif initial in ')]}': parenlev = parenlev - 1 + if initial in '([{': + parenlev = parenlev + 1 + elif initial in ')]}': + parenlev = parenlev - 1 tok = token_from_values(tokenmod.OP, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((OP, token, spos, epos, line)) else: tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((ERRORTOKEN, line[pos], - # (lnum, pos), (lnum, pos+1), line)) pos = pos + 1 lnum -= 1 for indent in indents[1:]: # pop remaining indent levels tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) - # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) ## adim: this can't be (only) that, can it ? if token_list and token_list[-1] != symbol.file_input: @@ -299,7 +291,7 @@ ## tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) - # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) + return token_list, encoding class PythonSource(TokenSource): @@ -330,6 +322,7 @@ return self._current_line def current_lineno(self): + """Returns the current lineno""" return self._lineno def context(self): @@ -370,8 +363,8 @@ return (self._current_line, self._lineno) # return 'line %s : %s' % ('XXX', self._current_line) -NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] -NAMED_LIST = [tokenmod.OP, ] +NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT] +NAMED_LIST = [tokenmod.OP] def token_from_values(tok_type, tok_string): """Compatibility layer between both parsers""" Modified: pypy/dist/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pytokenize.py Mon Jul 4 21:47:55 2005 @@ -13,23 +13,21 @@ expressions have been replaced with hand built DFA's using the basil.util.automata module. -XXX This now assumes that the automata module is in the Python path. - $Id: pytokenize.py,v 1.3 2003/10/03 16:31:53 jriehl Exp $ """ # ______________________________________________________________________ from __future__ import generators -import automata +from pypy.interpreter.pyparser import automata # ______________________________________________________________________ # COPIED: -from token import * - import token __all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", "generate_tokens", "NL"] del x +N_TOKENS = token.N_TOKENS +tok_name = token.tok_name del token COMMENT = N_TOKENS From ac at codespeak.net Mon Jul 4 22:13:59 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 4 Jul 2005 22:13:59 +0200 (CEST) Subject: [pypy-svn] r14257 - in pypy/branch/dist-2.4.1/pypy/objspace/std: . test Message-ID: <20050704201359.F384B27B56@code1.codespeak.net> Author: ac Date: Mon Jul 4 22:13:59 2005 New Revision: 14257 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Log: Add a fullchar argument to unicode.[lr]just Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/stringobject.py Mon Jul 4 22:13:59 2005 @@ -658,12 +658,6 @@ return W_StringObject(space, u_centered) -# This is so that str_center__String_ANY_Unicode in unicodeobject -# won't convert a String fillchar -def str_center__String_ANY_String(space, w_self, w_arg, w_fillchar): - return str_center__String_ANY_ANY(space, w_self, w_arg, w_fillchar) - - def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): u_self = w_self._value u_arg = w_arg._value Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py Mon Jul 4 22:13:59 2005 @@ -128,11 +128,41 @@ assert u'abc'.center(6) == u' abc ' assert u'abc'.center(3) == u'abc' assert u'abc'.center(2) == u'abc' - assert u'abc'.center(5, u'*') == u'*abc*' # Python 2.4 + assert u'abc'.center(5, u'*') == u'*abc*' # Python 2.4 assert u'abc'.center(5, '*') == u'*abc*' # Python 2.4 - assert 'abc'.center(5, u'*') == u'*abc*' # Python 2.4 + raises(TypeError, 'abc'.center, 5, u'*') # Python 2.4 raises(TypeError, u'abc'.center, 4, u'cba') + def test_rjust(self): + s = u"abc" + assert s.rjust(2) == s + assert s.rjust(3) == s + assert s.rjust(4) == u" " + s + assert s.rjust(5) == u" " + s + assert u'abc'.rjust(10) == u' abc' + assert u'abc'.rjust(6) == u' abc' + assert u'abc'.rjust(3) == u'abc' + assert u'abc'.rjust(2) == u'abc' + assert u'abc'.rjust(5, u'*') == u'**abc' # Python 2.4 + assert u'abc'.rjust(5, '*') == u'**abc' # Python 2.4 + raises(TypeError, 'abc'.rjust, 5, u'*') # Python 2.4 + raises(TypeError, u'abc'.rjust, 5, u'xx') + + def test_ljust(self): + s = u"abc" + assert s.ljust(2) == s + assert s.ljust(3) == s + assert s.ljust(4) == s + u" " + assert s.ljust(5) == s + u" " + assert u'abc'.ljust(10) == u'abc ' + assert u'abc'.ljust(6) == u'abc ' + assert u'abc'.ljust(3) == u'abc' + assert u'abc'.ljust(2) == u'abc' + assert u'abc'.ljust(5, u'*') == u'abc**' # Python 2.4 + assert u'abc'.ljust(5, '*') == u'abc**' # Python 2.4 + raises(TypeError, 'abc'.ljust, 5, u'*') # Python 2.4 + raises(TypeError, u'abc'.ljust, 6, u'') + def test_long_from_unicode(self): assert long(u'12345678901234567890') == 12345678901234567890 assert int(u'12345678901234567890') == 12345678901234567890 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodeobject.py Mon Jul 4 22:13:59 2005 @@ -62,7 +62,7 @@ return space.str_w(space.str(w_uni)) def repr__Unicode(space, w_uni): - return space.wrap(repr(u''.join(w_uni._value))) + return space.wrap(repr(u''.join(w_uni._value))) # XXX: We don't support unicodestrings and certainly not repr on them. def str__Unicode(space, w_uni): return space.call_method(w_uni, 'encode') @@ -154,6 +154,10 @@ totlen = 0 if len(list) == 0: return W_UnicodeObject(space, []) + if (len(list) == 1 and + space.is_true(space.is_(space.type(list[0]), space.w_unicode))): + return list[0] + values_list = [None] * len(list) values_list[0] = [u'\0'] for i in range(len(list)): @@ -505,23 +509,21 @@ return space.w_False return space.w_True +def _to_unichar_w(space, w_char): + try: + w_unichar = unicodetype.unicode_from_object(space, w_char) + except OperationError: + raise OperationError(space.w_TypeError, space.wrap('The fill character cannot be converted to Unicode')) + + if space.int_w(space.len(w_unichar)) != 1: + raise OperationError(space.w_TypeError, space.wrap('The fill character must be exactly one character long')) + unichar = unichr(space.int_w(space.ord(w_unichar))) + return unichar + def unicode_center__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value width = space.int_w(w_width) - - if space.is_true(space.isinstance(w_fillchar, space.w_str)): - fillchar = space.str_w(w_fillchar) - if len(fillchar) != 1: - raise OperationError( - space.w_TypeError, - space.wrap("center() argument 2 must be a single character")) - elif space.is_true(space.isinstance(w_fillchar, space.w_unicode)): - if len(w_fillchar._value) != 1: - raise OperationError( - space.w_TypeError, - space.wrap("center() argument 2 must be a single character")) - fillchar = w_fillchar._value[0] - + fillchar = _to_unichar_w(space, w_fillchar) padding = width - len(self) if padding < 0: return space.call_function(space.w_unicode, w_self) @@ -531,24 +533,26 @@ result[leftpad + i] = self[i] return W_UnicodeObject(space, result) -def unicode_ljust__Unicode_ANY(space, w_self, w_width): +def unicode_ljust__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value width = space.int_w(w_width) + fillchar = _to_unichar_w(space, w_fillchar) padding = width - len(self) if padding < 0: return space.call_function(space.w_unicode, w_self) - result = [u' '] * width + result = [fillchar] * width for i in range(len(self)): result[i] = self[i] return W_UnicodeObject(space, result) -def unicode_rjust__Unicode_ANY(space, w_self, w_width): +def unicode_rjust__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value width = space.int_w(w_width) + fillchar = _to_unichar_w(space, w_fillchar) padding = width - len(self) if padding < 0: return space.call_function(space.w_unicode, w_self) - result = [u' '] * width + result = [fillchar] * width for i in range(len(self)): result[padding + i] = self[i] return W_UnicodeObject(space, result) @@ -794,7 +798,6 @@ return space.call_method(w_new, 'join', w_parts) -'translate' app = gateway.applevel(r''' import sys @@ -883,7 +886,6 @@ def str_lstrip__String_Unicode(space, w_self, w_chars): return space.call_method(space.call_function(space.w_unicode, w_self), 'lstrip', w_chars) - self = w_self._value def str_rstrip__String_Unicode(space, w_self, w_chars): return space.call_method(space.call_function(space.w_unicode, w_self), 'rstrip', w_chars) @@ -915,9 +917,4 @@ return space.call_method(space.call_function(space.w_unicode, w_self), 'rsplit', w_delim, w_maxsplit) - def str_center__String_ANY_Unicode(space, w_self, w_width, w_fillchar): - print 'Centering a string with unicode.' - return space.call_method(space.call_function(space.w_unicode, w_self), - 'center', w_width, w_fillchar) - register_all(vars(), stringtype) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/unicodetype.py Mon Jul 4 22:13:59 2005 @@ -22,13 +22,13 @@ unicode_istitle = MultiMethod('istitle', 1) unicode_isupper = MultiMethod('isupper', 1) unicode_join = MultiMethod('join', 2) -unicode_ljust = MultiMethod('ljust', 2) +unicode_ljust = MultiMethod('ljust', 3, defaults=(' ',)) unicode_lower = MultiMethod('lower', 1) unicode_lstrip = MultiMethod('lstrip', 2, defaults=(None,)) unicode_replace = MultiMethod('replace', 4, defaults=(-1,)) unicode_rfind = MultiMethod('rfind', 4, defaults=(0, maxint)) unicode_rindex = MultiMethod('rindex', 4, defaults=(0, maxint)) -unicode_rjust = MultiMethod('rjust', 2) +unicode_rjust = MultiMethod('rjust', 3, defaults=(' ',)) unicode_rstrip = MultiMethod('rstrip', 2, defaults=(None,)) unicode_rsplit = MultiMethod('rsplit', 3, defaults=(None,-1)) unicode_split = MultiMethod('split', 3, defaults=(None,-1)) From arigo at codespeak.net Tue Jul 5 12:00:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 12:00:40 +0200 (CEST) Subject: [pypy-svn] r14261 - in pypy/dist/pypy/interpreter/pyparser: . test test/samples Message-ID: <20050705100040.06C0927B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 12:00:39 2005 New Revision: 14261 Modified: pypy/dist/pypy/interpreter/pyparser/ (props changed) pypy/dist/pypy/interpreter/pyparser/__init__.py (props changed) pypy/dist/pypy/interpreter/pyparser/automata.py (props changed) pypy/dist/pypy/interpreter/pyparser/pytokenize.py (props changed) pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_multiline.py (props changed) pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py (props changed) Log: fixeol. From pedronis at codespeak.net Tue Jul 5 12:02:11 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 12:02:11 +0200 (CEST) Subject: [pypy-svn] r14262 - pypy/extradoc/sprintinfo Message-ID: <20050705100211.21ADD27B42@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 12:02:10 2005 New Revision: 14262 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: listed missing builtin functionality Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Tue Jul 5 12:02:10 2005 @@ -74,6 +74,8 @@ Builtins -------- + implement int(string) and int(string, 16) + (strange)(delegating to backend?) sys.getrefcount (medium) applevel sys module should not refer to interplevel sys.getdefaultencoding From arigo at codespeak.net Tue Jul 5 12:03:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 12:03:40 +0200 (CEST) Subject: [pypy-svn] r14263 - in pypy/branch/dist-2.4.1: lib-python/modified-2.3.4 lib-python/modified-2.3.4/test pypy/documentation pypy/interpreter pypy/interpreter/astcompiler pypy/interpreter/pyparser pypy/interpreter/pyparser/test pypy/interpreter/pyparser/test/samples pypy/interpreter/stablecompiler pypy/interpreter/test pypy/lib pypy/objspace/std pypy/objspace/std/test pypy/tool pypy/translator/goal pypy/translator/llvm2 pypy/translator/llvm2/test Message-ID: <20050705100340.B939627B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 12:03:38 2005 New Revision: 14263 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/binhex.py - copied unchanged from r14261, pypy/dist/lib-python/modified-2.3.4/binhex.py pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/test/test_binhex.py - copied unchanged from r14261, pypy/dist/lib-python/modified-2.3.4/test/test_binhex.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_multiline.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_multiline.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/ (props changed) - copied from r14261, pypy/dist/pypy/interpreter/stablecompiler/ pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/__init__.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/__init__.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/ast.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/ast.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/consts.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/consts.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/future.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/future.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/misc.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/misc.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/pyassem.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/pyassem.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/pycodegen.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/symbols.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/symbols.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/syntax.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/syntax.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/transformer.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/transformer.py pypy/branch/dist-2.4.1/pypy/interpreter/stablecompiler/visitor.py - copied unchanged from r14261, pypy/dist/pypy/interpreter/stablecompiler/visitor.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/atomic.py - copied unchanged from r14261, pypy/dist/pypy/translator/llvm2/atomic.py Removed: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED Modified: pypy/branch/dist-2.4.1/pypy/documentation/ext-functions-draft.txt pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/transformer.py pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ (props changed) pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/__init__.py (props changed) pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/automata.py (props changed) pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnfparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/grammar.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py (contents, props changed) pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_lookahead.py (props changed) pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/tuplebuilder.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py pypy/branch/dist-2.4.1/pypy/lib/binascii.py pypy/branch/dist-2.4.1/pypy/lib/struct.py pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py pypy/branch/dist-2.4.1/pypy/tool/option.py pypy/branch/dist-2.4.1/pypy/translator/goal/targetparser.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Log: merged the trunk into r14261 svn merge -r14183:14261 http://codespeak.net/svn/pypy/dist Modified: pypy/branch/dist-2.4.1/pypy/documentation/ext-functions-draft.txt ============================================================================== --- pypy/branch/dist-2.4.1/pypy/documentation/ext-functions-draft.txt (original) +++ pypy/branch/dist-2.4.1/pypy/documentation/ext-functions-draft.txt Tue Jul 5 12:03:38 2005 @@ -15,8 +15,10 @@ * rtyper will replace the calls with for testing or dummy lowlevel functions (ll_os_open for os.open), specified somehow trough the - table (issue: how to annotate these helper calls avoiding making - copies as in the usual case, so that the backends can recognize them) + table. The usual specialisation for low-level helpers will happem + but the original function will be attached as _callable to the + function pointer such that backends can recognize the original + function as from the table. * the backends will have implementations for these helper functions (to allow writing such implementations we will need a way to assign Modified: pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/transformer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/transformer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/astcompiler/transformer.py Tue Jul 5 12:03:38 2005 @@ -89,7 +89,7 @@ print nodes[kind], len(args), args raise else: - raise WalkerEror, "Can't find appropriate Node type: %s" % str(args) + raise WalkerError, "Can't find appropriate Node type: %s" % str(args) #return apply(ast.Node, args) class Transformer: @@ -165,7 +165,7 @@ if n == symbol.classdef: return self.classdef(node[1:]) - raise WalkerEror, ('unexpected node type', n) + raise WalkerError, ('unexpected node type', n) def single_input(self, node): ### do we want to do anything about being "interactive" ? @@ -314,31 +314,31 @@ return Stmt(stmts) def parameters(self, nodelist): - raise WalkerEror + raise WalkerError def varargslist(self, nodelist): - raise WalkerEror + raise WalkerError def fpdef(self, nodelist): - raise WalkerEror + raise WalkerError def fplist(self, nodelist): - raise WalkerEror + raise WalkerError def dotted_name(self, nodelist): - raise WalkerEror + raise WalkerError def comp_op(self, nodelist): - raise WalkerEror + raise WalkerError def trailer(self, nodelist): - raise WalkerEror + raise WalkerError def sliceop(self, nodelist): - raise WalkerEror + raise WalkerError def argument(self, nodelist): - raise WalkerEror + raise WalkerError # -------------------------------------------------------------- # Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Tue Jul 5 12:03:38 2005 @@ -68,7 +68,7 @@ if not err2.match(space, space.w_SyntaxError): raise - if space.eq_w(err1.w_value, err2.w_value): + if mode != 'single' and space.eq_w(err1.w_value, err2.w_value): raise # twice the same error, re-raise return None # two different errors, expect more @@ -169,14 +169,12 @@ ######## -# from compiler.transformer import Transformer -from compiler.pycodegen import ModuleCodeGenerator -from compiler.pycodegen import InteractiveCodeGenerator -from compiler.pycodegen import ExpressionCodeGenerator -from pyparser.pythonparse import parse_python_source, PYTHON_PARSER -from pyparser.tuplebuilder import TupleBuilder +from pypy.interpreter import stablecompiler +from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator +from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator +from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator +from pypy.interpreter.stablecompiler.transformer import Transformer from pyparser.pythonutil import ast_from_input -import compiler class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler @@ -190,8 +188,9 @@ flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: - tree = ast_from_input(source, mode) - compiler.misc.set_filename(filename, tree) + transformer = Transformer() + tree = ast_from_input(source, mode, transformer) + stablecompiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) elif mode == 'single': Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/ebnfparse.py Tue Jul 5 12:03:38 2005 @@ -8,7 +8,10 @@ punct=['>=', '<>', '!=', '<', '>', '<=', '==', '\\*=', '//=', '%=', '^=', '<<=', '\\*\\*=', '\\', '=', - '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', '@', '\\[', '\\]', '`', '\\{', '\\}'] + '\\+=', '>>=', '=', '&=', '/=', '-=', '\n,', '^', + '>>', '&', '\\+', '\\*', '-', '/', '\\.', '\\*\\*', + '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', + '@', '\\[', '\\]', '`', '\\{', '\\}'] py_punct = re.compile(r""" >=|<>|!=|<|>|<=|==|~| @@ -77,17 +80,16 @@ self.items = [] self.terminals['NAME'] = NameToken() - def new_name( self ): + def new_name(self): rule_name = ":%s_%s" % (self.current_rule, self.current_subrule) self.current_subrule += 1 return rule_name - def new_item( self, itm ): - self.items.append( itm ) + def new_item(self, itm): + self.items.append(itm) return itm - def visit_grammar( self, node ): - # print "Grammar:" + def visit_grammar(self, node): for rule in node.nodes: rule.visit(self) # the rules are registered already @@ -103,23 +105,23 @@ # XXX .keywords also contains punctuations self.terminals['NAME'].keywords = self.tokens.keys() - def visit_rule( self, node ): + def visit_rule(self, node): symdef = node.nodes[0].value self.current_rule = symdef self.current_subrule = 0 alt = node.nodes[1] rule = alt.visit(self) - if not isinstance( rule, Token ): + if not isinstance(rule, Token): rule.name = symdef self.rules[symdef] = rule - def visit_alternative( self, node ): - items = [ node.nodes[0].visit(self) ] + def visit_alternative(self, node): + items = [node.nodes[0].visit(self)] items += node.nodes[1].visit(self) if len(items) == 1 and items[0].name.startswith(':'): return items[0] - alt = Alternative( self.new_name(), items ) - return self.new_item( alt ) + alt = Alternative(self.new_name(), items) + return self.new_item(alt) def visit_sequence( self, node ): """ """ @@ -181,11 +183,14 @@ rule_name = self.new_name() tok = star_opt.nodes[0].nodes[0] if tok.value == '+': - return self.new_item( KleenStar( rule_name, _min=1, rule = myrule ) ) + item = KleenStar(rule_name, _min=1, rule=myrule) + return self.new_item(item) elif tok.value == '*': - return self.new_item( KleenStar( rule_name, _min=0, rule = myrule ) ) + item = KleenStar(rule_name, _min=0, rule=myrule) + return self.new_item(item) else: - raise SyntaxError("Got symbol star_opt with value='%s'" % tok.value ) + raise SyntaxError("Got symbol star_opt with value='%s'" + % tok.value) return myrule rules = None Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/grammar.py Tue Jul 5 12:03:38 2005 @@ -78,8 +78,9 @@ class BaseGrammarBuilder(object): """Base/default class for a builder""" def __init__(self, rules=None, debug=0): - self.rules = rules or {} # a dictionary of grammar rules for debug/reference - # XXX This attribute is here for convenience + # a dictionary of grammar rules for debug/reference + self.rules = rules or {} + # This attribute is here for convenience self.source_encoding = None self.debug = debug self.stack = [] @@ -166,8 +167,8 @@ """ if not USE_LOOKAHEAD: return self._match(source, builder, level) - pos1 = -1 # XXX make the annotator happy - pos2 = -1 # XXX make the annotator happy + pos1 = -1 # make the annotator happy + pos2 = -1 # make the annotator happy token = source.peek() if self._trace: pos1 = source.get_pos() @@ -242,9 +243,10 @@ def debug_return(self, ret, *args ): # FIXME: use a wrapper of match() methods instead of debug_return() # to prevent additional indirection - if ret and DEBUG>0: + if ret and DEBUG > 0: sargs = ",".join( [ str(i) for i in args ] ) - print "matched %s (%s): %s" % (self.__class__.__name__, sargs, self.display() ) + print "matched %s (%s): %s" % (self.__class__.__name__, + sargs, self.display() ) return ret @@ -268,8 +270,9 @@ return other in self.first_set def reorder_rule(self): - """Called after the computation of first set to allow rules to be reordered - to avoid ambiguities""" + """Called after the computation of first set to allow rules to be + reordered to avoid ambiguities + """ pass class Alternative(GrammarElement): @@ -285,7 +288,7 @@ """If any of the rules in self.args matches returns the object built from the first rules that matches """ - if DEBUG>1: + if DEBUG > 1: print "try alt:", self.display() tok = source.peek() # Here we stop at the first match we should @@ -304,7 +307,7 @@ return 0 def display(self, level=0): - if level==0: + if level == 0: name = self.name + " -> " elif not self.name.startswith(":"): return self.name @@ -344,12 +347,13 @@ # a same alternative for token in rule.first_set: if token is not EmptyToken and token in tokens_set: - print "Warning, token %s in\n\t%s's first set is part " \ - "of a previous rule's first set in alternative\n\t" \ - "%s" % (token, rule, self) + print "Warning, token %s in\n\t%s's first set is " \ + " part of a previous rule's first set in " \ + " alternative\n\t%s" % (token, rule, self) tokens_set.append(token) if len(empty_set) > 1 and not self._reordered: - print "Warning: alternative %s has more than one rule matching Empty" % self + print "Warning: alternative %s has more than one rule " \ + "matching Empty" % self self._reordered = True self.args[:] = not_empty_set self.args.extend( empty_set ) @@ -365,7 +369,7 @@ def _match(self, source, builder, level=0): """matches all of the symbols in order""" - if DEBUG>1: + if DEBUG > 1: print "try seq:", self.display() ctx = source.context() bctx = builder.context() @@ -381,7 +385,7 @@ return self.debug_return( ret ) def display(self, level=0): - if level == 0: + if level == 0: name = self.name + " -> " elif not self.name.startswith(":"): return self.name @@ -431,9 +435,11 @@ # self.first_set[EmptyToken] = 1 def _match(self, source, builder, level=0): - """matches a number of times self.args[0]. the number must be comprised - between self._min and self._max inclusive. -1 is used to represent infinity""" - if DEBUG>1: + """matches a number of times self.args[0]. the number must be + comprised between self._min and self._max inclusive. -1 is used to + represent infinity + """ + if DEBUG > 1: print "try kle:", self.display() ctx = source.context() bctx = builder.context() @@ -507,7 +513,6 @@ """ ctx = source.context() tk = source.next() - # XXX: match_token if tk.name == self.name: if self.value is None: ret = builder.token( tk.name, tk.value, source ) @@ -515,7 +520,7 @@ elif self.value == tk.value: ret = builder.token( tk.name, tk.value, source ) return self.debug_return( ret, tk.name, tk.value ) - if DEBUG>1: + if DEBUG > 1: print "tried tok:", self.display() source.restore( ctx ) return 0 @@ -534,9 +539,6 @@ must be equal - a tuple, such as those yielded by the Python lexer, in which case the comparison algorithm is similar to the one in match() - XXX: - 1/ refactor match and __eq__ ? - 2/ make source.next and source.peek return a Token() instance """ if not isinstance(other, Token): raise RuntimeError("Unexpected token type %r" % other) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 12:03:38 2005 @@ -2,8 +2,9 @@ it obeys the TokenSource interface defined for the grammar analyser in grammar.py """ +import symbol -from grammar import TokenSource, Token +from pypy.interpreter.pyparser.grammar import TokenSource, Token # Don't import string for that ... NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' NUMCHARS = '0123456789' @@ -72,10 +73,13 @@ class TokenError(SyntaxError): """Raised when EOF is found prematuerly""" - def __init__(self, msg, strstart, token_stack): + def __init__(self, msg, line, strstart, token_stack): self.lineno, self.offset = strstart - self.text = "XXX" - self.msg = "TokenError at pos (%d, %d)" % (self.lineno, self.offset) + self.text = line + self.errlabel = msg + self.msg = "TokenError at pos (%d, %d) in %r" % (self.lineno, + self.offset, + line) self.token_stack = token_stack def generate_tokens(lines): @@ -109,17 +113,20 @@ last_comment = '' encoding = None strstart = (0, 0) + # make the annotator happy pos = -1 lines.append('') # XXX HACK probably not needed - endDFA = automata.DFA([], []) # XXX Make the translator happy - line = '' # XXX Make the translator happy + # make the annotator happy + endDFA = automata.DFA([], []) + # make the annotator happy + line = '' for line in lines: lnum = lnum + 1 pos, max = 0, len(line) if contstr: # continued string if not line: - raise TokenError("EOF in multi-line string", strstart, + raise TokenError("EOF in multi-line string", line, strstart, token_list) endmatch = endDFA.recognize(line) if -1 != endmatch: @@ -169,9 +176,6 @@ last_comment = '' # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line, lnum, pos)) - # token_list.append(((NL, COMMENT)[line[pos] == '#'], - # line[pos:], - # (lnum, pos), (lnum, len(line)), line)) continue if column > indents[-1]: # count indents or dedents @@ -179,17 +183,15 @@ tok = token_from_values(tokenmod.INDENT, line[:pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((INDENT, line[:pos],(lnum, 0),(lnum,pos),line)) while column < indents[-1]: indents = indents[:-1] tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((DEDENT, '', (lnum, pos),(lnum,pos),line)) - else: # continued statement if not line: - raise TokenError("EOF in multi-line statement", (lnum, 0), token_list) + raise TokenError("EOF in multi-line statement", line, + (lnum, 0), token_list) continued = 0 while pos < max: @@ -209,7 +211,6 @@ tok = token_from_values(tokenmod.NUMBER, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((NUMBER, token, spos, epos, line)) elif initial in '\r\n': if parenlev > 0: tok = token_from_values(tokenmod.NL, token) @@ -221,7 +222,6 @@ tok.value = last_comment token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) elif initial == '#': tok = token_from_values(tokenmod.COMMENT, token) last_comment = token @@ -240,7 +240,6 @@ tok = token_from_values(tokenmod.STRING, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((STRING, token, spos, (lnum, pos), line)) else: strstart = (lnum, start) # multiple lines contstr = line[start:] @@ -265,36 +264,34 @@ tok = token_from_values(tokenmod.NAME, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((NAME, token, spos, epos, line)) elif initial == '\\': # continued stmt continued = 1 else: - if initial in '([{': parenlev = parenlev + 1 - elif initial in ')]}': parenlev = parenlev - 1 + if initial in '([{': + parenlev = parenlev + 1 + elif initial in ')]}': + parenlev = parenlev - 1 tok = token_from_values(tokenmod.OP, token) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((OP, token, spos, epos, line)) else: tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' - # token_list.append((ERRORTOKEN, line[pos], - # (lnum, pos), (lnum, pos+1), line)) pos = pos + 1 - last_comment = '' + lnum -= 1 for indent in indents[1:]: # pop remaining indent levels tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) - # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) - - ## adim - token_list.append((Token('NEWLINE', ''), line, lnum, 0)) + + ## adim: this can't be (only) that, can it ? + if token_list and token_list[-1] != symbol.file_input: + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) ## tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) - # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) + return token_list, encoding class PythonSource(TokenSource): @@ -324,6 +321,10 @@ """Returns the current line being parsed""" return self._current_line + def current_lineno(self): + """Returns the current lineno""" + return self._lineno + def context(self): """Returns an opaque context object for later restore""" return self.stack_pos @@ -362,11 +363,11 @@ return (self._current_line, self._lineno) # return 'line %s : %s' % ('XXX', self._current_line) -NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] -NAMED_LIST = [tokenmod.OP, ] +NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT] +NAMED_LIST = [tokenmod.OP] def token_from_values(tok_type, tok_string): - """XXX Compatibility layer between both parsers""" + """Compatibility layer between both parsers""" if tok_type in NONE_LIST: return Token(tokenmod.tok_name[tok_type], None) if tok_type in NAMED_LIST: Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py Tue Jul 5 12:03:38 2005 @@ -6,29 +6,107 @@ using file_input, single_input and eval_input targets """ from pypy.interpreter.error import OperationError, debug_print +from pypy.tool.option import Options from pythonlexer import Source import ebnfparse import sys import os import grammar +import symbol -# parse the python grammar corresponding to our CPython version -_ver = ".".join([str(i) for i in sys.version_info[:2]]) -PYTHON_GRAMMAR = os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ) +class PythonParser(object): + """Wrapper class for python grammar""" + def __init__(self, grammar_builder): + self.items = grammar_builder.items + self.rules = grammar_builder.rules + # Build first sets for each rule (including anonymous ones) + grammar.build_first_sets(self.items) + + def parse_source(self, textsrc, goal, builder=None): + """Parse a python source according to goal""" + lines = [line + '\n' for line in textsrc.split('\n')] + if textsrc == '\n': + lines.pop() + else: + last_line = lines[-1] + lines[-1] = last_line[:-1] + return self.parse_lines(lines, goal, builder) + + def parse_lines(self, lines, goal, builder=None): + target = self.rules[goal] + src = Source(lines) + + if builder is None: + builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) + result = target.match(src, builder) + # XXX find a clean way to process encoding declarations + builder.source_encoding = src.encoding + # + if not result: + # raising a SyntaxError here is not annotable, and it can + # probably be handled in an other way + line, lineno = src.debug() + raise BuilderError(line, lineno) + # return None + return builder + +PYTHON_VERSION = ".".join([str(i) for i in sys.version_info[:2]]) +def get_grammar_file( version ): + """returns the python grammar corresponding to our CPython version""" + if version == "native": + _ver = PYTHON_VERSION + elif version in ("2.3","2.4"): + _ver = version + return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver -def python_grammar(): - """returns a """ +# unfortunately the command line options are not parsed yet +PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( Options.version ) + +def python_grammar(fname): + """returns a PythonParser build from the specified grammar file""" level = grammar.DEBUG grammar.DEBUG = 0 - gram = ebnfparse.parse_grammar( file(PYTHON_GRAMMAR) ) + gram = ebnfparse.parse_grammar( file(fname) ) grammar.DEBUG = level - # Build first sets for each rule (including anonymous ones) - grammar.build_first_sets(gram.items) - return gram + return PythonParser(gram) debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -PYTHON_PARSER = python_grammar() +PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) +_symbols = symbol.sym_name.keys() +_symbols.sort() + +def add_symbol( sym ): + if not hasattr(symbol, sym): + nextval = _symbols[-1] + 1 + setattr(symbol, sym, nextval) + _symbols.append(nextval) + symbol.sym_name[nextval] = sym + return nextval + return 0 + +def reload_grammar( version ): + """helper function to test with pypy different grammars""" + global PYTHON_GRAMMAR, PYTHON_PARSER, PYPY_VERSION + PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( version ) + debug_print( "Reloading grammar %s" % PYTHON_GRAMMAR ) + PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) + for rule in PYTHON_PARSER.rules: + add_symbol( rule ) + + +for rule in PYTHON_PARSER.rules: + add_symbol( rule ) + + +SYMBOLS = {} +# copies the numerical mapping between symbol name and symbol value +# into SYMBOLS +for k, v in symbol.sym_name.items(): + SYMBOLS[v] = k +SYMBOLS['UNKNOWN'] = -1 + + class BuilderError(SyntaxError): def __init__(self, line, lineno): @@ -38,32 +116,14 @@ self.offset = -1 self.msg = "SyntaxError at line %d: %r" % (self.lineno, self.line) -def parse_python_source(textsrc, gram, goal, builder=None): - """Parse a python source according to goal""" - target = gram.rules[goal] - src = Source(textsrc) - if builder is None: - builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) - result = target.match(src, builder) - # XXX find a clean way to process encoding declarations - builder.source_encoding = src.encoding - # - if not result: - # raising a SyntaxError here is not annotable, and it can - # probably be handled in an other way - line, lineno = src.debug() - raise BuilderError(line, lineno) - # return None - return builder - def parse_file_input(pyf, gram, builder=None): """Parse a python file""" - return parse_python_source( pyf.read(), gram, "file_input", builder ) + return gram.parse_source( pyf.read(), "file_input", builder ) def parse_single_input(textsrc, gram, builder=None): """Parse a python single statement""" - return parse_python_source( textsrc, gram, "single_input", builder ) + return gram.parse_source( textsrc, "single_input", builder ) def parse_eval_input(textsrc, gram, builder=None): """Parse a python expression""" - return parse_python_source( textsrc, gram, "eval_input", builder ) + return gram.parse_source( textsrc, "eval_input", builder ) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py Tue Jul 5 12:03:38 2005 @@ -1,7 +1,6 @@ __all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", - "ast_eval_input" ] + "ast_eval_input"] -from compiler.transformer import Transformer import parser import symbol @@ -12,7 +11,7 @@ TARGET_DICT = { 'exec' : "file_input", 'eval' : "eval_input", - 'single' : "single_input", + 'single' : "file_input", } ## convenience functions around CPython's parser functions @@ -28,11 +27,11 @@ """parse python source using CPython's parser module and return nested tuples """ - if mode == 'exec': - tp = parser.suite(source) - else: + if mode == 'eval': tp = parser.expr(source) - return tp.totuple() + else: + tp = parser.suite(source) + return parser.ast2tuple(tp, line_info=lineno) ## convenience functions around recparser functions def pypy_parsefile(filename, lineno=False): @@ -63,24 +62,11 @@ nested tuples """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - # finalize the last line - if not source.endswith('\n'): - last_line = strings[-1] - strings[-1] = last_line[:-1] - else: - strings.pop() target_rule = TARGET_DICT[mode] - pythonparse.parse_python_source(strings, PYTHON_PARSER, - target_rule, builder) -## if builder.error_occured(): -## line, lineno, offset, filename = builder.get_error() -## raise SyntaxError(line, lineno, offset, filename) -## # stack_element is a tuplerbuilder.StackElement's instance + PYTHON_PARSER.parse_source(source, target_rule, builder) stack_element = builder.stack[-1] - # convert the stack element into nested tuples - # XXX : the annotator can't follow this call + # convert the stack element into nested tuples (caution, the annotator + # can't follow this call) nested_tuples = stack_element.as_tuple(lineno) if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) @@ -88,14 +74,23 @@ return nested_tuples ## convenience functions for computing AST objects using recparser -def ast_from_input(input, mode): +def ast_from_input(input, mode, transformer): + """converts a source input into an AST + + - input : the source to be converted + - mode : 'exec', 'eval' or 'single' + - transformer : the transfomer instance to use to convert + the nested tuples into the AST + XXX: transformer could be instantiated here but we don't want + here to explicitly import compiler or stablecompiler or + etc. This is to be fixed in a clean way + """ tuples = pypy_parse(input, mode, True) - transformer = Transformer() ast = transformer.compile_node(tuples) return ast ## TARGET FOR ANNOTATORS ############################################# -def annotateme(strings): +def annotateme(source): """This function has no other role than testing the parser's annotation annotateme() is basically the same code that pypy_parse(), but with the @@ -108,7 +103,7 @@ """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - pythonparse.parse_python_source(strings, PYTHON_PARSER, 'file_input', builder) + PYTHON_PARSER.parse_source(source, 'file_input', builder) nested_tuples = builder.stack[-1] if builder.source_encoding is not None: return (symbol.encoding_decl, nested_tuples, builder.source_encoding) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py Tue Jul 5 12:03:38 2005 @@ -13,23 +13,21 @@ expressions have been replaced with hand built DFA's using the basil.util.automata module. -XXX This now assumes that the automata module is in the Python path. - $Id: pytokenize.py,v 1.3 2003/10/03 16:31:53 jriehl Exp $ """ # ______________________________________________________________________ from __future__ import generators -import automata +from pypy.interpreter.pyparser import automata # ______________________________________________________________________ # COPIED: -from token import * - import token __all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", "generate_tokens", "NL"] del x +N_TOKENS = token.N_TOKENS +tok_name = token.tok_name del token COMMENT = N_TOKENS Deleted: /pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED ============================================================================== --- /pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/samples/snippet_only_one_comment.DISABLED Tue Jul 5 12:03:38 2005 +++ (empty file) @@ -1 +0,0 @@ -# only one comment Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py Tue Jul 5 12:03:38 2005 @@ -9,8 +9,19 @@ pypy_parsefile, python_parse, pypy_parse from pypy.interpreter.pyparser import grammar from pypy.interpreter.pyparser.pythonlexer import TokenError +from pypy.interpreter.pyparser.pythonparse import PYTHON_VERSION, PYPY_VERSION grammar.DEBUG = False + +# these samples are skipped if the native version of Python does not match +# the version of the grammar we use +GRAMMAR_MISMATCH = PYTHON_VERSION != PYPY_VERSION +SKIP_IF_NOT_NATIVE = [ + "snippet_samples.py", + "snippet_import_statements.py", +] + + def name(elt): return "%s[%s]"% (sym_name.get(elt,elt),elt) @@ -50,11 +61,14 @@ def test_samples(): samples_dir = osp.join(osp.dirname(__file__), 'samples') + # samples_dir = osp.dirname(os.__file__) for use_lookahead in (True, False): grammar.USE_LOOKAHEAD = use_lookahead for fname in os.listdir(samples_dir): if not fname.endswith('.py'): - # if fname != 'snippet_simple_assignment.py': + continue + if GRAMMAR_MISMATCH and fname in SKIP_IF_NOT_NATIVE: + print "Skipping", fname continue abspath = osp.join(samples_dir, fname) yield check_parse, abspath @@ -78,9 +92,9 @@ _check_tuples_equality(pypy_tuples, python_tuples, filepath) -def check_parse_input(snippet, mode): - pypy_tuples = pypy_parse(snippet, mode) - python_tuples = python_parse(snippet, mode) +def check_parse_input(snippet, mode, lineno=False): + pypy_tuples = pypy_parse(snippet, mode, lineno) + python_tuples = python_parse(snippet, mode, lineno) _check_tuples_equality(pypy_tuples, python_tuples, snippet) def test_eval_inputs(): @@ -90,7 +104,8 @@ 'True and False', ] for snippet in snippets: - yield check_parse_input, snippet, 'eval' + yield check_parse_input, snippet, 'eval', True + yield check_parse_input, snippet, 'eval', False def test_exec_inputs(): snippets = [ @@ -98,8 +113,16 @@ 'print 6*7', 'if 1:\n x\n', ] for snippet in snippets: - yield check_parse_input, snippet, 'exec' + yield check_parse_input, snippet, 'exec', True + yield check_parse_input, snippet, 'exec', False + +def test_single_inputs(): + snippets = ['a=1', 'True', 'def f(a):\n return a+1\n\n'] + for snippet in snippets: + yield check_parse_input, snippet, 'single', True + yield check_parse_input, snippet, 'single', False + def test_bad_inputs(): inputs = ['x = (', 'x = (\n', 'x = (\n\n'] for inp in inputs: Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/tuplebuilder.py Tue Jul 5 12:03:38 2005 @@ -1,6 +1,7 @@ from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET +from syntaxtree import TOKEN_MAP # , NT_OFFSET +from pythonparse import SYMBOLS class StackElement: """wraps TupleBuilder's tuples""" @@ -87,14 +88,11 @@ def token(self, name, value, source): num = TOKEN_MAP.get(name, -1) - lineno = source.current_line() + lineno = source.current_lineno() if value is None: if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): value = name else: value = '' - if self.lineno: - self.stack.append( Terminal(num, value, lineno) ) - else: - self.stack.append( Terminal(num, value, -1) ) + self.stack.append( Terminal(num, value, lineno) ) return True Modified: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py Tue Jul 5 12:03:38 2005 @@ -48,6 +48,16 @@ flags2 = self.compiler.getcodeflags(code2) assert flags == flags2 + def test_interactivemode(self): + code = self.compiler.compile('a = 1', '', 'single', 0) + assert isinstance(code, PyCode) + assert code.co_filename == '' + space = self.space + w_globals = space.newdict([]) + code.exec_code(space, w_globals, w_globals) + w_a = space.getitem(w_globals, space.wrap('a')) + assert space.int_w(w_a) == 1 + class TestECCompiler(BaseTestCompiler): def setup_method(self, method): @@ -64,3 +74,4 @@ class SkippedForNowTestPyPyCompiler(BaseTestCompiler): def setup_method(self, method): self.compiler = PyPyCompiler(self.space) + Modified: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py Tue Jul 5 12:03:38 2005 @@ -1,4 +1,6 @@ import py +import sys +from pypy.interpreter.pycompiler import PythonCompiler class TestInterpreter: def codetest(self, source, functionname, args): @@ -13,7 +15,6 @@ w = space.wrap w_code = space.builtin.call('compile', w(source), w(''), w('exec'), w(0), w(0)) - ec = executioncontext.ExecutionContext(space) tempmodule = module.Module(space, w("__temp__")) w_glob = tempmodule.w_dict @@ -226,6 +227,20 @@ assert self.codetest(code, 'g', [12, {}]) == () assert self.codetest(code, 'g', [12, {3:1}]) == (3,) +class TestPyPyInterpreter(TestInterpreter): + """Runs the previous test with the pypy parser""" + def setup_class(klass): + sys.setrecursionlimit(10000) + + def setup_method(self,arg): + ec = self.space.getexecutioncontext() + self.saved_compiler = ec.compiler + ec.compiler = PythonCompiler(self.space) + + def teardown_method(self,arg): + ec = self.space.getexecutioncontext() + ec.compiler = self.saved_compiler + class AppTestInterpreter: def test_trivial(self): x = 42 @@ -258,3 +273,4 @@ def test_identity(self): def f(x): return x assert f(666) == 666 + Modified: pypy/branch/dist-2.4.1/pypy/lib/binascii.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/binascii.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/binascii.py Tue Jul 5 12:03:38 2005 @@ -1,64 +1,66 @@ class Error(Exception): pass +class Apa(Exception): + pass + class Incomplete(Exception): pass def a2b_uu(s): length = (ord(s[0]) - 0x20) % 64 - a = quadruplets(s[1:].rstrip()) + + def quadruplets_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) + except IndexError: + s += ' ' + yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) + return + s = s[4:] + try: result = [''.join( [chr((A - 0x20) << 2 | (((B - 0x20) >> 4) & 0x3)), - chr(((B - 0x20) & 0xF) << 4 | (((C - 0x20) >> 2) & 0xF)), - chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3F)) - ]) for A, B, C, D in a] + chr(((B - 0x20) & 0xf) << 4 | (((C - 0x20) >> 2) & 0xf)), + chr(((C - 0x20) & 0x3) << 6 | ((D - 0x20) & 0x3f)) + ]) for A, B, C, D in quadruplets_gen(s[1:].rstrip())] except ValueError: - raise Error, 'Illegal char' + raise Error('Illegal char') result = ''.join(result) trailingdata = result[length:] if trailingdata.strip('\x00'): - raise Error, 'Trailing garbage' + raise Error('Trailing garbage') result = result[:length] if len(result) < length: result += ((length - len(result)) * '\x00') return result -def quadruplets(s): - while s: - try: - a, b, c, d = s[0], s[1], s[2], s[3] - except IndexError: - s += ' ' - yield ord(s[0]), ord(s[1]), ord(s[2]), ord(s[3]) - return - s = s[4:] - yield ord(a), ord(b), ord(c), ord(d) def b2a_uu(s): length = len(s) if length > 45: - raise Error, 'At most 45 bytes at once' + raise Error('At most 45 bytes at once') + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + s += '\0\0' + yield ord(s[0]), ord(s[1]), ord(s[2]) + return + s = s[3:] - a = triples(s) result = [''.join( [chr(0x20 + (( A >> 2 ) & 0x3F)), chr(0x20 + (((A << 4) | ((B >> 4) & 0xF)) & 0x3F)), chr(0x20 + (((B << 2) | ((C >> 6) & 0x3)) & 0x3F)), - chr(0x20 + (( C ) & 0x3F))]) for A, B, C in a] + chr(0x20 + (( C ) & 0x3F))]) + for A, B, C in triples_gen(s)] return chr(ord(' ') + (length & 077)) + ''.join(result) + '\n' -def triples(s): - while s: - try: - a, b, c = s[0], s[1], s[2] - except IndexError: - s += '\0\0' - yield ord(s[0]), ord(s[1]), ord(s[2]) - return - s = s[3:] - yield ord(a), ord(b), ord(c) - table_a2b_base64 = { 'A': 0, @@ -127,11 +129,6 @@ '/': 63, } -def quadruplets_base64(s): - while s: - a, b, c, d = table_a2b_base64[s[0]], table_a2b_base64[s[1]], table_a2b_base64[s[2]], table_a2b_base64[s[3]] - s = s[4:] - yield a, b, c, d def a2b_base64(s): s = s.rstrip() @@ -145,12 +142,19 @@ if len(s) % 4: s = s + ('=' * (4 - len(s) % 4)) - a = quadruplets_base64(s[:-4]) + def quadruplets_gen(s): + while s: + yield (table_a2b_base64[s[0]], + table_a2b_base64[s[1]], + table_a2b_base64[s[2]], + table_a2b_base64[s[3]]) + s = s[4:] + result = [ chr(A << 2 | ((B >> 4) & 0x3)) + - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) + chr((C & 0x3) << 6 | D ) - for A, B, C, D in a] + for A, B, C, D in quadruplets_gen(s[:-4])] if s: final = s[-4:] @@ -163,14 +167,14 @@ B = table_a2b_base64[final[1]] C = table_a2b_base64[final[2]] snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) else: A = table_a2b_base64[final[0]] B = table_a2b_base64[final[1]] C = table_a2b_base64[final[2]] D = table_a2b_base64[final[3]] snippet = chr(A << 2 | ((B >> 4) & 0x3)) + \ - chr((B & 0xF) << 4 | ((C >> 2 ) & 0xF)) + \ + chr((B & 0xf) << 4 | ((C >> 2 ) & 0xf)) + \ chr((C & 0x3) << 6 | D ) result.append(snippet) @@ -182,8 +186,19 @@ def b2a_base64(s): length = len(s) final_length = length % 3 + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + s += '\0\0' + yield ord(s[0]), ord(s[1]), ord(s[2]) + return + s = s[3:] + - a = triples(s[ :length - final_length]) + a = triples_gen(s[ :length - final_length]) result = [''.join( [table_b2a_base64[( A >> 2 ) & 0x3F], @@ -278,19 +293,20 @@ else: sign = '' arr = [] - for nibble in hexgen(n): + + def hex_gen(n): + """ Yield a nibble at a time. """ + while n: + yield n % 0x10 + n = n / 0x10 + + for nibble in hex_gen(n): arr = [hex_numbers[nibble]] + arr return sign + ''.join(arr) def two_hex_digits(n): return hex_numbers[n / 0x10] + hex_numbers[n % 0x10] -def hexgen(n): - """ Yield a nibble at a time. """ - while n: - remainder = n % 0x10 - n = n / 0x10 - yield remainder def strhex_to_int(s): i = 0 @@ -299,46 +315,115 @@ return i hqx_encoding = '!"#$%&\'()*+,-012345689 at ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr' -# Make a fast lookup dictionary for decoding hqx -hqx_decoding = {} -for i, c in enumerate(hqx_encoding): - hqx_decoding[c] = i + +DONE = 0x7f +SKIP = 0x7e +FAIL = 0x7d -def unpadded_quadruples(s): - while s: - yield s[:4] - s = s[4:] +table_a2b_hqx = [ + #^@ ^A ^B ^C ^D ^E ^F ^G + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + #\b \t \n ^K ^L \r ^N ^O + FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL, + #^P ^Q ^R ^S ^T ^U ^V ^W + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + #^X ^Y ^Z ^[ ^\ ^] ^^ ^_ + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + # ! " # $ % & ' + FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + #( ) * + , - . / + 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL, + #0 1 2 3 4 5 6 7 + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL, + #8 9 : ; < = > ? + 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL, + #@ A B C D E F G + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + #H I J K L M N O + 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL, + #P Q R S T U V W + 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL, + #X Y Z [ \ ] ^ _ + 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL, + #` a b c d e f g + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL, + #h i j k l m n o + 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL, + #p q r s t u v w + 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL, + #x y z { | } ~ ^? + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, + FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, +] def a2b_hqx(s): - decoded = [] - for c in s: - decoded.append(hqx_decoding[c]) - gen = unpadded_quadruples(decoded) result = [] - for snippet in gen: - length = len(snippet) - if length == 4: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - result.append(chr((snippet[2] << 6) | (snippet[3]))) - elif length == 3: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - result.append(chr((snippet[1] << 4) | (snippet[2] >> 4))) - elif length == 2: - result.append(chr((snippet[0] << 2) | (snippet[1] >> 6))) - else: - raise TypeError('Wrong number of characters.') - return ''.join(result) -def unpadded_triples(s): - while s: - yield [ord(c) for c in s[:3]] - s = s[3:] + def quadruples_gen(s): + t = [] + for c in s: + res = table_a2b_hqx[ord(c)] + if res == SKIP: + continue + elif res == FAIL: + raise Error('Illegal character') + elif res == DONE: + yield t + print 'raising' + raise Apa + else: + t.append(res) + if len(t) == 4: + yield t + t = [] + yield t + + done = 0 + try: + for snippet in quadruples_gen(s): + length = len(snippet) + if length == 4: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2))) + result.append(chr(((snippet[2] & 0x03) << 6) | (snippet[3]))) + elif length == 3: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + result.append(chr(((snippet[1] & 0x0f) << 4) | (snippet[2] >> 2))) + elif length == 2: + result.append(chr(((snippet[0] & 0x3f) << 2) | (snippet[1] >> 4))) + except Apa: + done = 1 + except Error: + raise + return (''.join(result), done) def b2a_hqx(s): result =[] - gen = unpadded_triples(s) - for snippet in gen: + + def triples_gen(s): + while s: + try: + yield ord(s[0]), ord(s[1]), ord(s[2]) + except IndexError: + yield tuple([ord(c) for c in s]) + s = s[3:] + + for snippet in triples_gen(s): length = len(snippet) if length == 3: result.append( @@ -399,11 +484,16 @@ def crc_hqx(s, crc): for c in s: - crc=((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ c] + crc = ((crc << 8) & 0xff00) ^ crctab_hqx[((crc >> 8) & 0xff) ^ ord(c)] return crc def rlecode_hqx(s): + """ + Run length encoding for binhex4. + The CPython implementation does not do run length encoding + of \x90 characters. This implementation does. + """ result = [] prev = s[0] count = 1 @@ -558,16 +648,14 @@ def pairs_gen(s): while s: try: - a, b = s[0], s[1] + yield table_hex[ord(s[0])], table_hex[ord(s[1])] except IndexError: if len(s): raise TypeError('Odd-length string') return s = s[2:] - yield table_hex[ord(a)], table_hex[ord(b)] - pairs = pairs_gen(t) - for a, b in pairs: + for a, b in pairs_gen(t): if a < 0 or b < 0: raise TypeError('Non-hexadecimal digit found') result.append(chr((a << 4) + b)) Modified: pypy/branch/dist-2.4.1/pypy/lib/struct.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/lib/struct.py (original) +++ pypy/branch/dist-2.4.1/pypy/lib/struct.py Tue Jul 5 12:03:38 2005 @@ -108,7 +108,7 @@ if not isinstance(number, (int,long)): raise StructError,"argument for i,I,l,L,q,Q,h,H must be integer" if number > 2**(8*size-1)-1 or number < -1*2**(8*size-1): - raise OverflowError,"Number:%i to large to convert" % number + raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) def pack_unsigned_int(number,size,le): @@ -117,7 +117,7 @@ if number < 0: raise TypeError,"can't convert negative long to unsigned" if number > 2**(8*size)-1: - raise OverflowError,"Number:%i to large to convert" % number + raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) def pack_char(char,size,le): Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py Tue Jul 5 12:03:38 2005 @@ -91,9 +91,9 @@ return W_LongObject(w_intobj.space, digits, sign) # long-to-float delegation -def delegate_Long2Float(w_longobj): #YYYYYY +def delegate_Long2Float(w_longobj): try: - return W_FloatObject(w_longobj.space, float(w_longobj.longval())) + return W_FloatObject(w_longobj.space, _AsDouble(w_longobj)) except OverflowError: raise OperationError(w_longobj.space.w_OverflowError, w_longobj.space.wrap("long int too large to convert to float")) @@ -127,9 +127,9 @@ #subtypes of long are converted to long! return long__Long(space, w_value) -def float__Long(space, w_longobj): #YYYYYY +def float__Long(space, w_longobj): try: - return space.newfloat(float(w_longobj.longval())) + return space.newfloat(_AsDouble(w_longobj)) except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to float")) @@ -253,30 +253,16 @@ result.sign = w_long1.sign * w_long2.sign return result -def truediv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - try: - z = operator.truediv(x, y) - except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("long/long too large for a float")) - return space.newfloat(float(z)) - -def floordiv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - z = x // y - return W_LongObject(space, *args_from_long(z)) +def truediv__Long_Long(space, 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, rem = _divrem(space, w_long1, w_long2) + return div old_style_div = 1 / 2 == 1 // 2 -def div__Long_Long(space, w_long1, w_long2): #YYYYYY +def div__Long_Long(space, w_long1, w_long2): # Select the proper div if old_style_div: return floordiv__Long_Long(space, w_long1, w_long2) @@ -284,25 +270,13 @@ return truediv__Long_Long(space, w_long1, w_long2) -def mod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z = x % y - return W_LongObject(space, *args_from_long(z)) +def mod__Long_Long(space, w_long1, w_long2): + div, rem = _divrem(space, w_long1, w_long2) + return rem -def divmod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z1, z2 = divmod(x, y) - w_result1 = W_LongObject(space, *args_from_long(z1)) - w_result2 = W_LongObject(space, *args_from_long(z2)) - return space.newtuple([w_result1, w_result2]) +def divmod__Long_Long(space, w_long1, w_long2): + div, rem = _divrem(space, w_long1, w_long2) + return space.newtuple([div, rem]) # helper for pow() #YYYYYY: still needs longval if second argument is negative def _impl_long_long_pow(space, lv, lw, lz=None): @@ -429,7 +403,7 @@ w_result._normalize() return w_result -def rshift__Long_Long(space, w_long1, w_long2): #YYYYYY +def rshift__Long_Long(space, w_long1, w_long2): if w_long2.sign < 0: raise OperationError(space.w_ValueError, space.wrap("negative shift count")) @@ -847,46 +821,120 @@ return a, rem -##def _divrem(a, b) -## size_a = len(a.digits) * 2 -## size_b = len(b.digits) * 2 -## PyLongObject *z; -## -## if (size_b == 0) { -## PyErr_SetString(PyExc_ZeroDivisionError, -## "long division or modulo by zero"); -## return -1; -## } -## if (size_a < size_b || -## (size_a == size_b && -## a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) { -## /* |a| < |b|. */ -## *pdiv = _PyLong_New(0); -## Py_INCREF(a); -## *prem = (PyLongObject *) a; -## return 0; -## } -## if (size_b == 1) { -## digit rem = 0; -## z = divrem1(a, b->ob_digit[0], &rem); -## if (z == NULL) -## return -1; -## *prem = (PyLongObject *) PyLong_FromLong((long)rem); -## } -## else { -## z = x_divrem(a, b, prem); -## if (z == NULL) -## return -1; -## } -## /* Set the signs. -## The quotient z has the sign of a*b; -## the remainder r has the sign of a, -## so a = b*z + r. */ -## if ((a->ob_size < 0) != (b->ob_size < 0)) -## z->ob_size = -(z->ob_size); -## if (a->ob_size < 0 && (*prem)->ob_size != 0) -## (*prem)->ob_size = -((*prem)->ob_size); -## *pdiv = z; -## return 0; +def _divrem(space, a, b): + """ Long division with remainder, top-level routine """ + size_a = len(a.digits) * 2 + size_b = len(b.digits) * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + if b._getshort(size_b-1) == 0: + size_b -= 1 -## XXXX + if size_b == 0: + raise OperationError(w_longobj.space.w_ZeroDivisionError, + w_longobj.space.wrap("long division or modulo by zero")) + + if (size_a < size_b or + (size_a == size_b and + a._getshort(size_a-1) < b._getshort(size_b-1))): + # |a| < |b| + z = W_LongObject(space, [r_uint(0)], 0) + rem = a + return z, rem + if size_b == 1: + z, urem = _divrem1(space, a, b._getshort(0)) + rem = W_LongObject(space, [urem], int(urem != 0)) + else: + z, rem = _x_divrem(space, a, b) + # Set the signs. + # The quotient z has the sign of a*b; + # the remainder r has the sign of a, + # so a = b*z + r. + if a.sign != b.sign: + z.sign = - z.sign + if z.sign < 0 and rem.sign != 0: + rem.sign = - rem.sign + return z, rem + +# ______________ conversions to double _______________ + +def _AsScaledDouble(v): + """ + NBITS_WANTED should be > the number of bits in a double's precision, + but small enough so that 2**NBITS_WANTED is within the normal double + range. nbitsneeded is set to 1 less than that because the most-significant + Python digit contains at least 1 significant bit, but we don't want to + bother counting them (catering to the worst case cheaply). + + 57 is one more than VAX-D double precision; I (Tim) don't know of a double + format with more precision than that; it's 1 larger so that we add in at + least one round bit to stand in for the ignored least-significant bits. + """ + NBITS_WANTED = 57 + multiplier = float(1 << SHORT_BIT) + if v.sign == 0: + return 0.0, 0 + i = len(v.digits) * 2 - 1 + if v._getshort(i) == 0: + i -= 1 + sign = v.sign + x = float(v._getshort(i)) + nbitsneeded = NBITS_WANTED - 1 + # Invariant: i Python digits remain unaccounted for. + while i > 0 and nbitsneeded > 0: + i -= 1 + x = x * multiplier + float(v._getshort(i)) + nbitsneeded -= SHORT_BIT + # There are i digits we didn't shift in. Pretending they're all + # zeroes, the true value is x * 2**(i*SHIFT). + exponent = i + assert x > 0.0 + return x * sign, exponent + +# XXX make ldexp and isinf a builtin float support function + +def isinf(x): + return x*2 == x + +def ldexp(x, exp): + assert type(x) is float + lb1 = LONG_BIT - 1 + multiplier = float(r_uint(1) << lb1) + while exp >= lb1: + x *= multiplier + exp -= lb1 + if exp: + x *= float(r_uint(1) << exp) + return x + +def _AsDouble(v): + """ Get a C double from a long int object. """ + x, e = _AsScaledDouble(v) + if e <= sys.maxint / SHORT_BIT: + x = ldexp(x, e * SHORT_BIT) + if not isinf(x): + return x + raise OverflowError# sorry, "long int too large to convert to float" + +def _long_true_divide(space, a, b): + try: + ad, aexp = _AsScaledDouble(a) + bd, bexp = _AsScaledDouble(b) + if bd == 0.0: + 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 + aexp -= bexp + if aexp > sys.maxint / SHORT_BIT: + raise OverflowError + elif aexp < -(sys.maxint / SHORT_BIT): + return 0.0 # underflow to 0 + ad = ldexp(ad, aexp * SHORT_BIT) + if isinf(ad): # ignore underflow to 0.0 + raise OverflowError + return ad + except OverflowError: + raise OperationError(space.w_OverflowError, + space.wrap("long/long too large for a float")) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py Tue Jul 5 12:03:38 2005 @@ -68,6 +68,50 @@ div, rem = lobj._divrem1(self.space, f1, f2) assert (div.longval(), rem) == divmod(x, y) + def test__muladd1(self): + x = 1238585838347L + y = 3 + z = 42 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f2 = r_uint(y) + f3 = r_uint(z) + prod = lobj._muladd1(self.space, f1, f2, f3) + assert prod.longval() == x * y + z + + def test__x_divrem(self): + x = 12345678901234567890L + for i in range(100): + 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)) + div, rem = lobj._x_divrem(self.space, f1, f2) + assert div.longval(), rem.longval() == divmod(x, y) + + def test__divrem(self): + x = 12345678901234567890L + for i in range(100): + y = long(randint(0, 1 << 30)) + y <<= 30 + y += randint(0, 1 << 30) + 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)) + div, rem = lobj._x_divrem(self.space, 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)) + d = lobj._AsDouble(f1) + assert d == float(x) + x = x ** 100 + f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + assert raises(OverflowError, lobj._AsDouble, f1) + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L @@ -220,10 +264,18 @@ def test_sub(self): assert int(58543L - 12332L) == 58543 - 12332 assert 237123838281233L * 12 == 237123838281233L * 12L - + def test_mul(self): assert 363L * 2 ** 40 == 363L << 40 + def test_truediv(self): + exec "from __future__ import division; a = 31415926L / 10000000L" + assert a == 3.1415926 + + def test_floordiv(self): + a = 31415926L // 10000000L + assert a == 3L + def test_conversion(self): class long2(long): pass Modified: pypy/branch/dist-2.4.1/pypy/tool/option.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/tool/option.py (original) +++ pypy/branch/dist-2.4.1/pypy/tool/option.py Tue Jul 5 12:03:38 2005 @@ -15,6 +15,7 @@ compiler = "cpython" # "cpython" # "pyparse" pypy parser, cpython compiler # "pycomp" pypy parser and compiler (TBD) + version = "2.4" # "native" / "2.3" / "2.4" def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server @@ -51,6 +52,11 @@ '--parsermodule', action="store",type="string", dest="useparsermodule", help="select the parser module to use", metavar="[cpython|recparser|parser]")) +## for this to work the option module need to be loaded before the grammar! +## options.append(make_option( +## '--version', action="store",type="string", dest="version", +## help="select the Python version to emulate", +## metavar="[native|2.3|2.4]")) return options Modified: pypy/branch/dist-2.4.1/pypy/translator/goal/targetparser.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/goal/targetparser.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/goal/targetparser.py Tue Jul 5 12:03:38 2005 @@ -14,8 +14,7 @@ # _____ Define and setup target ___ def target(): - s_list_of_strings = SomeList(ListDef(None, SomeString())) - return entry_point, [s_list_of_strings] + return entry_point, [str] # _____ Run translated _____ def run(c_entry_point): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py Tue Jul 5 12:03:38 2005 @@ -2,23 +2,31 @@ from pypy.rpython import lltype from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode +from pypy.objspace.flow.model import Constant import itertools log = log.structnode count = itertools.count().next +def wrapstr(s): + return '"%s"' % s + class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): self.db = db assert isinstance(array, lltype.Array) self.array = array - ref_template = "%%array.%s." % array.OF c = count() - self.ref = ref_template + str(c) - self.constructor_ref = "%%new.array.%s" % c - self.constructor_decl = "%s * %s(int %%len)" % ( - self.ref, self.constructor_ref) + ref_template = wrapstr("%%array.%s." + str(c)) + + self.ref = ref_template % array.OF + self.constructor_ref = wrapstr("%%new.array.%s" % c) + self.constructor_decl = "%s * %s(int %%len)" % \ + (self.ref, self.constructor_ref) + + def __str__(self): + return "" % self.ref def writedecl(self, codewriter): # declaration for constructor @@ -38,6 +46,8 @@ store int %len, int* %arraylength ret %array* %result }""" + from pypy.translator.llvm2.atomic import is_atomic + log.writeimpl(self.ref) codewriter.openfunc(self.constructor_decl) indices = [("uint", 1), ("int", "%len")] @@ -45,16 +55,13 @@ "null", *indices) fromtype = self.db.repr_arg_type(self.array.OF) codewriter.cast("%usize", fromtype + "*", "%size", "uint") - codewriter.malloc("%ptr", "sbyte", "%usize") + codewriter.malloc("%ptr", "sbyte", "%usize", atomic=is_atomic(self)) codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) codewriter.store("int", "%len", "%arraylength") codewriter.ret(self.ref+"*", "%result") codewriter.closefunc() - def __str__(self): - return "" % self.ref - def setup(self): self.db.prepare_repr_arg_type(self.array.OF) self._issetup = True @@ -75,8 +82,8 @@ def __init__(self, db, value): self.db = db - self.name = "%s.%s" % (value._TYPE.OF, ArrayNode.array_counter) - self.ref = "%%stinstance.%s" % self.name + name = '"%%arrayinstance.%s.%s"' % (value._TYPE.OF, ArrayNode.array_counter) + self.ref = name self.value = value ArrayNode.array_counter += 1 @@ -87,14 +94,15 @@ T = self.value._TYPE.OF for item in self.value.items: if not isinstance(T, lltype.Primitive): - value = getattr(self.value, name) # Create a dummy constant hack XXX - c = Constant(value, T) + c = Constant(item, T) self.db.prepare_arg(c) self._issetup = True - def get_values(self): + def getall(self): + arraylen = len(self.value.items) + res = [] T = self.value._TYPE.OF @@ -107,11 +115,17 @@ value = repr(value) res.append((typval, value)) - return ", ".join(["%s %s" % (t, v) for t, v in res]) + arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) + type_ = "{ int, [%s x %s] }" % (len(self.value.items), + self.db.repr_arg_type(self.value._TYPE.OF)) + + value = "int %s, [%s x %s] [ %s ]" % (arraylen, + arraylen, + typval, + arrayvalues) + return type_, value + def writeglobalconstants(self, codewriter): - lenitems = len(self.value.items) - lenstr = ".%s" % lenitems - codewriter.globalinstance(self.ref, - self.db.repr_arg_type() + lenstr, - self.get_values()) + type_, values = self.getall() + codewriter.globalinstance(self.ref, type_, values) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/build_llvm_module.py Tue Jul 5 12:03:38 2005 @@ -33,7 +33,7 @@ libraries = %(library_files)s, extra_objects = %(object_files)s)]) ''' % locals()))) - cmd = "python %s_setup.py build_ext --inplace" % module + cmd = "python %s_setup.py build_ext --inplace --force" % module if debug: print cmd cmdexec(cmd) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py Tue Jul 5 12:03:38 2005 @@ -10,7 +10,6 @@ class CodeWriter(object): def __init__(self): self._lines = [] - self.append('declare sbyte* %GC_malloc(uint)') def append(self, line): if show_line_numbers: @@ -94,12 +93,16 @@ self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) - def malloc(self, targetvar, type_, size=1): + def malloc(self, targetvar, type_, size=1, atomic=False): if use_boehm_gc: cnt = count() - self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, int %(size)d" % locals()) + if atomic: + atomicString = '_atomic' + else: + atomicString = '' + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, uint %(size)s" % locals()) self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) - self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc(uint %%malloc.SizeU.%(cnt)d)" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc%(atomicString)s(uint %%malloc.SizeU.%(cnt)d)" % locals()) self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) else: self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py Tue Jul 5 12:03:38 2005 @@ -1,6 +1,7 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode -from pypy.translator.llvm2.structnode import StructNode, StructTypeNode, StructVarsizeTypeNode +from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ + StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -82,7 +83,11 @@ value = value._obj if isinstance(ct, lltype.Struct): - self.addpending(const_or_var, StructNode(self, value)) + if ct._arrayfld: + assert False, "HERE" + self.addpending(const_or_var, StructVarsizeNode(self, value)) + else: + self.addpending(const_or_var, StructNode(self, value)) elif isinstance(ct, lltype.Array): self.addpending(const_or_var, ArrayNode(self, value)) @@ -141,7 +146,6 @@ if subset_types is None or isinstance(v, subset_types): res.append(v) return res - # __________________________________________________________ # Representing variables and constants in LLVM source code Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py Tue Jul 5 12:03:38 2005 @@ -5,6 +5,7 @@ from pypy.translator.backendoptimization import remove_same_as from pypy.translator.unsimplify import remove_double_links from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log log = log.funcnode @@ -251,8 +252,9 @@ assert (isinstance(arg, Constant) and isinstance(arg.value, lltype.Struct)) #XXX unclean - type = self.db.obj2node[arg.value].ref - self.codewriter.malloc(targetvar, type) + node = self.db.obj2node[arg.value] + type_ = node.ref + self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) def malloc_varsize(self, op): targetvar = self.db.repr_arg(op.result) @@ -273,18 +275,16 @@ typevar = self.db.repr_arg(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) - + self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" - #XXX This doesnt work - yet - #if isinstance(op.result.concretetype, lltype.Ptr): - # self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - #else: - # Moving to correct result variable - #self.codewriter.load(targetvar, targettype, tmpvar) - self.codewriter.load(targetvar, targettype, tmpvar) + if isinstance(op.result.concretetype, lltype.ContainerType): + # noop + self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + else: + self.codewriter.load(targetvar, targettype, tmpvar) + getsubstruct = getfield def setfield(self, op): @@ -304,20 +304,16 @@ vartype = self.db.repr_arg_type(op.args[0]) index = self.db.repr_arg(op.args[1]) indextype = self.db.repr_arg_type(op.args[1]) - tmpvar = self.db.repr_tmpvar() self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 1), (indextype, index)) - targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - - # Ditto see getfield - if not isinstance(op.result.concretetype, lltype.Ptr): - self.codewriter.load(targetvar, targettype, tmpvar) - else: - # XXX noop + if isinstance(op.result.concretetype, lltype.ContainerType): + # noop self.codewriter.cast(targetvar, targettype, tmpvar, targettype) + else: + self.codewriter.load(targetvar, targettype, tmpvar) def setarrayitem(self, op): array = self.db.repr_arg(op.args[0]) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py Tue Jul 5 12:03:38 2005 @@ -1,5 +1,5 @@ from os.path import exists -use_boehm_gc = exists('/usr/lib/libgc.so') +use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') import py from pypy.translator.llvm2 import build_llvm_module @@ -13,6 +13,8 @@ from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void +function_count = {} + def genllvm(translator): remove_void(translator) func = translator.entrypoint @@ -37,6 +39,10 @@ typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() + if use_boehm_gc: + codewriter.declare('sbyte* %GC_malloc(uint)') + codewriter.declare('sbyte* %GC_malloc_atomic(uint)') + codewriter.declare('sbyte* %GC_realloc(sbyte*, uint)') for typ_decl in db.getobjects(): typ_decl.writedecl(codewriter) @@ -47,21 +53,27 @@ typ_decl.writeimpl(codewriter) comment("End of file") ; nl() + + if func.func_name in function_count: + postfix = '_%d' % function_count[func.func_name] + function_count[func.func_name] += 1 + else: + postfix = '' + function_count[func.func_name] = 1 targetdir = udir - llvmsource = targetdir.join(func.func_name).new(ext='.ll') + llvmsource = targetdir.join(func.func_name+postfix).new(ext='.ll') content = str(codewriter) llvmsource.write(content) log.source(content) if not llvm_is_on_path(): py.test.skip("llvm not found") # XXX not good to call py.test.skip here - - pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') + + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+postfix+'.pyx') write_pyx_wrapper(entrynode, pyxsource) - mod = build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) - return getattr(mod, func.func_name + "_wrapper") + return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) def llvm_is_on_path(): try: Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/pyxwrapper.py Tue Jul 5 12:03:38 2005 @@ -1,5 +1,6 @@ from pypy.translator.llvm2.log import log from pypy.rpython import lltype +from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.pyrex PRIMITIVES_TO_C = {lltype.Signed: "int", @@ -23,6 +24,11 @@ inputargs = funcgen.db.repr_arg_multi(funcgen.graph.startblock.inputargs) inputargs = [x.strip("%") for x in inputargs] append("cdef extern " + c_declaration()) + if use_boehm_gc: + append("cdef extern int GC_get_heap_size()") + append("") + append("def GC_get_heap_size_wrapper():") + append(" return GC_get_heap_size()") append("") append("def %s_wrapper(%s):" % (funcgen.ref.strip("%"), ", ".join(inputargs))) append(" return %s(%s)" % (funcgen.ref.strip("%"), ", ".join(inputargs))) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py Tue Jul 5 12:03:38 2005 @@ -42,18 +42,23 @@ super(StructVarsizeTypeNode, self).__init__(db, struct) new_var_name = "%%new.st.var.%s" % self.name self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + + def __str__(self): + return "" %(self.ref,) def writedecl(self, codewriter): # declaration for constructor codewriter.declare(self.constructor_name) def writeimpl(self, codewriter): + from pypy.translator.llvm2.atomic import is_atomic + log.writeimpl(self.ref) codewriter.openfunc(self.constructor_name) codewriter.label("block0") indices_to_array = [("int", 0)] s = self.struct - while isintance(s, lltypes.Struct): + while isinstance(s, lltype.Struct): last_pos = len(self.struct._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) s = s._flds.values()[-1] @@ -65,7 +70,7 @@ #XXX is this ok for 64bit? codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "uint", "%sizeu") + codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=is_atomic(self)) codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") # remember the allocated length for later use. @@ -79,14 +84,22 @@ codewriter.ret(self.ref + "*", "%result") codewriter.closefunc() + +def cast_global(toptr, from_, name): + s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, + from_, + name, + toptr) + return s + class StructNode(LLVMNode): _issetup = False struct_counter = 0 def __init__(self, db, value): self.db = db - self.name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) - self.ref = "%%stinstance.%s" % self.name + name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) + self.ref = "%%stinstance.%s" % name self.value = value StructNode.struct_counter += 1 @@ -105,9 +118,40 @@ self._issetup = True - def get_values(self): + def getall(self): res = [] - for name in self.value._TYPE._names_without_voids(): + type_ = self.value._TYPE + for name in type_._names_without_voids(): + T = type_._flds[name] + value = getattr(self.value, name) + if not isinstance(T, lltype.Primitive): + # Create a dummy constant hack XXX + c = Constant(value, T) + x = self.db.obj2node[c] + value = self.db.repr_arg(c) + t, v = x.getall() + value = cast_global(self.db.repr_arg_type(T), t, value) + + else: + value = str(value) + res.append((self.db.repr_arg_type(T), value)) + + typestr = self.db.repr_arg_type(type_) + values = ", ".join(["%s %s" % (t, v) for t, v in res]) + return typestr, values + + def writeglobalconstants(self, codewriter): + type_, values = self.getall() + codewriter.globalinstance(self.ref, type_, values) + +class StructVarsizeNode(StructNode): + def __str__(self): + return "" %(self.ref,) + + def getall(self): + + res = [] + for name in self.value._TYPE._names_without_voids()[:-1]: T = self.value._TYPE._flds[name] value = getattr(self.value, name) if not isinstance(T, lltype.Primitive): @@ -116,10 +160,18 @@ else: value = str(value) res.append((self.db.repr_arg_type(T), value)) - return ", ".join(["%s %s" % (t, v) for t, v in res]) - - def writeglobalconstants(self, codewriter): - codewriter.globalinstance(self.ref, - self.db.repr_arg_type(self.value._TYPE), - self.get_values()) + # Special case for varsized arrays + self.value._TYPE._names_without_voids()[-1] + x = self.db.obj2node[Constant(value, T)] + t, v = x.get_values() + res.append((t, "{%s}" % v)) + + s = self.value._TYPE + fields = [getattr(s, name) for name in s._names_without_voids()[-1]] + l = [self.db.repr_arg_type(field) for field in fields] + l += t + typestr = "{ %s }" % ", ".join(l) + values = ", ".join(["%s %s" % (t, v) for t, v in res]) + return typestr, values + Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 12:03:38 2005 @@ -19,7 +19,7 @@ ## def setup_module(mod): ## mod.llvm_found = is_on_path("llvm-as") -def compile_function(function, annotate, view=False): +def compile_module(function, annotate, view=False): t = Translator(function) a = t.annotate(annotate) t.specialize() @@ -28,23 +28,37 @@ t.view() return genllvm(t) +def compile_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + return getattr(mod, function.func_name + "_wrapper") + +def compile_module_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + f = getattr(mod, function.func_name + "_wrapper") + return mod, f + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") return - py.test.skip("test_GC_malloc skipped because test not yet correct (Boehm collector IS used anyway)") - return def tuple_getitem(n): - x = 0 + x = 666 i = 0 while i < n: - l = (1,2,i,234,23,23,23,234,234,234,234) + l = (1,2,i,4,5,6,7,8,9,10,11) x += l[2] i += 1 return x - f = compile_function(tuple_getitem, [int]) - t = 1024*1024*100 - f(t) #assert f(t) == t + mod,f = compile_module_function(tuple_getitem, [int]) + n = 5000 + result = tuple_getitem(n) + assert f(n) == result + get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") + heap_size_start = get_heap_size() + for i in range(0,25): + assert f(n) == result + heap_size_inc = get_heap_size() - heap_size_start + assert heap_size_inc < 500000 def test_return1(): def simple1(): @@ -196,15 +210,15 @@ if m == 0: return ackermann(n - 1, 1) return ackermann(n - 1, ackermann(n, m - 1)) - f = compile_function(call_ackermann, [int, int], view=False) + f = compile_function(call_ackermann, [int, int]) assert f(0, 2) == 3 def test_tuple_getitem(): def tuple_getitem(i): - l = (1,2,i) + l = (4,5,i) return l[1] f = compile_function(tuple_getitem, [int]) - assert f(1) == 2 + assert f(1) == tuple_getitem(1) def test_nested_tuple(): def nested_tuple(i): @@ -228,7 +242,7 @@ assert f(-1) == 3 assert f(0) == 5 -def DONOT_test_simple_chars(): +def Xtest_simple_chars(): def char_constant2(s): s = s + s + s return len(s + '.') @@ -246,6 +260,29 @@ assert f(1) == 2 assert f(2) == 3 +def test_list_list_getitem(): + def list_list_getitem(): + l = [[1]] + return l[0][0] + f = compile_function(list_list_getitem, []) + assert f() == 1 + +def test_list_getitem_pbc(): + 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(): + 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(): def list_basic_ops(i, j): l = [1,2,3] From cfbolz at codespeak.net Tue Jul 5 12:16:49 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Jul 2005 12:16:49 +0200 (CEST) Subject: [pypy-svn] r14264 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050705101649.859DD27B42@code1.codespeak.net> Author: cfbolz Date: Tue Jul 5 12:16:49 2005 New Revision: 14264 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: added (passing) test for global tuples Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 12:16:49 2005 @@ -227,6 +227,20 @@ 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(): def f2(x): return x+1 From pedronis at codespeak.net Tue Jul 5 12:23:58 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 12:23:58 +0200 (CEST) Subject: [pypy-svn] r14265 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050705102358.C744027B40@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 12:23:48 2005 New Revision: 14265 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/translator/test/test_annrpython.py Log: annotation for int(string[,16]) Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 5 12:23:48 2005 @@ -66,8 +66,15 @@ def builtin_bool(s_obj): return constpropagate(bool, [s_obj], SomeBool()) -def builtin_int(s_obj): - return constpropagate(int, [s_obj], SomeInteger()) +def builtin_int(s_obj, s_base=None): + assert (s_base is None or s_base.is_constant() + and s_base.const == 16 + and s_obj.knowntype == str), "only int(v|string) or int(string,16) expected" + if s_base is not None: + args_s = [s_obj, s_base] + else: + 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], Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Tue Jul 5 12:23:48 2005 @@ -1380,6 +1380,13 @@ s = a.build_types(f, [int]) assert s == a.bookkeeper.immutablevalue(12) + def test_int(self): + def f(x, s): + return int(x) + int(s) + int(s, 16) + a = self.RPythonAnnotator() + s = a.build_types(f, [int, str]) + assert s.knowntype == int + def g(n): return [0,1,2,n] From arigo at codespeak.net Tue Jul 5 12:31:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 12:31:23 +0200 (CEST) Subject: [pypy-svn] r14266 - pypy/dist/pypy/interpreter Message-ID: <20050705103123.AA31827B40@code1.codespeak.net> Author: arigo Date: Tue Jul 5 12:31:22 2005 New Revision: 14266 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: For now, move these import statements to a place where they will only execute when running with the --pyparse option. This avoids confusion created by the "Loading grammar" message that shows up even if you forget --pyparse. Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Tue Jul 5 12:31:22 2005 @@ -169,13 +169,6 @@ ######## -from pypy.interpreter import stablecompiler -from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator -from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator -from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator -from pypy.interpreter.stablecompiler.transformer import Transformer -from pyparser.pythonutil import ast_from_input - class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler @@ -185,6 +178,13 @@ the whole source after having only added a new '\n') """ def compile(self, source, filename, mode, flags): + from pypy.interpreter import stablecompiler + from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator + from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator + from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator + from pypy.interpreter.stablecompiler.transformer import Transformer + from pyparser.pythonutil import ast_from_input + flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: From arigo at codespeak.net Tue Jul 5 12:35:34 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 12:35:34 +0200 (CEST) Subject: [pypy-svn] r14267 - in pypy/branch/dist-2.4.1/pypy: annotation interpreter translator/llvm2/test translator/test Message-ID: <20050705103534.1CC5327B40@code1.codespeak.net> Author: arigo Date: Tue Jul 5 12:35:33 2005 New Revision: 14267 Modified: pypy/branch/dist-2.4.1/pypy/annotation/builtin.py pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py pypy/branch/dist-2.4.1/pypy/translator/test/test_annrpython.py Log: svn merge -r14261:14266 http://codespeak.net/svn/pypy/dist Modified: pypy/branch/dist-2.4.1/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/annotation/builtin.py (original) +++ pypy/branch/dist-2.4.1/pypy/annotation/builtin.py Tue Jul 5 12:35:33 2005 @@ -66,8 +66,15 @@ def builtin_bool(s_obj): return constpropagate(bool, [s_obj], SomeBool()) -def builtin_int(s_obj): - return constpropagate(int, [s_obj], SomeInteger()) +def builtin_int(s_obj, s_base=None): + assert (s_base is None or s_base.is_constant() + and s_base.const == 16 + and s_obj.knowntype == str), "only int(v|string) or int(string,16) expected" + if s_base is not None: + args_s = [s_obj, s_base] + else: + 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], Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Tue Jul 5 12:35:33 2005 @@ -169,13 +169,6 @@ ######## -from pypy.interpreter import stablecompiler -from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator -from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator -from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator -from pypy.interpreter.stablecompiler.transformer import Transformer -from pyparser.pythonutil import ast_from_input - class PythonCompiler(CPythonCompiler): """Uses the stdlib's python implementation of compiler @@ -185,6 +178,13 @@ the whole source after having only added a new '\n') """ def compile(self, source, filename, mode, flags): + from pypy.interpreter import stablecompiler + from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator + from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator + from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator + from pypy.interpreter.stablecompiler.transformer import Transformer + from pyparser.pythonutil import ast_from_input + flags |= __future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 12:35:33 2005 @@ -227,6 +227,20 @@ 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(): def f2(x): return x+1 Modified: pypy/branch/dist-2.4.1/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/test/test_annrpython.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/test/test_annrpython.py Tue Jul 5 12:35:33 2005 @@ -1380,6 +1380,13 @@ s = a.build_types(f, [int]) assert s == a.bookkeeper.immutablevalue(12) + def test_int(self): + def f(x, s): + return int(x) + int(s) + int(s, 16) + a = self.RPythonAnnotator() + s = a.build_types(f, [int, str]) + assert s.knowntype == int + def g(n): return [0,1,2,n] From hpk at codespeak.net Tue Jul 5 12:49:13 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 12:49:13 +0200 (CEST) Subject: [pypy-svn] r14268 - pypy/extradoc/sprintinfo Message-ID: <20050705104913.0A75A27B40@code1.codespeak.net> Author: hpk Date: Tue Jul 5 12:49:13 2005 New Revision: 14268 Removed: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: status of 5th July and some planning for today Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Tue Jul 5 12:49:13 2005 @@ -39,18 +39,9 @@ we decide about pairing at the venue (after everybody tells what he/she is interested in). These are the people expected currently:: - Gustavo Niemeyer until 3rd (including) - - Adrien Di Mascio until 4th (including) - Carl Friedrich Bolz until 5th afternoon Richard Emslie whole-time (until 10th) - Armin Rigo whole-time - - Niklaus Haldimann until 4th (including) - - Ludovic Aubry until 4th (including) Anders Chrigstroem whole-time (likely) Anders Qvist whole-time (likely) Holger Krekel whole-time @@ -58,7 +49,6 @@ Christian Tismer whole-time Laura Creighton whole-time Samuele Pedroni whole-time - Eric van Riet Paap until 8th Bert Freudenberg whole-time @@ -74,7 +64,9 @@ Builtins -------- - implement int(string) and int(string, 16) + (arre, bert) implement int(string) and int(string, 16) + rclass: (easy) issubtype (use issubclass to generate + an example that has issubtype in the annotated flow graph) (strange)(delegating to backend?) sys.getrefcount (medium) applevel sys module should not refer to @@ -82,11 +74,6 @@ (generate c_api calls) os.path.exists (generate c_api calls) os.path.isdir - Unary operations - ---------------- - - rclass: (easy) issubtype - Overridden functions in PyPy ---------------------------- @@ -112,7 +99,7 @@ ----------------------- subcoach: Armin -Niklaus, Arre, Anders +Arre, Anders experiment in a branch with using Python 2.4 semantics and the standard library @@ -122,14 +109,15 @@ review ca. 1 modified test files) * Merge 2.4.1 branch (blocked by parser/compiler being able - to process 2.4.1 files on top of CPython 2.3.4) + to process 2.4.1 files on top of CPython 2.3.4, Armin looks + into that) * DONE: semantic differences: comparison of recursive data structures, more? * new required C-level modules: - DONE: 'sets' - - (mostly naively mostly done) implement 'collections' module + - (DONE except for one test) implement 'collections' module - (probably) revert 'bisect' module to the 2.3 version (or 2.5) - (probably) revert 'heapq' module to the 2.3 version (2.5) @@ -144,10 +132,11 @@ broke the high level annotator (in that it produced SomeObjects). Consider distributing the actual annotation to multiple hosts. -* (medium) finish objspace/std/longobject.py. +* (Christian, cfbolz) (medium) finish objspace/std/longobject.py. - (MOSTLY DONE) div implementation (christian, jacob) -* (hard, starting soon to be discussed) find a way +* (Samuele, Eric) (hard, doc in + pypy/documentation/ext-functions-draft.txt) find a way to generate c_api calls (including automated conversions from ll-strings to c-like strings) -> conceptually discussed, needs to be written @@ -161,7 +150,7 @@ functions, etc. (Laura): there now is a program that generates the docstrings into the appropriate places but it needs prettification. -* (should start sometime soon) GC discussion in the middle of the sprint +* (DONE) GC discussion in the middle of the sprint (kickoff Carl Friedrich with Armin/Samuele) * DONE: (should start sunday) _sre module reimplementation kickoff @@ -169,7 +158,7 @@ Rewriting important C functionality in Python -------------------------------------------------- -* parsing/compiling (Adrien) +* parsing/compiling * (PROGRESS): translate to C (fix annotation problems by either tweaking the code or extending the annotator on @@ -186,11 +175,11 @@ * move towards a rpython compliant (translatable) compiler * rewrite in Python a C module you are familiar with - (partial list of missing/incomplete modules: math, array, - regular expressions, binascii...) + (partial list of missing/incomplete modules: math, array (Nik), + regular expressions (Nik)) -* (Jacob, progress) binascii implementation, needs more tests - (but compliancy tests already pass) +* DONE: binascii implementation, needs more tests + (but compliancy tests already pass) * implement Python 2.3's import hook extensions (zip-imports etc.) @@ -205,13 +194,11 @@ - (DONE) arrays work (special case of variable sized structs) -- (PROGRESS, cfbolz, hpk) implement variable - sized structs +- (PROGRESS, cfbolz, hpk) implement variable sized structs - DONE: (Eric, Bert) added some void-helpers to Structs -- there are problems with voids all around the flowgraph, - which is being reduced by a cfg transformation +- (PROGRESS) make prebuilt values work - DONE: support function pointers Deleted: /pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- /pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Tue Jul 5 12:49:13 2005 +++ (empty file) @@ -1,91 +0,0 @@ - -Open areas in translation -------------------------------------- - -Still missing are: - -* currently remaining rtyper topics: - - - found to be missing (ale, arigo):: - - Builtins - -------- - - (strange)(delegating to backend?) sys.getrefcount - (medium) applevel sys module should not refer to - interplevel sys.getdefaultencoding - - implement in RPython (and change importing.py accordingly) - os.path.dirname/normpath/join (including the closure of what they use) - - (generate c_api calls) os.path.exists - (generate c_api calls) os.path.isdir - - Unary operations - ---------------- - - rclass: (easy) issubtype - - (arre, christian): - rdict: (DONE) (easy) method_get (?) - (DONE) (easy) method_copy - (DONE) (easy) method_update (?) - (DONE) (easy) method_keys (?) - (DONE) (easy) method_values (?) - (DONE) (easy) method_items (?) - (DONE) (easy) contains - (DONE) (easy) rstr: str.split(single_constant_character) - (DONE) method_replace with char/char - - - Binary operations - ----------------- - - (DONE) (easy) rstr: mul, inplace_mul (for CharRepr only!) - - (easy) 'contains' applied on: - * (DONE) dict of string keys - * (DONE) constant tuple of ints - * (DONE) constant tuple of strings - * constant tuple of unicode characters - -- needs constant dict of unichr keys - * (DONE) constant dict with int keys - * (DONE via string) constant string - * (DONE) string - - Overridden functions in PyPy - ---------------------------- - - (easy) override:ignore - (easy) override:instantiate - (hard, probably needs to be implemented at C/CPython level): - override:wrap_exception_cls - override:fake_object - override:cpy_compile - -* (DONE) prebuilt immutable dictionaries with int keys - -* (partially DONE) convert each file that does - 'from ... import *' to use explicit imports (e.g. - from pypy.rpython import lltype and then use lltype.*) - -* DONE (holger, michael) translator/c/float_include.h should be complete. - -DONE * translator/c/int_include.h needs unsigned arithmetic operations. - -* progress on translation of example targets: - python demo/bpnn.py (holger, michael, samuele) - python pypy/translator/goal/translate_pypy.py targetrichards.py - -* (medium) write a tool that discovers which revision of the pypy tree - broke the high level annotator (in that it produced SomeObjects). - Consider distributing the actual annotation to multiple hosts. - -* (medium) experiment in a branch with using Python 2.4 semantics - and the standard library (lib-python/2.4.1 ...) - -* (medium) finish objspace/std/longobject.py. - -* (hard) find a way to generate c_api calls with automated - conversions from ll-strings to c-like strings - From ac at codespeak.net Tue Jul 5 12:51:43 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 5 Jul 2005 12:51:43 +0200 (CEST) Subject: [pypy-svn] r14269 - pypy/branch/dist-2.4.1/pypy/objspace/std/test Message-ID: <20050705105143.9740027B44@code1.codespeak.net> Author: ac Date: Tue Jul 5 12:51:43 2005 New Revision: 14269 Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py Log: Remove some incorrect tests. Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_unicodeobject.py Tue Jul 5 12:51:43 2005 @@ -130,7 +130,6 @@ assert u'abc'.center(2) == u'abc' assert u'abc'.center(5, u'*') == u'*abc*' # Python 2.4 assert u'abc'.center(5, '*') == u'*abc*' # Python 2.4 - raises(TypeError, 'abc'.center, 5, u'*') # Python 2.4 raises(TypeError, u'abc'.center, 4, u'cba') def test_rjust(self): @@ -145,7 +144,6 @@ assert u'abc'.rjust(2) == u'abc' assert u'abc'.rjust(5, u'*') == u'**abc' # Python 2.4 assert u'abc'.rjust(5, '*') == u'**abc' # Python 2.4 - raises(TypeError, 'abc'.rjust, 5, u'*') # Python 2.4 raises(TypeError, u'abc'.rjust, 5, u'xx') def test_ljust(self): @@ -160,7 +158,6 @@ assert u'abc'.ljust(2) == u'abc' assert u'abc'.ljust(5, u'*') == u'abc**' # Python 2.4 assert u'abc'.ljust(5, '*') == u'abc**' # Python 2.4 - raises(TypeError, 'abc'.ljust, 5, u'*') # Python 2.4 raises(TypeError, u'abc'.ljust, 6, u'') def test_long_from_unicode(self): From arigo at codespeak.net Tue Jul 5 13:09:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 13:09:15 +0200 (CEST) Subject: [pypy-svn] r14270 - pypy/dist/pypy/interpreter Message-ID: <20050705110915.2C97D27B44@code1.codespeak.net> Author: arigo Date: Tue Jul 5 13:09:14 2005 New Revision: 14270 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: Added some XXXs about DIVIDE vs TRUE_DIVIDE. Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Tue Jul 5 13:09:14 2005 @@ -171,6 +171,7 @@ BINARY_TRUE_DIVIDE = binaryoperation("truediv") BINARY_FLOOR_DIVIDE = binaryoperation("floordiv") BINARY_DIVIDE = binaryoperation("div") + # XXX BINARY_DIVIDE must fall back to BINARY_TRUE_DIVIDE with -Qnew BINARY_MODULO = binaryoperation("mod") BINARY_ADD = binaryoperation("add") BINARY_SUBTRACT = binaryoperation("sub") @@ -191,6 +192,7 @@ INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv") INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv") INPLACE_DIVIDE = binaryoperation("inplace_div") + # XXX INPLACE_DIVIDE must fall back to INPLACE_TRUE_DIVIDE with -Qnew INPLACE_MODULO = binaryoperation("inplace_mod") INPLACE_ADD = binaryoperation("inplace_add") INPLACE_SUBTRACT = binaryoperation("inplace_sub") From cfbolz at codespeak.net Tue Jul 5 13:10:31 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Jul 2005 13:10:31 +0200 (CEST) Subject: [pypy-svn] r14271 - pypy/dist/pypy/objspace/std Message-ID: <20050705111031.7A3CC27B3F@code1.codespeak.net> Author: cfbolz Date: Tue Jul 5 13:10:30 2005 New Revision: 14271 Modified: pypy/dist/pypy/objspace/std/intobject.py pypy/dist/pypy/objspace/std/longobject.py Log: fixed div for ints and longs Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Tue Jul 5 13:10:30 2005 @@ -209,13 +209,8 @@ m = x % y return space.wrap((z,m)) -old_style_div = 1 / 2 == 1 // 2 def div__Int_Int(space, w_int1, w_int2): - # Select the proper div - if old_style_div: - return _floordiv(space, w_int1, w_int2) - else: - return _truediv(space, w_int1, w_int2) + return _floordiv(space, w_int1, w_int2) floordiv__Int_Int = _floordiv truediv__Int_Int = _truediv Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 13:10:30 2005 @@ -261,14 +261,8 @@ div, rem = _divrem(space, w_long1, w_long2) return div -old_style_div = 1 / 2 == 1 // 2 def div__Long_Long(space, w_long1, w_long2): - # Select the proper div - if old_style_div: - return floordiv__Long_Long(space, w_long1, w_long2) - else: - return truediv__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, rem = _divrem(space, w_long1, w_long2) From tismer at codespeak.net Tue Jul 5 13:11:50 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 13:11:50 +0200 (CEST) Subject: [pypy-svn] r14272 - pypy/dist/pypy/objspace/std Message-ID: <20050705111150.89A6727B3F@code1.codespeak.net> Author: tismer Date: Tue Jul 5 13:11:46 2005 New Revision: 14272 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: remove ldexp, using math.ldexp Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 13:11:46 2005 @@ -885,29 +885,31 @@ assert x > 0.0 return x * sign, exponent -# XXX make ldexp and isinf a builtin float support function +##def isinf(x): +## return x != 0.0 and x / 2 == x +## +##def ldexp(x, exp): +## assert type(x) is float +## lb1 = LONG_BIT - 1 +## multiplier = float(r_uint(1) << lb1) +## while exp >= lb1: +## x *= multiplier +## exp -= lb1 +## if exp: +## x *= float(r_uint(1) << exp) +## return x -def isinf(x): - return x*2 == x - -def ldexp(x, exp): - assert type(x) is float - lb1 = LONG_BIT - 1 - multiplier = float(r_uint(1) << lb1) - while exp >= lb1: - x *= multiplier - exp -= lb1 - if exp: - x *= float(r_uint(1) << exp) - return x +# note that math.ldexp checks for overflows, +# while the C ldexp is not guaranteed to. def _AsDouble(v): """ Get a C double from a long int object. """ x, e = _AsScaledDouble(v) if e <= sys.maxint / SHORT_BIT: - x = ldexp(x, e * SHORT_BIT) - if not isinf(x): - return x + x = math.ldexp(x, e * SHORT_BIT) + #if not isinf(x): + # this is checked by math.ldexp + return x raise OverflowError# sorry, "long int too large to convert to float" def _long_true_divide(space, a, b): @@ -925,9 +927,10 @@ raise OverflowError elif aexp < -(sys.maxint / SHORT_BIT): return 0.0 # underflow to 0 - ad = ldexp(ad, aexp * SHORT_BIT) - if isinf(ad): # ignore underflow to 0.0 - raise OverflowError + ad = math.ldexp(ad, aexp * SHORT_BIT) + #if isinf(ad): # ignore underflow to 0.0 + # raise OverflowError + # math.ldexp checks and raises return ad except OverflowError: raise OperationError(space.w_OverflowError, From rxe at codespeak.net Tue Jul 5 13:29:36 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 5 Jul 2005 13:29:36 +0200 (CEST) Subject: [pypy-svn] r14273 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050705112936.4B42F27B3F@code1.codespeak.net> Author: rxe Date: Tue Jul 5 13:29:34 2005 New Revision: 14273 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: A wip checkin - really just as way to sync up code bases. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Tue Jul 5 13:29:34 2005 @@ -97,10 +97,10 @@ # Create a dummy constant hack XXX c = Constant(item, T) self.db.prepare_arg(c) - self._issetup = True def getall(self): + "Returns the type and value for this node. " arraylen = len(self.value.items) res = [] @@ -112,14 +112,16 @@ # Create a dummy constant hack XXX value = self.db.repr_arg(Constant(value, T)) else: - value = repr(value) + if isinstance(value, str): + value = ord(value) + + value = str(value) res.append((typval, value)) - arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) - - type_ = "{ int, [%s x %s] }" % (len(self.value.items), + type_ = "{ int, [%s x %s] }" % (arraylen, self.db.repr_arg_type(self.value._TYPE.OF)) + arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, typval, Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Tue Jul 5 13:29:34 2005 @@ -84,7 +84,6 @@ if isinstance(ct, lltype.Struct): if ct._arrayfld: - assert False, "HERE" self.addpending(const_or_var, StructVarsizeNode(self, value)) else: self.addpending(const_or_var, StructNode(self, value)) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Tue Jul 5 13:29:34 2005 @@ -1,6 +1,9 @@ from os.path import exists use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') +#XXXTmp +use_boehm_gc = False + import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Tue Jul 5 13:29:34 2005 @@ -59,15 +59,17 @@ indices_to_array = [("int", 0)] s = self.struct while isinstance(s, lltype.Struct): - last_pos = len(self.struct._names_without_voids()) - 1 + last_pos = len(s._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) - s = s._flds.values()[-1] + s = s._flds[s._names_without_voids()[-1]] + + arraytype = self.db.repr_arg_type(s) # Into array and length indices = indices_to_array + [("uint", 1), ("int", "%len")] codewriter.getelementptr("%size", self.ref + "*", "null", *indices) - + #XXX is this ok for 64bit? codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=is_atomic(self)) @@ -127,6 +129,8 @@ if not isinstance(T, lltype.Primitive): # Create a dummy constant hack XXX c = Constant(value, T) + + # Needs some sanitisation x = self.db.obj2node[c] value = self.db.repr_arg(c) t, v = x.getall() @@ -149,10 +153,10 @@ return "" %(self.ref,) def getall(self): - res = [] - for name in self.value._TYPE._names_without_voids()[:-1]: - T = self.value._TYPE._flds[name] + type_ = self.value._TYPE + for name in type_._names_without_voids()[:-1]: + T = type_._flds[name] value = getattr(self.value, name) if not isinstance(T, lltype.Primitive): # Create a dummy constant hack XXX @@ -162,16 +166,19 @@ res.append((self.db.repr_arg_type(T), value)) # Special case for varsized arrays - self.value._TYPE._names_without_voids()[-1] - x = self.db.obj2node[Constant(value, T)] - t, v = x.get_values() - res.append((t, "{%s}" % v)) - - s = self.value._TYPE - fields = [getattr(s, name) for name in s._names_without_voids()[-1]] - l = [self.db.repr_arg_type(field) for field in fields] - l += t - typestr = "{ %s }" % ", ".join(l) + name = type_._names_without_voids()[-1] + T = type_._flds[name] + assert not isinstance(T, lltype.Primitive) + value = getattr(self.value, name) + c = Constant(value, T) + x = self.db.obj2node[c] + t, v = x.getall() + + #value = self.db.repr_arg(c) + value = cast_global(self.db.repr_arg_type(T), t, "{%s}" % v) + res.append((self.db.repr_arg_type(T), value)) + + typestr = self.db.repr_arg_type(type_) values = ", ".join(["%s %s" % (t, v) for t, v in res]) return typestr, values Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 13:29:34 2005 @@ -288,7 +288,7 @@ f = compile_function(list_getitem_pbc, [int]) assert f(0) == 1 assert f(1) == 2 - + def test_list_list_getitem_pbc(): l = [[0, 1], [0, 1]] def list_list_getitem_pbc(i): @@ -316,9 +316,9 @@ def Xtest_string_getitem1(): l = "Hello, World" - def string_test(i): + def string_getitem1(i): return l[i] - f = compile_function(string_test, [int], view=True) + f = compile_function(string_getitem1, [int], view=True) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From rxe at codespeak.net Tue Jul 5 13:31:20 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 5 Jul 2005 13:31:20 +0200 (CEST) Subject: [pypy-svn] r14274 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705113120.A9D9727B3F@code1.codespeak.net> Author: rxe Date: Tue Jul 5 13:31:19 2005 New Revision: 14274 Modified: pypy/dist/pypy/translator/llvm2/genllvm.py Log: Oups. Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Tue Jul 5 13:31:19 2005 @@ -1,9 +1,6 @@ from os.path import exists use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') -#XXXTmp -use_boehm_gc = False - import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database From arigo at codespeak.net Tue Jul 5 13:38:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 13:38:32 +0200 (CEST) Subject: [pypy-svn] r14276 - in pypy/dist/pypy: interpreter/pyparser module/recparser Message-ID: <20050705113832.9294A27B3F@code1.codespeak.net> Author: arigo Date: Tue Jul 5 13:38:29 2005 New Revision: 14276 Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/module/recparser/pyparser.py Log: Fixes in the imports. Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Tue Jul 5 13:38:29 2005 @@ -1,5 +1,4 @@ -__all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", - "ast_eval_input"] +__all__ = ["python_parse", "pypy_parse"] import parser import symbol Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Tue Jul 5 13:38:29 2005 @@ -8,7 +8,6 @@ from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import SyntaxNode -from pypy.interpreter.pyparser.pythonparse import parse_python_source from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -101,16 +100,14 @@ def suite( space, source ): # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) + builder = PYTHON_PARSER.parse_source( source, "file_input" ) return space.wrap( STType(space, builder.stack[-1]) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) + builder = PYTHON_PARSER.parse_source( source, "eval_input" ) return space.wrap( STType(space, builder.stack[-1]) ) expr.unwrap_spec = [ObjSpace, str] From tismer at codespeak.net Tue Jul 5 14:08:34 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 14:08:34 +0200 (CEST) Subject: [pypy-svn] r14277 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050705120834.DC7E927B42@code1.codespeak.net> Author: tismer Date: Tue Jul 5 14:08:33 2005 New Revision: 14277 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: _FromDouble works, too Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 14:08:33 2005 @@ -885,9 +885,9 @@ assert x > 0.0 return x * sign, exponent -##def isinf(x): -## return x != 0.0 and x / 2 == x -## +def isinf(x): + return x != 0.0 and x / 2 == x + ##def ldexp(x, exp): ## assert type(x) is float ## lb1 = LONG_BIT - 1 @@ -935,3 +935,29 @@ except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("long/long too large for a float")) + + +def _FromDouble(space, dval): + """ Create a new long int object from a C double """ + neg = 0 + if isinf(dval): + raise OperationError(space.w_OverflowError, + space.wrap("cannot convert float infinity to long")) + if dval < 0.0: + neg = 1 + dval = -dval + frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 + if expo <= 0: + return W_LongObject(space, [r_uint(0)], 0) + ndig = (expo-1) // SHORT_BIT + 1 # Number of 'digits' in result + digitpairs = (ndig + 1) // 2 + v = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + frac = math.ldexp(frac, (expo-1) % SHORT_BIT + 1) + for i in range(ndig-1, -1, -1): + bits = int(frac) + v._setshort(i, r_uint(bits)) + frac -= float(bits) + frac = math.ldexp(frac, SHORT_BIT) + if neg: + v.sign = -1 + return v 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 Tue Jul 5 14:08:33 2005 @@ -4,6 +4,7 @@ from pypy.objspace.std import longobject as lobj from pypy.objspace.std.objspace import FailedToImplement from pypy.rpython.rarithmetic import r_uint +from pypy.interpreter.error import OperationError objspacename = 'std' @@ -112,6 +113,18 @@ f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) assert raises(OverflowError, lobj._AsDouble, f1) + def test__FromDouble(self): + x = 1234567890.1234567890 + f1 = lobj._FromDouble(self.space, x) + y = lobj._AsDouble(f1) + assert f1.longval() == long(x) + # check overflow + x = 12345.6789e10000000000000000000000000000 + try: + lobj._FromDouble(self.space, x) + except OperationError, e: + assert e.w_type is self.space.w_OverflowError + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L From cfbolz at codespeak.net Tue Jul 5 14:28:28 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Jul 2005 14:28:28 +0200 (CEST) Subject: [pypy-svn] r14278 - pypy/dist/pypy/objspace/std/test Message-ID: <20050705122828.2EECE27B3E@code1.codespeak.net> Author: cfbolz Date: Tue Jul 5 14:28:27 2005 New Revision: 14278 Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py Log: long division rounds to the wrong direction. added (for now failing) test 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 Tue Jul 5 14:28:27 2005 @@ -302,3 +302,21 @@ def test_getnewargs(self): assert 0L .__getnewargs__() == (0L,) assert (-1L) .__getnewargs__() == (-1L,) + + def test_divmod(self): + def check_division(x, y): + q, r = divmod(x, y) + pab, pba = x*y, y*x + assert pab == pba + assert q == x//y + assert r == x%y + assert x == q*y + r + if y > 0: + assert 0 <= r < y + else: + assert y < r <= 0 + for x in [-1L, 0L, 1L, 2L ** 100 - 1, -2L ** 100 - 1]: + for y in [-105566530L, -1L, 1L, 1034522340L]: + print "checking division for %s, %s" % (x, y) + check_division(x, y) + raises(ZeroDivisionError, "x // 0L") From tismer at codespeak.net Tue Jul 5 14:31:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 14:31:20 +0200 (CEST) Subject: [pypy-svn] r14279 - pypy/dist/pypy/objspace/std Message-ID: <20050705123120.2746E27B3E@code1.codespeak.net> Author: tismer Date: Tue Jul 5 14:31:19 2005 New Revision: 14279 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: getting closer to correct divmod (was divrem by an oversight :-) Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 14:31:19 2005 @@ -258,19 +258,19 @@ return space.newfloat(div) def floordiv__Long_Long(space, w_long1, w_long2): - div, rem = _divrem(space, 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, rem = _divrem(space, w_long1, w_long2) - return rem + div, mod = _l_divmod(space, w_long1, w_long2) + return mod def divmod__Long_Long(space, w_long1, w_long2): - div, rem = _divrem(space, w_long1, w_long2) - return space.newtuple([div, rem]) + div, mod = _l_divmod(space, w_long1, w_long2) + return space.newtuple([div, mod]) # helper for pow() #YYYYYY: still needs longval if second argument is negative def _impl_long_long_pow(space, lv, lw, lz=None): @@ -961,3 +961,27 @@ if neg: v.sign = -1 return v + +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). + The long_divrem function gives the remainder after division of + |a| by |b|, with the sign of a. This is also expressed + as a - b*trunc(a/b), if trunc truncates towards zero. + Some examples: + a b a rem b a mod b + 13 10 3 3 + -13 10 -3 7 + 13 -10 3 -7 + -13 -10 -3 -3 + So, to get from rem to mod, we have to add b if a and b + have different signs. We then subtract one from the 'div' + part of the outcome to keep the invariant intact. + """ + div, mod = _divrem(space, v, w) + if mod.sign * w.sign == -1: + mod = add__Long_Long(space, mod, w) + one = W_LongObject(space, [r_uint(1)], 1) + div = sub__Long_Long(space, div, one) + return div, mod From bert at codespeak.net Tue Jul 5 14:37:47 2005 From: bert at codespeak.net (bert at codespeak.net) Date: Tue, 5 Jul 2005 14:37:47 +0200 (CEST) Subject: [pypy-svn] r14280 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050705123747.DE1F927B3E@code1.codespeak.net> Author: bert Date: Tue Jul 5 14:37:44 2005 New Revision: 14280 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (bert,arre): - implemented int(string) and int(string, base) for bases 2-36 Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 5 14:37:44 2005 @@ -67,9 +67,8 @@ return constpropagate(bool, [s_obj], SomeBool()) def builtin_int(s_obj, s_base=None): - assert (s_base is None or s_base.is_constant() - and s_base.const == 16 - and s_obj.knowntype == str), "only int(v|string) or int(string,16) expected" + assert (s_base is None or isinstance(s_base, SomeInteger) + and s_obj.knowntype == str), "only int(v|string) or int(string,int) expected" if s_base is not None: args_s = [s_obj, s_base] else: Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 5 14:37:44 2005 @@ -87,7 +87,8 @@ def rtype_builtin_int(hop): if isinstance(hop.args_s[0], annmodel.SomeString): - raise TyperError('int("string") not supported') + assert 1 <= hop.nb_args <= 2 + return hop.args_r[0].rtype_int(hop) assert hop.nb_args == 1 return hop.args_r[0].rtype_int(hop) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jul 5 14:37:44 2005 @@ -142,6 +142,16 @@ v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr) return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2) + def rtype_int(_, hop): + if hop.nb_args == 1: + v_str, = hop.inputargs(string_repr) + c_base = inputconst(Signed, 10) + return hop.gendirectcall(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) + return hop.gendirectcall(ll_int, v_str, v_base) + def ll_str(s, r): if typeOf(s) == Char: return ll_chr2str(s) @@ -768,6 +778,47 @@ 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 + # ____________________________________________________________ # # Iteration. Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Jul 5 14:37:44 2005 @@ -2,8 +2,8 @@ from pypy.rpython.lltype import * from pypy.rpython.rstr import parse_fmt_string from pypy.rpython.rtyper import RPythonTyper, TyperError -from pypy.rpython.test.test_llinterp import interpret - +from pypy.rpython.test.test_llinterp import interpret,find_exception +from pypy.rpython.llinterp import LLException def test_simple(): def fn(i): @@ -356,3 +356,20 @@ 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', ''] + 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: + info = raises(LLException, interpret, fn, [i, j]) + assert find_exception(info.value) is ValueError + else: + res = interpret(fn, [i, j]) + assert res == expected From pedronis at codespeak.net Tue Jul 5 14:38:35 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 14:38:35 +0200 (CEST) Subject: [pypy-svn] r14281 - pypy/dist/pypy/annotation Message-ID: <20050705123835.CB4A627B3E@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 14:38:35 2005 New Revision: 14281 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: improved error message Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Tue Jul 5 14:38:35 2005 @@ -627,7 +627,7 @@ raise Exception, "no __init__ found in %r" % (cls,) return s_instance - assert isinstance(func, FunctionType), "[%s] expected function, got %r" % (self.whereami(), func) + assert isinstance(func, FunctionType), "[%s] expected user-defined function, got %r" % (self.whereami(), func) inputcells = self.get_inputcells(func, args) From ac at codespeak.net Tue Jul 5 14:41:18 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 5 Jul 2005 14:41:18 +0200 (CEST) Subject: [pypy-svn] r14282 - pypy/extradoc/sprintinfo Message-ID: <20050705124118.6DA8427B3E@code1.codespeak.net> Author: ac Date: Tue Jul 5 14:41:18 2005 New Revision: 14282 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: int(string) is done. Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Tue Jul 5 14:41:18 2005 @@ -64,7 +64,7 @@ Builtins -------- - (arre, bert) implement int(string) and int(string, 16) + DONE: (arre, bert) implement int(string) and int(string, 16) rclass: (easy) issubtype (use issubclass to generate an example that has issubtype in the annotated flow graph) From tismer at codespeak.net Tue Jul 5 14:43:42 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 14:43:42 +0200 (CEST) Subject: [pypy-svn] r14283 - pypy/dist/pypy/objspace/std Message-ID: <20050705124342.BFDF627B3E@code1.codespeak.net> Author: tismer Date: Tue Jul 5 14:43:41 2005 New Revision: 14283 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: still marginal errors Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 14:43:41 2005 @@ -824,9 +824,9 @@ if b._getshort(size_b-1) == 0: size_b -= 1 - if size_b == 0: - raise OperationError(w_longobj.space.w_ZeroDivisionError, - w_longobj.space.wrap("long division or modulo by zero")) + if b.sign == 0: + raise OperationError(space.w_ZeroDivisionError, + space.wrap("long division or modulo by zero")) if (size_a < size_b or (size_a == size_b and From pedronis at codespeak.net Tue Jul 5 14:45:17 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 14:45:17 +0200 (CEST) Subject: [pypy-svn] r14284 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050705124517.D186B27B3E@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 14:45:15 2005 New Revision: 14284 Added: pypy/dist/pypy/rpython/extfunctable.py (contents, props changed) Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: started implementing the plan in documentation/ext-function-draft about supporting external function calls trhough the translation tool chain. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 5 14:45:15 2005 @@ -335,3 +335,9 @@ BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info +from pypy.rpython import extfunctable + +# import annotation information for external functions +# from the extfunctable.table into our own annotation specific table +for func, extfuncinfo in extfunctable.table.iteritems(): + BUILTIN_ANALYZERS[func] = extfuncinfo.annotation Added: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/extfunctable.py Tue Jul 5 14:45:15 2005 @@ -0,0 +1,35 @@ +""" +information table about external functions for annotation/ rtyping and backends +""" +import os +import types + +class ExtFuncInfo: + def __init__(self, func, annotation, ll_function, ll_annotable): + self.func = func + self.annotation = annotation + self.ll_function = ll_function + self.ll_annotable = ll_annotable + +table = {} +def declare(func, annotation, ll_function, ll_annotable=True): + # annotation can be a function computing the annotation + # or a simple python type from which an annotation will be construcuted + global table + if not isinstance(annotation, types.FunctionType): + typ = annotation + def annotation(*args_s): + from pypy.annotation import bookkeeper + return bookkeeper.getbookkeeper().valueoftype(typ) + table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable) + +# low-level helpers representing the external functions +def ll_os_getuid(): + return 1 #return os.getuid() + +def ll_os_dup(fd): + return 999 + +# external function declarations +declare(os.getuid, int, ll_os_getuid, ll_annotable=True) +declare(os.dup, int, ll_os_dup, ll_annotable=True) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 5 14:45:15 2005 @@ -9,7 +9,7 @@ from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr, FloatRepr from pypy.rpython import rclass - +from pypy.tool import sourcetools class __extend__(annmodel.SomeBuiltin): def rtyper_makerepr(self, rtyper): @@ -241,3 +241,21 @@ includes=("math.h",)) # XXX clean up needed BUILTIN_TYPER[math.exp] = rtype_math_exp + +from pypy.rpython import extfunctable + +def make_rtype_extfunc(extfuncinfo): + ll_function = extfuncinfo.ll_function + if extfuncinfo.ll_annotable: + def rtype_extfunc(hop): + return hop.gendirectcall(ll_function, *hop.args_v) + else: + assert False, "xxx not implemented" + return sourcetools.func_with_new_name(rtype_extfunc, + "rtype_extfunc_%s" % extfuncinfo.func.__name__) + +# import rtyping information for external functions +# from the extfunctable.table into our own specific table +for func, extfuncinfo in extfunctable.table.iteritems(): + BUILTIN_TYPER[func] = make_rtype_extfunc(extfuncinfo) + Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 5 14:45:15 2005 @@ -226,11 +226,13 @@ def getconcretetype(v): return getattr(v, 'concretetype', PyObjPtr) -def getfunctionptr(translator, func, getconcretetype=getconcretetype): +def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype, _callable=None): """Make a functionptr from the given Python function.""" - graph = translator.getflowgraph(func) + graph = translator.getflowgraph(graphfunc) llinputs = [getconcretetype(v) for v in graph.getargs()] lloutput = getconcretetype(graph.getreturnvar()) FT = FuncType(llinputs, lloutput) - return functionptr(FT, func.func_name, graph = graph, _callable = func) + if _callable is None: + _callable = graphfunc + return functionptr(FT, graphfunc.func_name, graph = graph, _callable = _callable) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 5 14:45:15 2005 @@ -355,10 +355,10 @@ # __________ utilities __________ - def getfunctionptr(self, func): + def getfunctionptr(self, graphfunc, _callable=None): def getconcretetype(v): return self.bindingrepr(v).lowleveltype - return getfunctionptr(self.annotator.translator, func, getconcretetype) + return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype, _callable=_callable) def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): self.call_all_setups() # compute ForwardReferences now @@ -516,7 +516,7 @@ dontcare, spec_function = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s) # build the 'direct_call' operation - f = self.rtyper.getfunctionptr(spec_function) + f = self.rtyper.getfunctionptr(spec_function, _callable=ll_function) c = inputconst(typeOf(f), f) return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 5 14:45:15 2005 @@ -1,4 +1,6 @@ from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test import test_llinterp +from pypy.objspace.flow import model as flowmodel from pypy.annotation.builtin import * import py @@ -61,6 +63,35 @@ ry = 100 * float(i-10) +0.1 assert fn(rv,ry) == interpret(fn, (rv, ry)) +def DONOT_test_os_getuid(): + import os + def fn(): + return os.getuid() + assert interpret(fn, []) == fn() + +def test_os_dup(): + import os + def fn(fd): + return os.dup(fd) + res = interpret(fn, [0]) + #try: + # os.close(res) + #except OSError: + # pass + t = test_llinterp.typer.annotator.translator + graph = t.getflowgraph(fn) + count = [0] + def visit(block): + from pypy.rpython import extfunctable + if isinstance(block, flowmodel.Block): + for op in block.operations: + if op.opname == 'direct_call': + cfptr = op.args[0] + assert cfptr.value._obj._callable == extfunctable.ll_os_dup + count[0] += 1 + flowmodel.traverse(visit, graph) + assert count[0] == 1 + def test_pbc_isTrue(): class C: def f(self): From hpk at codespeak.net Tue Jul 5 15:02:05 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 15:02:05 +0200 (CEST) Subject: [pypy-svn] r14285 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705130205.D791827B3F@code1.codespeak.net> Author: hpk Date: Tue Jul 5 15:02:03 2005 New Revision: 14285 Modified: pypy/dist/pypy/translator/llvm2/atomic.py Log: slight refactoring fo is_atomic (but untested, doh) Modified: pypy/dist/pypy/translator/llvm2/atomic.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/atomic.py (original) +++ pypy/dist/pypy/translator/llvm2/atomic.py Tue Jul 5 15:02:03 2005 @@ -1,16 +1,20 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.structnode import StructTypeNode from pypy.translator.llvm2.arraynode import ArrayTypeNode +from pypy.rpython import lltype log = log.atomic def is_atomic(node): + # XXX is the below really right? if isinstance(node, StructTypeNode): - fields = str([getattr(node.struct, name) for name in node.struct._names_without_voids()]) - if '*' not in fields: + fields = [getattr(node.struct, name) + for name in node.struct._names_without_voids()] + fields = [x for x in fields if isinstance(x, lltype.Ptr)] + if not fields: return True #non-pointers only return False #contains pointer(s) elif isinstance(node, ArrayTypeNode): - return False #because they actually are arrays of pointers + return not isinstance(node.array.OF, lltype.Ptr) log("unknown type %s, assuming non-atomic" % str(type(node))) return False From hpk at codespeak.net Tue Jul 5 15:03:16 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 15:03:16 +0200 (CEST) Subject: [pypy-svn] r14286 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705130316.028E127B3F@code1.codespeak.net> Author: hpk Date: Tue Jul 5 15:03:13 2005 New Revision: 14286 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/node.py Log: (hpk, rxe) slight refactoring of representing refs in llvm source Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Tue Jul 5 15:03:13 2005 @@ -6,10 +6,7 @@ import itertools log = log.structnode -count = itertools.count().next - -def wrapstr(s): - return '"%s"' % s +nextnum = itertools.count().next class ArrayTypeNode(LLVMNode): _issetup = False @@ -17,11 +14,16 @@ self.db = db assert isinstance(array, lltype.Array) self.array = array - c = count() - ref_template = wrapstr("%%array.%s." + str(c)) + c = nextnum() + ref_template = "%%array.%s." + str(c) + # ref is used to reference the arraytype in llvm source self.ref = ref_template % array.OF - self.constructor_ref = wrapstr("%%new.array.%s" % c) + # constructor_ref is used to reference the constructor + # for the array type in llvm source code + self.constructor_ref = "%%new.array.%s" % c + # constructor_decl is used to declare the constructor + # for the array type (see writeimpl). self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -72,8 +74,7 @@ def writedatatypedecl(self, codewriter): codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) -# Each ArrayNode is a global constant. This needs to have a specific type of -# a certain type. +# Each ArrayNode instance is a global constant. class ArrayNode(LLVMNode): @@ -82,7 +83,8 @@ def __init__(self, db, value): self.db = db - name = '"%%arrayinstance.%s.%s"' % (value._TYPE.OF, ArrayNode.array_counter) + name = '"%%arrayinstance.%s.%s"' % ( + value._TYPE.OF, ArrayNode.array_counter) self.ref = name self.value = value ArrayNode.array_counter += 1 Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Tue Jul 5 15:03:13 2005 @@ -1,12 +1,30 @@ class LLVMNode(object): - def _get_ref(self): - return self._ref - def _set_ref(self, ref): - if hasattr(self, "_ref"): - raise TypeError, ("can only set ref once! currently: %s" % - (self._ref,)) - self._ref = ref - ref = property(_get_ref, _set_ref) + + def ref(): + def _get_ref(self): + return self._ref + def _set_ref(self, ref): + if hasattr(self, "_ref"): + raise TypeError, ("can only set ref once! currently: %s" % + (self._ref,)) + if " " in ref: + ref = '"%s"' % (ref,) + self._ref = ref + return property(_get_ref, _set_ref) + ref = ref() + + def constructor_ref(): + def _get_ref(self): + return self._constructor_ref + def _set_ref(self, ref): + if hasattr(self, "_constructor_ref"): + raise TypeError, ("can only set constructor_ref once!" + " currently: %s" % (self._constructor_ref,)) + if " " in ref: + ref = '"%s"' % (ref,) + self._constructor_ref = ref + return property(_get_ref, _set_ref) + constructor_ref = constructor_ref() # __________________ before "implementation" ____________________ def writedatatypedecl(self, codewriter): From cfbolz at codespeak.net Tue Jul 5 15:30:27 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Jul 2005 15:30:27 +0200 (CEST) Subject: [pypy-svn] r14287 - pypy/dist/pypy/objspace/std Message-ID: <20050705133027.04DFB27B3F@code1.codespeak.net> Author: cfbolz Date: Tue Jul 5 15:30:25 2005 New Revision: 14287 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: found one error (and changed a docstring). doesn't fix the failing test, though. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 15:30:25 2005 @@ -846,7 +846,7 @@ # so a = b*z + r. if a.sign != b.sign: z.sign = - z.sign - if z.sign < 0 and rem.sign != 0: + if a.sign < 0 and rem.sign != 0: rem.sign = - rem.sign return z, rem @@ -966,15 +966,15 @@ """ The / and % operators are now defined in terms of divmod(). The expression a mod b has the value a - b*floor(a/b). - The long_divrem function gives the remainder after division of + The _divrem function gives the remainder after division of |a| by |b|, with the sign of a. This is also expressed as a - b*trunc(a/b), if trunc truncates towards zero. Some examples: - a b a rem b a mod b - 13 10 3 3 - -13 10 -3 7 - 13 -10 3 -7 - -13 -10 -3 -3 + a b a rem b a mod b + 13 10 3 3 + -13 10 -3 7 + 13 -10 3 -7 + -13 -10 -3 -3 So, to get from rem to mod, we have to add b if a and b have different signs. We then subtract one from the 'div' part of the outcome to keep the invariant intact. From hpk at codespeak.net Tue Jul 5 15:38:51 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 15:38:51 +0200 (CEST) Subject: [pypy-svn] r14288 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050705133851.72E7D27B3F@code1.codespeak.net> Author: hpk Date: Tue Jul 5 15:38:49 2005 New Revision: 14288 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (rxe, hpk) - refactoring the array constructor to also serve for constructring varsize arrays - clean up little bits and pieces Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Tue Jul 5 15:38:49 2005 @@ -3,6 +3,7 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode from pypy.objspace.flow.model import Constant +from pypy.translator.llvm2 import varsize import itertools log = log.structnode @@ -35,34 +36,11 @@ codewriter.declare(self.constructor_decl) def writeimpl(self, codewriter): - """ this function generates a LLVM function like the following: - %array = type { int, [0 x double] } - %array *%NewArray(int %len) { - ;; Get the offset of the 'len' element of the array from the null - ;; pointer. - %size = getelementptr %array* null, int 0, uint 1, %int %len - %usize = cast double* %size to uint - %ptr = malloc sbyte, uint %usize - %result = cast sbyte* %ptr to %array* - %arraylength = getelementptr %array* %result, int 0, uint 0 - store int %len, int* %arraylength - ret %array* %result - }""" - from pypy.translator.llvm2.atomic import is_atomic - log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_decl) - indices = [("uint", 1), ("int", "%len")] - codewriter.getelementptr("%size", self.ref + "*", - "null", *indices) fromtype = self.db.repr_arg_type(self.array.OF) - codewriter.cast("%usize", fromtype + "*", "%size", "uint") - codewriter.malloc("%ptr", "sbyte", "%usize", atomic=is_atomic(self)) - codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") - codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) - codewriter.store("int", "%len", "%arraylength") - codewriter.ret(self.ref+"*", "%result") - codewriter.closefunc() + varsize.write_constructor(codewriter, self.ref, + self.constructor_decl, + fromtype) def setup(self): self.db.prepare_repr_arg_type(self.array.OF) @@ -79,15 +57,11 @@ class ArrayNode(LLVMNode): _issetup = False - array_counter = 0 def __init__(self, db, value): self.db = db - name = '"%%arrayinstance.%s.%s"' % ( - value._TYPE.OF, ArrayNode.array_counter) - self.ref = name + self.ref = "%%arrayinstance.%s.%s" % (value._TYPE.OF, nextnum()) self.value = value - ArrayNode.array_counter += 1 def __str__(self): return "" %(self.ref,) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Tue Jul 5 15:38:49 2005 @@ -7,19 +7,16 @@ from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log +nextnum = py.std.itertools.count().next log = log.funcnode class FuncTypeNode(LLVMNode): - func_type_node_counter = 0 - def __init__(self, db, type_): self.db = db assert isinstance(type_, lltype.FuncType) self.type_ = type_ - ref = '"ft.%s.%s"' % (type_, FuncTypeNode.func_type_node_counter) - self.ref = ref.replace(" ", "") - FuncTypeNode.func_type_node_counter += 1 + self.ref = 'ft.%s.%s' % (type_, nextnum()) def __str__(self): return "" % self.ref @@ -260,7 +257,7 @@ targetvar = self.db.repr_arg(op.result) arg_type = op.args[0] assert (isinstance(arg_type, Constant) and - isinstance(arg_type.value, lltype.Array)) + isinstance(arg_type.value, (lltype.Array, lltype.Struct))) #XXX unclean struct_type = self.db.obj2node[arg_type.value].ref struct_cons = self.db.obj2node[arg_type.value].constructor_ref Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Tue Jul 5 15:38:49 2005 @@ -41,7 +41,13 @@ def __init__(self, db, struct): super(StructVarsizeTypeNode, self).__init__(db, struct) new_var_name = "%%new.st.var.%s" % self.name - self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + self.constructor_ref = "%s * %s(int %%len)" % (self.ref, new_var_name) + + ref_template = wrapstr("%%st.%s." + str(c)) + self.ref = ref_template % array.OF + self.constructor_ref = wrapstr("%%new.array.%s" % c) + self.constructor_decl = "%s * %s(int %%len)" % \ + (self.ref, self.constructor_ref) def __str__(self): return "" %(self.ref,) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 15:38:49 2005 @@ -314,6 +314,12 @@ for j in range(6): assert f(i,j) == list_basic_ops(i,j) +def xtest_string_simple(): + def string_simple(i): + return str(i) + f = compile_function(string_simple, [int], view=False) + assert f(0) + def Xtest_string_getitem1(): l = "Hello, World" def string_getitem1(i): From hpk at codespeak.net Tue Jul 5 15:42:29 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 15:42:29 +0200 (CEST) Subject: [pypy-svn] r14289 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705134229.268D327B3F@code1.codespeak.net> Author: hpk Date: Tue Jul 5 15:42:25 2005 New Revision: 14289 Added: pypy/dist/pypy/translator/llvm2/varsize.py (contents, props changed) Log: (hpk/rxe) missing file from previous checkin r14288 Added: pypy/dist/pypy/translator/llvm2/varsize.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/varsize.py Tue Jul 5 15:42:25 2005 @@ -0,0 +1,40 @@ + +# example for an array constructor in concrete llvm code: +# (thanks to chris lattner) +""" this function generates a LLVM function like the following: +%array = type { int, [0 x double] } +%array *%NewArray(int %len) { + ;; Get the offset of the 'len' element of the array from the null + ;; pointer. + %size = getelementptr %array* null, int 0, uint 1, %int %len + %usize = cast double* %size to uint + %ptr = malloc sbyte, uint %usize + %result = cast sbyte* %ptr to %array* + %arraylength = getelementptr %array* %result, int 0, uint 0 + store int %len, int* %arraylength + ret %array* %result +}""" + +def write_constructor(codewriter, ref, constructor_decl, elemtype, + indices_to_array=(), atomicmalloc=False): + #varsized arrays and structs look like this: + #Array: {int length , elemtype*} + #Struct: {...., Array} + + # the following indices access the last element in the array + elemindices = list(indices_to_array) + [("uint", 1), ("int", "%len")] + + codewriter.openfunc(constructor_decl) + codewriter.getelementptr("%size", ref + "*", "null", *elemindices) + codewriter.cast("%usize", elemtype + "*", "%size", "uint") + codewriter.malloc("%ptr", "sbyte", "%usize", atomic=atomicmalloc) + codewriter.cast("%result", "sbyte*", "%ptr", ref + "*") + + # the following accesses the length field of the array + codewriter.getelementptr("%arraylength", ref + "*", + "%result", + indices_to_array + ("uint", 0)) + codewriter.store("int", "%len", "%arraylength") + codewriter.ret(ref + "*", "%result") + codewriter.closefunc() + From rxe at codespeak.net Tue Jul 5 15:53:47 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 5 Jul 2005 15:53:47 +0200 (CEST) Subject: [pypy-svn] r14290 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705135347.A1B9627B3F@code1.codespeak.net> Author: rxe Date: Tue Jul 5 15:53:46 2005 New Revision: 14290 Modified: pypy/dist/pypy/translator/llvm2/structnode.py Log: Minor refactors / clean ups. Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Tue Jul 5 15:53:46 2005 @@ -4,19 +4,20 @@ from pypy.translator.llvm2.node import LLVMNode from pypy.rpython import lltype +import itertools +nextnum = itertools.count().next + log = log.structnode class StructTypeNode(LLVMNode): _issetup = False - struct_counter = 0 def __init__(self, db, struct): assert isinstance(struct, lltype.Struct) self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name, StructTypeNode.struct_counter) + self.name = "%s.%s" % (self.struct._name, nextnum()) self.ref = "%%st.%s" % self.name - StructTypeNode.struct_counter += 1 def __str__(self): return "" %(self.ref,) @@ -40,12 +41,7 @@ def __init__(self, db, struct): super(StructVarsizeTypeNode, self).__init__(db, struct) - new_var_name = "%%new.st.var.%s" % self.name - self.constructor_ref = "%s * %s(int %%len)" % (self.ref, new_var_name) - - ref_template = wrapstr("%%st.%s." + str(c)) - self.ref = ref_template % array.OF - self.constructor_ref = wrapstr("%%new.array.%s" % c) + self.constructor_ref = "%%new.st.var.%s" % (self.name) self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -54,13 +50,13 @@ def writedecl(self, codewriter): # declaration for constructor - codewriter.declare(self.constructor_name) + codewriter.declare(self.constructor_decl) def writeimpl(self, codewriter): from pypy.translator.llvm2.atomic import is_atomic log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_name) + codewriter.openfunc(self.constructor_ref) codewriter.label("block0") indices_to_array = [("int", 0)] s = self.struct @@ -102,14 +98,11 @@ class StructNode(LLVMNode): _issetup = False - struct_counter = 0 def __init__(self, db, value): self.db = db - name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) - self.ref = "%%stinstance.%s" % name self.value = value - StructNode.struct_counter += 1 + self.ref = "%%stinstance.%s.%s" % (value._TYPE._name, nextnum()) def __str__(self): return "" %(self.ref,) From rxe at codespeak.net Tue Jul 5 15:56:42 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 5 Jul 2005 15:56:42 +0200 (CEST) Subject: [pypy-svn] r14291 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705135642.9823127B3F@code1.codespeak.net> Author: rxe Date: Tue Jul 5 15:56:41 2005 New Revision: 14291 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py Log: Reordering of methods so comment makes sense. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Tue Jul 5 15:56:41 2005 @@ -31,6 +31,16 @@ def __str__(self): return "" % self.ref + def setup(self): + self.db.prepare_repr_arg_type(self.array.OF) + self._issetup = True + + # ______________________________________________________________________ + # entry points from genllvm + # + def writedatatypedecl(self, codewriter): + codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) + def writedecl(self, codewriter): # declaration for constructor codewriter.declare(self.constructor_decl) @@ -42,16 +52,6 @@ self.constructor_decl, fromtype) - def setup(self): - self.db.prepare_repr_arg_type(self.array.OF) - self._issetup = True - - # ______________________________________________________________________ - # entry points from genllvm - # - def writedatatypedecl(self, codewriter): - codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) - # Each ArrayNode instance is a global constant. class ArrayNode(LLVMNode): From quest at codespeak.net Tue Jul 5 16:06:05 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Tue, 5 Jul 2005 16:06:05 +0200 (CEST) Subject: [pypy-svn] r14292 - pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test Message-ID: <20050705140605.054FD27B3F@code1.codespeak.net> Author: quest Date: Tue Jul 5 16:06:04 2005 New Revision: 14292 Added: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_urllib2.py - copied, changed from r14161, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllib2.py Log: Removed test that triggers complaint about raising ambiguous exception. Copied: pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_urllib2.py (from r14161, pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllib2.py) ============================================================================== --- pypy/branch/dist-2.4.1/lib-python/2.4.1/test/test_urllib2.py (original) +++ pypy/branch/dist-2.4.1/lib-python/modified-2.4.1/test/test_urllib2.py Tue Jul 5 16:06:04 2005 @@ -476,7 +476,10 @@ # check socket.error converted to URLError http.raise_on_endheaders = True - self.assertRaises(urllib2.URLError, h.do_open, http, req) + + # The raising of socket.error is not recognized as an + # exception by pypy, so this test fails + # self.assertRaises(urllib2.URLError, h.do_open, http, req) # check adding of standard headers o.addheaders = [("Spam", "eggs")] From hpk at codespeak.net Tue Jul 5 16:30:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 16:30:58 +0200 (CEST) Subject: [pypy-svn] r14294 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050705143058.D160827B3F@code1.codespeak.net> Author: hpk Date: Tue Jul 5 16:30:51 2005 New Revision: 14294 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py pypy/dist/pypy/translator/llvm2/varsize.py Log: (hpk, rxe) moving and refactoring towards varsize structs it still doesn't work quite yet. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Tue Jul 5 16:30:51 2005 @@ -152,6 +152,10 @@ def repr_arg(self, arg): if (isinstance(arg, Constant) and isinstance(arg.concretetype, lltype.Primitive)): + + # XXX generalize and test this + if isinstance(arg.value, str) and len(arg.value) == 1: + return str(ord(arg.value)) return str(arg.value).lower() #False --> false elif isinstance(arg, Variable): return "%" + str(arg) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Tue Jul 5 16:30:51 2005 @@ -194,6 +194,15 @@ assert meth is not None, "operation %r not found" %(op.opname,) meth(op) + def int_neg(self, op): + self.codewriter.binaryop("sub", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + "0", + self.db.repr_arg(op.args[0]), + ) + + def binaryop(self, op): name = self.binary_operations[op.opname] assert len(op.args) == 2 @@ -213,6 +222,7 @@ cast_bool_to_int = cast_primitive cast_bool_to_uint = uint_is_true = cast_primitive + cast_int_to_char = cast_char_to_int = cast_primitive def int_is_true(self, op): self.codewriter.binaryop("setne", @@ -324,6 +334,7 @@ valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) + assert valuevar.strip() != '-' self.codewriter.store(valuetype, valuevar, tmpvar) def getarraysize(self, op): Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Tue Jul 5 16:30:51 2005 @@ -2,6 +2,7 @@ from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2 import varsize from pypy.rpython import lltype import itertools @@ -56,38 +57,19 @@ from pypy.translator.llvm2.atomic import is_atomic log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_ref) - codewriter.label("block0") + + # build up a list of indices to get to the last + # var-sized struct (or rather the according array) indices_to_array = [("int", 0)] s = self.struct while isinstance(s, lltype.Struct): last_pos = len(s._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) s = s._flds[s._names_without_voids()[-1]] - arraytype = self.db.repr_arg_type(s) - - # Into array and length - indices = indices_to_array + [("uint", 1), ("int", "%len")] - codewriter.getelementptr("%size", self.ref + "*", - "null", *indices) - - #XXX is this ok for 64bit? - codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=is_atomic(self)) - codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") - - # remember the allocated length for later use. - indices = indices_to_array + [("uint", 0)] - codewriter.getelementptr("%size_ptr", self.ref + "*", - "%result", *indices) - - codewriter.cast("%signedsize", "uint", "%sizeu", "int") - codewriter.store("int", "%signedsize", "%size_ptr") - - codewriter.ret(self.ref + "*", "%result") - codewriter.closefunc() - + varsize.write_constructor(codewriter, + self.ref, self.constructor_decl, arraytype, + indices_to_array) def cast_global(toptr, from_, name): s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 16:30:51 2005 @@ -12,7 +12,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rarithmetic import r_uint -py.log.setconsumer("genllvm", py.log.STDOUT) +#py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) @@ -316,7 +316,7 @@ def xtest_string_simple(): def string_simple(i): - return str(i) + return ord(str(i)) f = compile_function(string_simple, [int], view=False) assert f(0) Modified: pypy/dist/pypy/translator/llvm2/varsize.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/varsize.py (original) +++ pypy/dist/pypy/translator/llvm2/varsize.py Tue Jul 5 16:30:51 2005 @@ -29,11 +29,12 @@ codewriter.cast("%usize", elemtype + "*", "%size", "uint") codewriter.malloc("%ptr", "sbyte", "%usize", atomic=atomicmalloc) codewriter.cast("%result", "sbyte*", "%ptr", ref + "*") - + + indices_to_array = tuple(indices_to_array) + (("uint", 0),) # the following accesses the length field of the array codewriter.getelementptr("%arraylength", ref + "*", "%result", - indices_to_array + ("uint", 0)) + *indices_to_array) codewriter.store("int", "%len", "%arraylength") codewriter.ret(ref + "*", "%result") codewriter.closefunc() From pedronis at codespeak.net Tue Jul 5 17:07:03 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 17:07:03 +0200 (CEST) Subject: [pypy-svn] r14297 - in pypy/dist/pypy/rpython: . test Message-ID: <20050705150703.8C1AD27B3F@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 17:06:59 2005 New Revision: 14297 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: implemented rtyping support for external functions with a testing-only ll_function that cannot be annotated. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Tue Jul 5 17:06:59 2005 @@ -24,12 +24,16 @@ table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable) # low-level helpers representing the external functions +def ll_os_open(fname, mode): + return os.open(''.join(fname.chars), mode) + def ll_os_getuid(): - return 1 #return os.getuid() + return os.getuid() def ll_os_dup(fd): return 999 # external function declarations -declare(os.getuid, int, ll_os_getuid, ll_annotable=True) +declare(os.open, int, ll_os_open, ll_annotable=False) +declare(os.getuid, int, ll_os_getuid, ll_annotable=False) declare(os.dup, int, ll_os_dup, ll_annotable=True) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Jul 5 17:06:59 2005 @@ -169,7 +169,11 @@ if hasattr(f._obj, 'graph'): graph = f._obj.graph else: - graph = self.llinterpreter.getgraph(f._obj._callable) + try: + graph = self.llinterpreter.getgraph(f._obj._callable) + except KeyError: + assert hasattr(f._obj, '_callable'), "don't know how to execute %r" % f + return f._obj._callable(*args) frame = self.__class__(graph, args, self.llinterpreter) return frame.eval() Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 5 17:06:59 2005 @@ -248,9 +248,15 @@ ll_function = extfuncinfo.ll_function if extfuncinfo.ll_annotable: def rtype_extfunc(hop): - return hop.gendirectcall(ll_function, *hop.args_v) + vars = hop.inputargs(*hop.args_r) + return hop.gendirectcall(ll_function, *vars) else: - assert False, "xxx not implemented" + def rtype_extfunc(hop): + resulttype = hop.r_result + vars = hop.inputargs(*hop.args_r) + return hop.llops.genexternalcall(ll_function.__name__, vars, resulttype=resulttype, + _callable = ll_function) + return sourcetools.func_with_new_name(rtype_extfunc, "rtype_extfunc_%s" % extfuncinfo.func.__name__) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 5 17:06:59 2005 @@ -521,15 +521,17 @@ return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) - def gencapicall(self, cfnname, args_v, resulttype=None, **flags): + def genexternalcall(self, fnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) - f = functionptr(FUNCTYPE, cfnname, external="C", **flags) + f = functionptr(FUNCTYPE, fnname, **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype) + def gencapicall(self, cfnname, args_v, resulttype=None, **flags): + return genexternalcall(cfname, args_v, resulttype=resulttype, external="C") # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 5 17:06:59 2005 @@ -1,6 +1,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test import test_llinterp from pypy.objspace.flow import model as flowmodel +from pypy.tool import udir from pypy.annotation.builtin import * import py @@ -63,12 +64,24 @@ ry = 100 * float(i-10) +0.1 assert fn(rv,ry) == interpret(fn, (rv, ry)) -def DONOT_test_os_getuid(): +def enum_direct_calls(translator, func): + blocks = [] + graph = translator.getflowgraph(func) + def visit(block): + if isinstance(block, flowmodel.Block): + blocks.append(block) + flowmodel.traverse(visit, graph) + for block in blocks: + for op in block.operations: + if op.opname == 'direct_call': + yield op + +def test_os_getuid(): import os def fn(): return os.getuid() assert interpret(fn, []) == fn() - + def test_os_dup(): import os def fn(fd): @@ -78,20 +91,31 @@ # os.close(res) #except OSError: # pass - t = test_llinterp.typer.annotator.translator - graph = t.getflowgraph(fn) - count = [0] - def visit(block): - from pypy.rpython import extfunctable - if isinstance(block, flowmodel.Block): - for op in block.operations: - if op.opname == 'direct_call': - cfptr = op.args[0] - assert cfptr.value._obj._callable == extfunctable.ll_os_dup - count[0] += 1 - flowmodel.traverse(visit, graph) - assert count[0] == 1 + count = 0 + from pypy.rpython import extfunctable + for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn): + cfptr = dir_call.args[0] + assert cfptr.value._obj._callable == extfunctable.ll_os_dup + count += 1 + assert count == 1 +def test_os_open(): + tmpdir = str(udir.udir.join("os_open_test")) + import os + def wr_open(fname): + return os.open(fname, os.O_WRONLY|os.O_CREAT) + def f(): + return wr_open(tmpdir) + res = interpret(f, []) + os.close(res) + count = 0 + from pypy.rpython import extfunctable + for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, wr_open): + cfptr = dir_call.args[0] + assert cfptr.value._obj._callable == extfunctable.ll_os_open + count += 1 + assert count == 1 + def test_pbc_isTrue(): class C: def f(self): From hpk at codespeak.net Tue Jul 5 17:38:48 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 17:38:48 +0200 (CEST) Subject: [pypy-svn] r14298 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050705153848.291AA27B40@code1.codespeak.net> Author: hpk Date: Tue Jul 5 17:38:46 2005 New Revision: 14298 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py pypy/dist/pypy/translator/llvm2/varsize.py Log: (rxe, hpk) made a first string test pass! it turned out that getsubstruct and getfield were doing wrong things. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Tue Jul 5 17:38:46 2005 @@ -4,7 +4,7 @@ from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.codewriter -show_line_numbers = True +show_line_numbers = False # True count = count().next class CodeWriter(object): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Tue Jul 5 17:38:46 2005 @@ -129,6 +129,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: + codewriter.comment(str(op)) opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) @@ -286,14 +287,19 @@ targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" - if isinstance(op.result.concretetype, lltype.ContainerType): - # noop - self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - else: - self.codewriter.load(targetvar, targettype, tmpvar) - - getsubstruct = getfield + self.codewriter.load(targetvar, targettype, tmpvar) + def getsubstruct(self, op): + typ = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + targetvar = self.db.repr_arg(op.result) + self.codewriter.getelementptr(targetvar, typ, + typevar, ("uint", index)) + targettype = self.db.repr_arg_type(op.result) + assert targettype != "void" + def setfield(self, op): tmpvar = self.db.repr_tmpvar() type = self.db.repr_arg_type(op.args[0]) @@ -316,11 +322,7 @@ ("uint", 1), (indextype, index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - if isinstance(op.result.concretetype, lltype.ContainerType): - # noop - self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - else: - self.codewriter.load(targetvar, targettype, tmpvar) + self.codewriter.load(targetvar, targettype, tmpvar) def setarrayitem(self, op): array = self.db.repr_arg(op.args[0]) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Tue Jul 5 17:38:46 2005 @@ -60,13 +60,16 @@ # build up a list of indices to get to the last # var-sized struct (or rather the according array) - indices_to_array = [("int", 0)] - s = self.struct - while isinstance(s, lltype.Struct): - last_pos = len(s._names_without_voids()) - 1 + indices_to_array = [] + current = self.struct + while isinstance(current, lltype.Struct): + last_pos = len(current._names_without_voids()) - 1 indices_to_array.append(("uint", last_pos)) - s = s._flds[s._names_without_voids()[-1]] - arraytype = self.db.repr_arg_type(s) + name = current._names_without_voids()[-1] + current = current._flds[name] + assert isinstance(current, lltype.Array) + arraytype = self.db.repr_arg_type(current.OF) + # XXX write type info as a comment varsize.write_constructor(codewriter, self.ref, self.constructor_decl, arraytype, indices_to_array) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 17:38:46 2005 @@ -314,7 +314,7 @@ for j in range(6): assert f(i,j) == list_basic_ops(i,j) -def xtest_string_simple(): +def test_string_simple(): def string_simple(i): return ord(str(i)) f = compile_function(string_simple, [int], view=False) Modified: pypy/dist/pypy/translator/llvm2/varsize.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/varsize.py (original) +++ pypy/dist/pypy/translator/llvm2/varsize.py Tue Jul 5 17:38:46 2005 @@ -23,7 +23,7 @@ # the following indices access the last element in the array elemindices = list(indices_to_array) + [("uint", 1), ("int", "%len")] - + codewriter.openfunc(constructor_decl) codewriter.getelementptr("%size", ref + "*", "null", *elemindices) codewriter.cast("%usize", elemtype + "*", "%size", "uint") From pedronis at codespeak.net Tue Jul 5 17:44:24 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 17:44:24 +0200 (CEST) Subject: [pypy-svn] r14299 - pypy/dist/pypy/rpython Message-ID: <20050705154424.CDBC827B45@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 17:44:24 2005 New Revision: 14299 Modified: pypy/dist/pypy/rpython/rtyper.py Log: oops Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 5 17:44:24 2005 @@ -531,7 +531,7 @@ return self.genop('direct_call', [cf]+list(args_v), resulttype) def gencapicall(self, cfnname, args_v, resulttype=None, **flags): - return genexternalcall(cfname, args_v, resulttype=resulttype, external="C") + return self.genexternalcall(cfnname, args_v, resulttype=resulttype, external="C") # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations From pedronis at codespeak.net Tue Jul 5 18:23:06 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 18:23:06 +0200 (CEST) Subject: [pypy-svn] r14300 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050705162306.C544527B42@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 18:23:04 2005 New Revision: 14300 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_database.py Log: start of code to have types with fixed names preserved through the backend Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jul 5 18:23:04 2005 @@ -23,8 +23,8 @@ # chars: array of Char # } -STR = GcStruct('str', ('hash', Signed), - ('chars', Array(Char))) +STR = GcStruct('rpy_string', ('hash', Signed), + ('chars', Array(Char))) SIGNED_ARRAY = GcArray(Signed) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 5 18:23:04 2005 @@ -50,6 +50,7 @@ r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r self.exceptiondata = ExceptionData(self) + self.fixednames = self.fixednames.copy() def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -542,3 +543,6 @@ from pypy.rpython import rlist, rstr, rtuple, rdict from pypy.rpython import rclass, rbuiltin, rpbc from pypy.rpython import rptr + +RPythonTyper.fixednames = {} +RPythonTyper.fixednames[rstr.STR] = True Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue Jul 5 18:23:04 2005 @@ -21,6 +21,16 @@ self.containernodes = {} self.containerlist = [] self.namespace = CNameManager() + if translator is not None and translator.rtyper is not None: + rtyper = translator.rtyper + for lltype, nameorflag in rtyper.fixednames.iteritems(): + if nameorflag is True: + self.namespace.make_reserved_names(lltype._name) + #else: + # self.namespace.make_reserved_names(nameorflag) + self.fixednames = rtyper.fixednames + else: + self.fixednames = {} self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) def gettypedefnode(self, T, varlength=1): Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Jul 5 18:23:04 2005 @@ -38,7 +38,10 @@ else: basename = db.gettypedefnode(STRUCT).name basename = '%s_len%d' % (basename, varlength) - self.name = db.namespace.uniquename(basename) + if STRUCT in db.fixednames: + self.name = basename + else: + self.name = db.namespace.uniquename(basename) self.dependencies = {} self.fields = [] self.prefix = somelettersfrom(STRUCT._name) + '_' Modified: pypy/dist/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_database.py (original) +++ pypy/dist/pypy/translator/c/test/test_database.py Tue Jul 5 18:23:04 2005 @@ -196,6 +196,23 @@ db.complete() dump_on_stdout(db) +def test_fixedname(): + def f(): + return "foo" + t = Translator(f) + t.annotate([]) + t.specialize() + + db = LowLevelDatabase(t) + S = GcStruct('rpy_string', ('x', Signed)) + s = malloc(S) + s.x = 42 + db.get(s) + Sname = db.gettype(S) + db.get(pyobjectptr(f)) + from pypy.rpython import rstr + assert db.gettype(rstr.STR) == "struct rpy_string @" + assert Sname != "struct rpy_string @" def test_malloc(): S = GcStruct('testing', ('x', Signed), ('y', Signed)) From pedronis at codespeak.net Tue Jul 5 18:30:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 5 Jul 2005 18:30:07 +0200 (CEST) Subject: [pypy-svn] r14301 - in pypy/dist/pypy/rpython: . test Message-ID: <20050705163007.541B327B42@code1.codespeak.net> Author: pedronis Date: Tue Jul 5 18:30:06 2005 New Revision: 14301 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: limit ourself to just testing with os.getcwd wich should exist on Windows too. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Tue Jul 5 18:30:06 2005 @@ -27,13 +27,18 @@ def ll_os_open(fname, mode): return os.open(''.join(fname.chars), mode) -def ll_os_getuid(): - return os.getuid() +def ll_os_getcwd(): + cwd = os.getcwd() + from pypy.rpython import rstr + p = rstr.malloc(rstr.STR, len(cwd)) + for i in range(len(cwd)): + p.chars[i] = cwd[i] + return p def ll_os_dup(fd): return 999 # external function declarations declare(os.open, int, ll_os_open, ll_annotable=False) -declare(os.getuid, int, ll_os_getuid, ll_annotable=False) +declare(os.getcwd, str, ll_os_getcwd, ll_annotable=False) declare(os.dup, int, ll_os_dup, ll_annotable=True) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 5 18:30:06 2005 @@ -76,11 +76,12 @@ if op.opname == 'direct_call': yield op -def test_os_getuid(): +def test_os_getcwd(): import os def fn(): - return os.getuid() - assert interpret(fn, []) == fn() + return os.getcwd() + res = interpret(fn, []) + assert ''.join(res.chars) == fn() def test_os_dup(): import os From rxe at codespeak.net Tue Jul 5 18:41:16 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 5 Jul 2005 18:41:16 +0200 (CEST) Subject: [pypy-svn] r14302 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705164116.83BC527B42@code1.codespeak.net> Author: rxe Date: Tue Jul 5 18:41:15 2005 New Revision: 14302 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py Log: Some braindead refactoring of array module. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Tue Jul 5 18:41:15 2005 @@ -12,19 +12,19 @@ class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): - self.db = db assert isinstance(array, lltype.Array) + + self.db = db self.array = array - c = nextnum() - ref_template = "%%array.%s." + str(c) # ref is used to reference the arraytype in llvm source - self.ref = ref_template % array.OF # constructor_ref is used to reference the constructor # for the array type in llvm source code - self.constructor_ref = "%%new.array.%s" % c # constructor_decl is used to declare the constructor - # for the array type (see writeimpl). + # for the array type (see writeimpl) + c = nextnum() + self.ref = "%%array.%s.%s" % (c, array.OF) + self.constructor_ref = "%%new.array.%s" % c self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -52,58 +52,54 @@ self.constructor_decl, fromtype) -# Each ArrayNode instance is a global constant. - class ArrayNode(LLVMNode): - _issetup = False - def __init__(self, db, value): self.db = db - self.ref = "%%arrayinstance.%s.%s" % (value._TYPE.OF, nextnum()) self.value = value + self.arraytype = value._TYPE.OF + self.ref = "%%arrayinstance.%s.%s" % (value._TYPE.OF, nextnum()) def __str__(self): return "" %(self.ref,) def setup(self): - T = self.value._TYPE.OF for item in self.value.items: - if not isinstance(T, lltype.Primitive): + if not isinstance(self.arraytype, lltype.Primitive): # Create a dummy constant hack XXX - c = Constant(item, T) - self.db.prepare_arg(c) + self.db.prepare_arg(Constant(item, self.arraytype)) self._issetup = True + def value_helper(self, value): + """ This should really be pushed back to the database??? XXX """ + if not isinstance(self.arraytype, lltype.Primitive): + # Create a dummy constant hack XXX + value = self.db.repr_arg(Constant(value, self.arraytype)) + else: + if isinstance(value, str) and len(value) == 1: + value = ord(value) + value = str(value) + return value + def getall(self): - "Returns the type and value for this node. " - arraylen = len(self.value.items) - - res = [] - - T = self.value._TYPE.OF - typval = self.db.repr_arg_type(self.value._TYPE.OF) - for value in self.value.items: - if not isinstance(T, lltype.Primitive): - # Create a dummy constant hack XXX - value = self.db.repr_arg(Constant(value, T)) - else: - if isinstance(value, str): - value = ord(value) - - value = str(value) - res.append((typval, value)) + """ Returns the type and value for this node. """ + items = self.value.items + typeval = self.db.repr_arg_type(self.arraytype) + arraylen = len(items) + + type_ = "{ int, [%s x %s] }" % (arraylen, typeval) + arrayvalues = ["%s %s" % (typeval, + self.value_helper(v)) for v in items] - type_ = "{ int, [%s x %s] }" % (arraylen, - self.db.repr_arg_type(self.value._TYPE.OF)) - - arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, - typval, - arrayvalues) + typeval, + ", ".join(arrayvalues)) return type_, value + # ______________________________________________________________________ + # entry points from genllvm + def writeglobalconstants(self, codewriter): type_, values = self.getall() codewriter.globalinstance(self.ref, type_, values) From tismer at codespeak.net Tue Jul 5 19:30:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 19:30:56 +0200 (CEST) Subject: [pypy-svn] r14304 - pypy/dist/pypy/objspace/std Message-ID: <20050705173056.E51C527B42@code1.codespeak.net> Author: tismer Date: Tue Jul 5 19:30:56 2005 New Revision: 14304 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: waaaah! fixed a very hard to detect bug, which occours when we are using all bits of a two digits word. The C source does not say this explicitly, but uses a weird expression that only works if a basic type can hold a sign plus two digits. Implemented this with r_suint. too bad, this took many hours to deduce. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 19:30:56 2005 @@ -9,7 +9,7 @@ import math SHORT_BIT = int(LONG_BIT // 2) -SHORT_MASK = int(LONG_MASK >> SHORT_BIT) +SHORT_MASK = int((1 << SHORT_BIT) - 1) SIGN_BIT = LONG_BIT-1 SIGN_MASK = r_uint(1) << SIGN_BIT @@ -63,7 +63,8 @@ def _setshort(self, index, short): a = self.digits[index // 2] - assert isinstance(short, r_uint) + ##!!assert isinstance(short, r_uint) + assert short & SHORT_MASK == short if index % 2 == 0: self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short else: @@ -727,6 +728,15 @@ res >>= n return res + def __ilshift__(self, n): + self.value <<= n + return self + + def __lshift__(self, n): + res = r_suint(self) + res <<= n + return res + def __and__(self, mask): # only used to get bits from the value return self.value & mask @@ -736,7 +746,7 @@ other = r_suint(other) return self.sign == other.sign and self.value == other.value -def _x_divrem(space, v1, w1): # return as tuple, PyLongObject **prem) +def _x_divrem(space, v1, w1): size_w = len(w1.digits) * 2 # hack for the moment: # find where w1 is really nonzero @@ -756,8 +766,10 @@ size_a = size_v - size_w + 1 digitpairs = (size_a + 1) // 2 a = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + j = size_v - for k in range(size_a-1, -1, -1): + k = size_a - 1 + while k >= 0: if j >= size_v: vj = r_uint(0) else: @@ -769,18 +781,20 @@ else: q = ((vj << SHORT_BIT) + v._getshort(j-1)) // w._getshort(size_w-1) + # notabene! + # this check needs a signed two digits result + # or we get an overflow. while (w._getshort(size_w-2) * q > (( - (vj << SHORT_BIT) + r_suint(vj << SHORT_BIT) # this one dominates + v._getshort(j-1) - q * w._getshort(size_w-1) ) << SHORT_BIT) + v._getshort(j-2)): q -= 1 - for i in range(size_w): - if i+k >= size_v: - break + i = 0 + while i < size_w and i+k < size_v: z = w._getshort(i) * q zz = z >> SHORT_BIT carry += v._getshort(i+k) + (zz << SHORT_BIT) @@ -788,8 +802,8 @@ v._setshort(i+k, r_uint(carry.value & SHORT_MASK)) carry >>= SHORT_BIT carry -= zz + i += 1 - i += 1 # compare C code which re-uses i of loop if i+k < size_v: carry += v._getshort(i+k) v._setshort(i+k, r_uint(0)) @@ -797,18 +811,18 @@ if carry == 0: a._setshort(k, q) else: - #assert carry == -1 - # the above would hold if we didn't minimize size_w + assert carry == -1 a._setshort(k, q-1) - carry = r_suint(0) - for i in range(size_w): - if i+k >= size_v: - break + carry = r_suint(0) + i = 0 + while i < size_w and i+k < size_v: carry += v._getshort(i+k) + w._getshort(i) - v._setshort(i+k, r_uint(carry) & SHORT_MASK) + v._setshort(i+k, r_uint(carry.value) & SHORT_MASK) carry >>= SHORT_BIT + i += 1 j -= 1 + k -= 1 a._normalize() rem, _ = _divrem1(space, v, d) From ac at codespeak.net Tue Jul 5 20:06:01 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 5 Jul 2005 20:06:01 +0200 (CEST) Subject: [pypy-svn] r14305 - pypy/branch/dist-2.4.1/pypy/interpreter/pyparser Message-ID: <20050705180601.B95E527B40@code1.codespeak.net> Author: ac Date: Tue Jul 5 20:06:01 2005 New Revision: 14305 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Log: Do not loop infinitely when encountering unknown characters. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 20:06:01 2005 @@ -2,7 +2,7 @@ it obeys the TokenSource interface defined for the grammar analyser in grammar.py """ -import symbol +import symbol, sys from pypy.interpreter.pyparser.grammar import TokenSource, Token # Don't import string for that ... @@ -203,9 +203,14 @@ start = pos end = pseudomatch + if start == end: + # Nothing matched!!! + raise TokenError("EOF in multi-line statement", line, + (lnum, pos), token_list) + + spos, epos, pos = (lnum, start), (lnum, end), end token, initial = line[start:end], line[start] - if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number tok = token_from_values(tokenmod.NUMBER, token) @@ -291,7 +296,6 @@ ## tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) - return token_list, encoding class PythonSource(TokenSource): From arigo at codespeak.net Tue Jul 5 20:10:34 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 20:10:34 +0200 (CEST) Subject: [pypy-svn] r14306 - pypy/branch/dist-2.4.1/pypy/interpreter/pyparser Message-ID: <20050705181034.415AB27B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 20:10:33 2005 New Revision: 14306 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Log: Fixing the error message. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 20:10:33 2005 @@ -205,9 +205,8 @@ if start == end: # Nothing matched!!! - raise TokenError("EOF in multi-line statement", line, - (lnum, pos), token_list) - + raise TokenError("Unknown character", line, + (lnum, start), token_list) spos, epos, pos = (lnum, start), (lnum, end), end token, initial = line[start:end], line[start] From arigo at codespeak.net Tue Jul 5 20:13:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 20:13:27 +0200 (CEST) Subject: [pypy-svn] r14307 - in pypy/branch/dist-2.4.1/pypy: annotation interpreter interpreter/pyparser module/recparser objspace/std objspace/std/test rpython rpython/test translator/c translator/c/test translator/llvm2 translator/llvm2/test Message-ID: <20050705181327.83B0227B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 20:13:26 2005 New Revision: 14307 Added: pypy/branch/dist-2.4.1/pypy/rpython/extfunctable.py - copied unchanged from r14306, pypy/dist/pypy/rpython/extfunctable.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/varsize.py - copied unchanged from r14306, pypy/dist/pypy/translator/llvm2/varsize.py Modified: pypy/branch/dist-2.4.1/pypy/annotation/bookkeeper.py pypy/branch/dist-2.4.1/pypy/annotation/builtin.py pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py pypy/branch/dist-2.4.1/pypy/objspace/std/intobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py pypy/branch/dist-2.4.1/pypy/rpython/llinterp.py pypy/branch/dist-2.4.1/pypy/rpython/rbuiltin.py pypy/branch/dist-2.4.1/pypy/rpython/rmodel.py pypy/branch/dist-2.4.1/pypy/rpython/rstr.py pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rbuiltin.py pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py pypy/branch/dist-2.4.1/pypy/translator/c/database.py pypy/branch/dist-2.4.1/pypy/translator/c/node.py pypy/branch/dist-2.4.1/pypy/translator/c/test/test_database.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/atomic.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/node.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Log: svn merge -r14266:14306 http://codespeak.net/svn/pypy/dist Modified: pypy/branch/dist-2.4.1/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/annotation/bookkeeper.py (original) +++ pypy/branch/dist-2.4.1/pypy/annotation/bookkeeper.py Tue Jul 5 20:13:26 2005 @@ -627,7 +627,7 @@ raise Exception, "no __init__ found in %r" % (cls,) return s_instance - assert isinstance(func, FunctionType), "[%s] expected function, got %r" % (self.whereami(), func) + assert isinstance(func, FunctionType), "[%s] expected user-defined function, got %r" % (self.whereami(), func) inputcells = self.get_inputcells(func, args) Modified: pypy/branch/dist-2.4.1/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/annotation/builtin.py (original) +++ pypy/branch/dist-2.4.1/pypy/annotation/builtin.py Tue Jul 5 20:13:26 2005 @@ -67,9 +67,8 @@ return constpropagate(bool, [s_obj], SomeBool()) def builtin_int(s_obj, s_base=None): - assert (s_base is None or s_base.is_constant() - and s_base.const == 16 - and s_obj.knowntype == str), "only int(v|string) or int(string,16) expected" + assert (s_base is None or isinstance(s_base, SomeInteger) + and s_obj.knowntype == str), "only int(v|string) or int(string,int) expected" if s_base is not None: args_s = [s_obj, s_base] else: @@ -336,3 +335,9 @@ BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info +from pypy.rpython import extfunctable + +# import annotation information for external functions +# from the extfunctable.table into our own annotation specific table +for func, extfuncinfo in extfunctable.table.iteritems(): + BUILTIN_ANALYZERS[func] = extfuncinfo.annotation Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py Tue Jul 5 20:13:26 2005 @@ -171,6 +171,7 @@ BINARY_TRUE_DIVIDE = binaryoperation("truediv") BINARY_FLOOR_DIVIDE = binaryoperation("floordiv") BINARY_DIVIDE = binaryoperation("div") + # XXX BINARY_DIVIDE must fall back to BINARY_TRUE_DIVIDE with -Qnew BINARY_MODULO = binaryoperation("mod") BINARY_ADD = binaryoperation("add") BINARY_SUBTRACT = binaryoperation("sub") @@ -191,6 +192,7 @@ INPLACE_TRUE_DIVIDE = binaryoperation("inplace_truediv") INPLACE_FLOOR_DIVIDE = binaryoperation("inplace_floordiv") INPLACE_DIVIDE = binaryoperation("inplace_div") + # XXX INPLACE_DIVIDE must fall back to INPLACE_TRUE_DIVIDE with -Qnew INPLACE_MODULO = binaryoperation("inplace_mod") INPLACE_ADD = binaryoperation("inplace_add") INPLACE_SUBTRACT = binaryoperation("inplace_sub") Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py Tue Jul 5 20:13:26 2005 @@ -1,5 +1,4 @@ -__all__ = ["python_parse", "pypy_parse", "ast_single_input", "ast_file_input", - "ast_eval_input"] +__all__ = ["python_parse", "pypy_parse"] import parser import symbol Modified: pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py Tue Jul 5 20:13:26 2005 @@ -8,7 +8,6 @@ from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import SyntaxNode -from pypy.interpreter.pyparser.pythonparse import parse_python_source from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -101,16 +100,14 @@ def suite( space, source ): # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - builder = parse_python_source( strings, PYTHON_PARSER, "file_input" ) + builder = PYTHON_PARSER.parse_source( source, "file_input" ) return space.wrap( STType(space, builder.stack[-1]) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): # make the annotator life easier (don't use str.splitlines()) - strings = [line + '\n' for line in source.split('\n')] - builder = parse_python_source( strings, PYTHON_PARSER, "eval_input" ) + builder = PYTHON_PARSER.parse_source( source, "eval_input" ) return space.wrap( STType(space, builder.stack[-1]) ) expr.unwrap_spec = [ObjSpace, str] Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/intobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/intobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/intobject.py Tue Jul 5 20:13:26 2005 @@ -209,13 +209,8 @@ m = x % y return space.wrap((z,m)) -old_style_div = 1 / 2 == 1 // 2 def div__Int_Int(space, w_int1, w_int2): - # Select the proper div - if old_style_div: - return _floordiv(space, w_int1, w_int2) - else: - return _truediv(space, w_int1, w_int2) + return _floordiv(space, w_int1, w_int2) floordiv__Int_Int = _floordiv truediv__Int_Int = _truediv Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py Tue Jul 5 20:13:26 2005 @@ -9,7 +9,7 @@ import math SHORT_BIT = int(LONG_BIT // 2) -SHORT_MASK = int(LONG_MASK >> SHORT_BIT) +SHORT_MASK = int((1 << SHORT_BIT) - 1) SIGN_BIT = LONG_BIT-1 SIGN_MASK = r_uint(1) << SIGN_BIT @@ -63,7 +63,8 @@ def _setshort(self, index, short): a = self.digits[index // 2] - assert isinstance(short, r_uint) + ##!!assert isinstance(short, r_uint) + assert short & SHORT_MASK == short if index % 2 == 0: self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short else: @@ -258,25 +259,19 @@ return space.newfloat(div) def floordiv__Long_Long(space, w_long1, w_long2): - div, rem = _divrem(space, w_long1, w_long2) + div, mod = _l_divmod(space, w_long1, w_long2) return div -old_style_div = 1 / 2 == 1 // 2 def div__Long_Long(space, w_long1, w_long2): - # Select the proper div - if old_style_div: - return floordiv__Long_Long(space, w_long1, w_long2) - else: - return truediv__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, rem = _divrem(space, w_long1, w_long2) - return rem + div, mod = _l_divmod(space, w_long1, w_long2) + return mod def divmod__Long_Long(space, w_long1, w_long2): - div, rem = _divrem(space, w_long1, w_long2) - return space.newtuple([div, rem]) + div, mod = _l_divmod(space, w_long1, w_long2) + return space.newtuple([div, mod]) # helper for pow() #YYYYYY: still needs longval if second argument is negative def _impl_long_long_pow(space, lv, lw, lz=None): @@ -733,6 +728,15 @@ res >>= n return res + def __ilshift__(self, n): + self.value <<= n + return self + + def __lshift__(self, n): + res = r_suint(self) + res <<= n + return res + def __and__(self, mask): # only used to get bits from the value return self.value & mask @@ -742,7 +746,7 @@ other = r_suint(other) return self.sign == other.sign and self.value == other.value -def _x_divrem(space, v1, w1): # return as tuple, PyLongObject **prem) +def _x_divrem(space, v1, w1): size_w = len(w1.digits) * 2 # hack for the moment: # find where w1 is really nonzero @@ -762,8 +766,10 @@ size_a = size_v - size_w + 1 digitpairs = (size_a + 1) // 2 a = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + j = size_v - for k in range(size_a-1, -1, -1): + k = size_a - 1 + while k >= 0: if j >= size_v: vj = r_uint(0) else: @@ -775,18 +781,20 @@ else: q = ((vj << SHORT_BIT) + v._getshort(j-1)) // w._getshort(size_w-1) + # notabene! + # this check needs a signed two digits result + # or we get an overflow. while (w._getshort(size_w-2) * q > (( - (vj << SHORT_BIT) + r_suint(vj << SHORT_BIT) # this one dominates + v._getshort(j-1) - q * w._getshort(size_w-1) ) << SHORT_BIT) + v._getshort(j-2)): q -= 1 - for i in range(size_w): - if i+k >= size_v: - break + i = 0 + while i < size_w and i+k < size_v: z = w._getshort(i) * q zz = z >> SHORT_BIT carry += v._getshort(i+k) + (zz << SHORT_BIT) @@ -794,8 +802,8 @@ v._setshort(i+k, r_uint(carry.value & SHORT_MASK)) carry >>= SHORT_BIT carry -= zz + i += 1 - i += 1 # compare C code which re-uses i of loop if i+k < size_v: carry += v._getshort(i+k) v._setshort(i+k, r_uint(0)) @@ -803,18 +811,18 @@ if carry == 0: a._setshort(k, q) else: - #assert carry == -1 - # the above would hold if we didn't minimize size_w + assert carry == -1 a._setshort(k, q-1) - carry = r_suint(0) - for i in range(size_w): - if i+k >= size_v: - break + carry = r_suint(0) + i = 0 + while i < size_w and i+k < size_v: carry += v._getshort(i+k) + w._getshort(i) - v._setshort(i+k, r_uint(carry) & SHORT_MASK) + v._setshort(i+k, r_uint(carry.value) & SHORT_MASK) carry >>= SHORT_BIT + i += 1 j -= 1 + k -= 1 a._normalize() rem, _ = _divrem1(space, v, d) @@ -830,9 +838,9 @@ if b._getshort(size_b-1) == 0: size_b -= 1 - if size_b == 0: - raise OperationError(w_longobj.space.w_ZeroDivisionError, - w_longobj.space.wrap("long division or modulo by zero")) + if b.sign == 0: + raise OperationError(space.w_ZeroDivisionError, + space.wrap("long division or modulo by zero")) if (size_a < size_b or (size_a == size_b and @@ -852,7 +860,7 @@ # so a = b*z + r. if a.sign != b.sign: z.sign = - z.sign - if z.sign < 0 and rem.sign != 0: + if a.sign < 0 and rem.sign != 0: rem.sign = - rem.sign return z, rem @@ -891,29 +899,31 @@ assert x > 0.0 return x * sign, exponent -# XXX make ldexp and isinf a builtin float support function - def isinf(x): - return x*2 == x + return x != 0.0 and x / 2 == x + +##def ldexp(x, exp): +## assert type(x) is float +## lb1 = LONG_BIT - 1 +## multiplier = float(r_uint(1) << lb1) +## while exp >= lb1: +## x *= multiplier +## exp -= lb1 +## if exp: +## x *= float(r_uint(1) << exp) +## return x -def ldexp(x, exp): - assert type(x) is float - lb1 = LONG_BIT - 1 - multiplier = float(r_uint(1) << lb1) - while exp >= lb1: - x *= multiplier - exp -= lb1 - if exp: - x *= float(r_uint(1) << exp) - return x +# note that math.ldexp checks for overflows, +# while the C ldexp is not guaranteed to. def _AsDouble(v): """ Get a C double from a long int object. """ x, e = _AsScaledDouble(v) if e <= sys.maxint / SHORT_BIT: - x = ldexp(x, e * SHORT_BIT) - if not isinf(x): - return x + x = math.ldexp(x, e * SHORT_BIT) + #if not isinf(x): + # this is checked by math.ldexp + return x raise OverflowError# sorry, "long int too large to convert to float" def _long_true_divide(space, a, b): @@ -931,10 +941,61 @@ raise OverflowError elif aexp < -(sys.maxint / SHORT_BIT): return 0.0 # underflow to 0 - ad = ldexp(ad, aexp * SHORT_BIT) - if isinf(ad): # ignore underflow to 0.0 - raise OverflowError + ad = math.ldexp(ad, aexp * SHORT_BIT) + #if isinf(ad): # ignore underflow to 0.0 + # raise OverflowError + # math.ldexp checks and raises return ad except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("long/long too large for a float")) + + +def _FromDouble(space, dval): + """ Create a new long int object from a C double """ + neg = 0 + if isinf(dval): + raise OperationError(space.w_OverflowError, + space.wrap("cannot convert float infinity to long")) + if dval < 0.0: + neg = 1 + dval = -dval + frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 + if expo <= 0: + return W_LongObject(space, [r_uint(0)], 0) + ndig = (expo-1) // SHORT_BIT + 1 # Number of 'digits' in result + digitpairs = (ndig + 1) // 2 + v = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + frac = math.ldexp(frac, (expo-1) % SHORT_BIT + 1) + for i in range(ndig-1, -1, -1): + bits = int(frac) + v._setshort(i, r_uint(bits)) + frac -= float(bits) + frac = math.ldexp(frac, SHORT_BIT) + if neg: + v.sign = -1 + return v + +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). + The _divrem function gives the remainder after division of + |a| by |b|, with the sign of a. This is also expressed + as a - b*trunc(a/b), if trunc truncates towards zero. + Some examples: + a b a rem b a mod b + 13 10 3 3 + -13 10 -3 7 + 13 -10 3 -7 + -13 -10 -3 -3 + So, to get from rem to mod, we have to add b if a and b + have different signs. We then subtract one from the 'div' + part of the outcome to keep the invariant intact. + """ + div, mod = _divrem(space, v, w) + if mod.sign * w.sign == -1: + mod = add__Long_Long(space, mod, w) + one = W_LongObject(space, [r_uint(1)], 1) + div = sub__Long_Long(space, div, one) + return div, mod Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py Tue Jul 5 20:13:26 2005 @@ -4,6 +4,7 @@ from pypy.objspace.std import longobject as lobj from pypy.objspace.std.objspace import FailedToImplement from pypy.rpython.rarithmetic import r_uint +from pypy.interpreter.error import OperationError objspacename = 'std' @@ -112,6 +113,18 @@ f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) assert raises(OverflowError, lobj._AsDouble, f1) + def test__FromDouble(self): + x = 1234567890.1234567890 + f1 = lobj._FromDouble(self.space, x) + y = lobj._AsDouble(f1) + assert f1.longval() == long(x) + # check overflow + x = 12345.6789e10000000000000000000000000000 + try: + lobj._FromDouble(self.space, x) + except OperationError, e: + assert e.w_type is self.space.w_OverflowError + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L @@ -289,3 +302,21 @@ def test_getnewargs(self): assert 0L .__getnewargs__() == (0L,) assert (-1L) .__getnewargs__() == (-1L,) + + def test_divmod(self): + def check_division(x, y): + q, r = divmod(x, y) + pab, pba = x*y, y*x + assert pab == pba + assert q == x//y + assert r == x%y + assert x == q*y + r + if y > 0: + assert 0 <= r < y + else: + assert y < r <= 0 + for x in [-1L, 0L, 1L, 2L ** 100 - 1, -2L ** 100 - 1]: + for y in [-105566530L, -1L, 1L, 1034522340L]: + print "checking division for %s, %s" % (x, y) + check_division(x, y) + raises(ZeroDivisionError, "x // 0L") Modified: pypy/branch/dist-2.4.1/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/llinterp.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/llinterp.py Tue Jul 5 20:13:26 2005 @@ -169,7 +169,11 @@ if hasattr(f._obj, 'graph'): graph = f._obj.graph else: - graph = self.llinterpreter.getgraph(f._obj._callable) + try: + graph = self.llinterpreter.getgraph(f._obj._callable) + except KeyError: + assert hasattr(f._obj, '_callable'), "don't know how to execute %r" % f + return f._obj._callable(*args) frame = self.__class__(graph, args, self.llinterpreter) return frame.eval() Modified: pypy/branch/dist-2.4.1/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rbuiltin.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rbuiltin.py Tue Jul 5 20:13:26 2005 @@ -9,7 +9,7 @@ from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr, FloatRepr from pypy.rpython import rclass - +from pypy.tool import sourcetools class __extend__(annmodel.SomeBuiltin): def rtyper_makerepr(self, rtyper): @@ -87,7 +87,8 @@ def rtype_builtin_int(hop): if isinstance(hop.args_s[0], annmodel.SomeString): - raise TyperError('int("string") not supported') + assert 1 <= hop.nb_args <= 2 + return hop.args_r[0].rtype_int(hop) assert hop.nb_args == 1 return hop.args_r[0].rtype_int(hop) @@ -240,3 +241,27 @@ includes=("math.h",)) # XXX clean up needed BUILTIN_TYPER[math.exp] = rtype_math_exp + +from pypy.rpython import extfunctable + +def make_rtype_extfunc(extfuncinfo): + ll_function = extfuncinfo.ll_function + if extfuncinfo.ll_annotable: + def rtype_extfunc(hop): + vars = hop.inputargs(*hop.args_r) + return hop.gendirectcall(ll_function, *vars) + else: + def rtype_extfunc(hop): + resulttype = hop.r_result + vars = hop.inputargs(*hop.args_r) + return hop.llops.genexternalcall(ll_function.__name__, vars, resulttype=resulttype, + _callable = ll_function) + + return sourcetools.func_with_new_name(rtype_extfunc, + "rtype_extfunc_%s" % extfuncinfo.func.__name__) + +# import rtyping information for external functions +# from the extfunctable.table into our own specific table +for func, extfuncinfo in extfunctable.table.iteritems(): + BUILTIN_TYPER[func] = make_rtype_extfunc(extfuncinfo) + Modified: pypy/branch/dist-2.4.1/pypy/rpython/rmodel.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rmodel.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rmodel.py Tue Jul 5 20:13:26 2005 @@ -226,11 +226,13 @@ def getconcretetype(v): return getattr(v, 'concretetype', PyObjPtr) -def getfunctionptr(translator, func, getconcretetype=getconcretetype): +def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype, _callable=None): """Make a functionptr from the given Python function.""" - graph = translator.getflowgraph(func) + graph = translator.getflowgraph(graphfunc) llinputs = [getconcretetype(v) for v in graph.getargs()] lloutput = getconcretetype(graph.getreturnvar()) FT = FuncType(llinputs, lloutput) - return functionptr(FT, func.func_name, graph = graph, _callable = func) + if _callable is None: + _callable = graphfunc + return functionptr(FT, graphfunc.func_name, graph = graph, _callable = _callable) Modified: pypy/branch/dist-2.4.1/pypy/rpython/rstr.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rstr.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rstr.py Tue Jul 5 20:13:26 2005 @@ -23,8 +23,8 @@ # chars: array of Char # } -STR = GcStruct('str', ('hash', Signed), - ('chars', Array(Char))) +STR = GcStruct('rpy_string', ('hash', Signed), + ('chars', Array(Char))) SIGNED_ARRAY = GcArray(Signed) @@ -142,6 +142,16 @@ v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr) return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2) + def rtype_int(_, hop): + if hop.nb_args == 1: + v_str, = hop.inputargs(string_repr) + c_base = inputconst(Signed, 10) + return hop.gendirectcall(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) + return hop.gendirectcall(ll_int, v_str, v_base) + def ll_str(s, r): if typeOf(s) == Char: return ll_chr2str(s) @@ -768,6 +778,47 @@ 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 + # ____________________________________________________________ # # Iteration. Modified: pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/rtyper.py Tue Jul 5 20:13:26 2005 @@ -50,6 +50,7 @@ r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r self.exceptiondata = ExceptionData(self) + self.fixednames = self.fixednames.copy() def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -355,10 +356,10 @@ # __________ utilities __________ - def getfunctionptr(self, func): + def getfunctionptr(self, graphfunc, _callable=None): def getconcretetype(v): return self.bindingrepr(v).lowleveltype - return getfunctionptr(self.annotator.translator, func, getconcretetype) + return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype, _callable=_callable) def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): self.call_all_setups() # compute ForwardReferences now @@ -516,20 +517,22 @@ dontcare, spec_function = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s) # build the 'direct_call' operation - f = self.rtyper.getfunctionptr(spec_function) + f = self.rtyper.getfunctionptr(spec_function, _callable=ll_function) c = inputconst(typeOf(f), f) return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) - def gencapicall(self, cfnname, args_v, resulttype=None, **flags): + def genexternalcall(self, fnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) - f = functionptr(FUNCTYPE, cfnname, external="C", **flags) + f = functionptr(FUNCTYPE, fnname, **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype) + def gencapicall(self, cfnname, args_v, resulttype=None, **flags): + return self.genexternalcall(cfnname, args_v, resulttype=resulttype, external="C") # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations @@ -540,3 +543,6 @@ from pypy.rpython import rlist, rstr, rtuple, rdict from pypy.rpython import rclass, rbuiltin, rpbc from pypy.rpython import rptr + +RPythonTyper.fixednames = {} +RPythonTyper.fixednames[rstr.STR] = True Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rbuiltin.py Tue Jul 5 20:13:26 2005 @@ -1,4 +1,7 @@ from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test import test_llinterp +from pypy.objspace.flow import model as flowmodel +from pypy.tool import udir from pypy.annotation.builtin import * import py @@ -61,6 +64,59 @@ ry = 100 * float(i-10) +0.1 assert fn(rv,ry) == interpret(fn, (rv, ry)) +def enum_direct_calls(translator, func): + blocks = [] + graph = translator.getflowgraph(func) + def visit(block): + if isinstance(block, flowmodel.Block): + blocks.append(block) + flowmodel.traverse(visit, graph) + for block in blocks: + for op in block.operations: + if op.opname == 'direct_call': + yield op + +def test_os_getcwd(): + import os + def fn(): + return os.getcwd() + res = interpret(fn, []) + assert ''.join(res.chars) == fn() + +def test_os_dup(): + import os + def fn(fd): + return os.dup(fd) + res = interpret(fn, [0]) + #try: + # os.close(res) + #except OSError: + # pass + count = 0 + from pypy.rpython import extfunctable + for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn): + cfptr = dir_call.args[0] + assert cfptr.value._obj._callable == extfunctable.ll_os_dup + count += 1 + assert count == 1 + +def test_os_open(): + tmpdir = str(udir.udir.join("os_open_test")) + import os + def wr_open(fname): + return os.open(fname, os.O_WRONLY|os.O_CREAT) + def f(): + return wr_open(tmpdir) + res = interpret(f, []) + os.close(res) + count = 0 + from pypy.rpython import extfunctable + for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, wr_open): + cfptr = dir_call.args[0] + assert cfptr.value._obj._callable == extfunctable.ll_os_open + count += 1 + assert count == 1 + def test_pbc_isTrue(): class C: def f(self): Modified: pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py (original) +++ pypy/branch/dist-2.4.1/pypy/rpython/test/test_rstr.py Tue Jul 5 20:13:26 2005 @@ -2,8 +2,8 @@ from pypy.rpython.lltype import * from pypy.rpython.rstr import parse_fmt_string from pypy.rpython.rtyper import RPythonTyper, TyperError -from pypy.rpython.test.test_llinterp import interpret - +from pypy.rpython.test.test_llinterp import interpret,find_exception +from pypy.rpython.llinterp import LLException def test_simple(): def fn(i): @@ -356,3 +356,20 @@ 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', ''] + 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: + info = raises(LLException, interpret, fn, [i, j]) + assert find_exception(info.value) is ValueError + else: + res = interpret(fn, [i, j]) + assert res == expected Modified: pypy/branch/dist-2.4.1/pypy/translator/c/database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/c/database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/c/database.py Tue Jul 5 20:13:26 2005 @@ -21,6 +21,16 @@ self.containernodes = {} self.containerlist = [] self.namespace = CNameManager() + if translator is not None and translator.rtyper is not None: + rtyper = translator.rtyper + for lltype, nameorflag in rtyper.fixednames.iteritems(): + if nameorflag is True: + self.namespace.make_reserved_names(lltype._name) + #else: + # self.namespace.make_reserved_names(nameorflag) + self.fixednames = rtyper.fixednames + else: + self.fixednames = {} self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) def gettypedefnode(self, T, varlength=1): Modified: pypy/branch/dist-2.4.1/pypy/translator/c/node.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/c/node.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/c/node.py Tue Jul 5 20:13:26 2005 @@ -38,7 +38,10 @@ else: basename = db.gettypedefnode(STRUCT).name basename = '%s_len%d' % (basename, varlength) - self.name = db.namespace.uniquename(basename) + if STRUCT in db.fixednames: + self.name = basename + else: + self.name = db.namespace.uniquename(basename) self.dependencies = {} self.fields = [] self.prefix = somelettersfrom(STRUCT._name) + '_' Modified: pypy/branch/dist-2.4.1/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/c/test/test_database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/c/test/test_database.py Tue Jul 5 20:13:26 2005 @@ -196,6 +196,23 @@ db.complete() dump_on_stdout(db) +def test_fixedname(): + def f(): + return "foo" + t = Translator(f) + t.annotate([]) + t.specialize() + + db = LowLevelDatabase(t) + S = GcStruct('rpy_string', ('x', Signed)) + s = malloc(S) + s.x = 42 + db.get(s) + Sname = db.gettype(S) + db.get(pyobjectptr(f)) + from pypy.rpython import rstr + assert db.gettype(rstr.STR) == "struct rpy_string @" + assert Sname != "struct rpy_string @" def test_malloc(): S = GcStruct('testing', ('x', Signed), ('y', Signed)) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/arraynode.py Tue Jul 5 20:13:26 2005 @@ -3,65 +3,34 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode from pypy.objspace.flow.model import Constant +from pypy.translator.llvm2 import varsize import itertools log = log.structnode -count = itertools.count().next - -def wrapstr(s): - return '"%s"' % s +nextnum = itertools.count().next class ArrayTypeNode(LLVMNode): _issetup = False def __init__(self, db, array): - self.db = db assert isinstance(array, lltype.Array) + + self.db = db self.array = array - c = count() - ref_template = wrapstr("%%array.%s." + str(c)) - self.ref = ref_template % array.OF - self.constructor_ref = wrapstr("%%new.array.%s" % c) + # ref is used to reference the arraytype in llvm source + # constructor_ref is used to reference the constructor + # for the array type in llvm source code + # constructor_decl is used to declare the constructor + # for the array type (see writeimpl) + c = nextnum() + self.ref = "%%array.%s.%s" % (c, array.OF) + self.constructor_ref = "%%new.array.%s" % c self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) def __str__(self): return "" % self.ref - def writedecl(self, codewriter): - # declaration for constructor - codewriter.declare(self.constructor_decl) - - def writeimpl(self, codewriter): - """ this function generates a LLVM function like the following: - %array = type { int, [0 x double] } - %array *%NewArray(int %len) { - ;; Get the offset of the 'len' element of the array from the null - ;; pointer. - %size = getelementptr %array* null, int 0, uint 1, %int %len - %usize = cast double* %size to uint - %ptr = malloc sbyte, uint %usize - %result = cast sbyte* %ptr to %array* - %arraylength = getelementptr %array* %result, int 0, uint 0 - store int %len, int* %arraylength - ret %array* %result - }""" - from pypy.translator.llvm2.atomic import is_atomic - - log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_decl) - indices = [("uint", 1), ("int", "%len")] - codewriter.getelementptr("%size", self.ref + "*", - "null", *indices) - fromtype = self.db.repr_arg_type(self.array.OF) - codewriter.cast("%usize", fromtype + "*", "%size", "uint") - codewriter.malloc("%ptr", "sbyte", "%usize", atomic=is_atomic(self)) - codewriter.cast("%result", "sbyte*", "%ptr", self.ref+"*") - codewriter.getelementptr("%arraylength", self.ref+"*", "%result", ("uint", 0)) - codewriter.store("int", "%len", "%arraylength") - codewriter.ret(self.ref+"*", "%result") - codewriter.closefunc() - def setup(self): self.db.prepare_repr_arg_type(self.array.OF) self._issetup = True @@ -72,60 +41,65 @@ def writedatatypedecl(self, codewriter): codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) -# Each ArrayNode is a global constant. This needs to have a specific type of -# a certain type. + def writedecl(self, codewriter): + # declaration for constructor + codewriter.declare(self.constructor_decl) + + def writeimpl(self, codewriter): + log.writeimpl(self.ref) + fromtype = self.db.repr_arg_type(self.array.OF) + varsize.write_constructor(codewriter, self.ref, + self.constructor_decl, + fromtype) class ArrayNode(LLVMNode): - _issetup = False - array_counter = 0 - def __init__(self, db, value): self.db = db - name = '"%%arrayinstance.%s.%s"' % (value._TYPE.OF, ArrayNode.array_counter) - self.ref = name self.value = value - ArrayNode.array_counter += 1 + self.arraytype = value._TYPE.OF + self.ref = "%%arrayinstance.%s.%s" % (value._TYPE.OF, nextnum()) def __str__(self): return "" %(self.ref,) def setup(self): - T = self.value._TYPE.OF for item in self.value.items: - if not isinstance(T, lltype.Primitive): + if not isinstance(self.arraytype, lltype.Primitive): # Create a dummy constant hack XXX - c = Constant(item, T) - self.db.prepare_arg(c) - + self.db.prepare_arg(Constant(item, self.arraytype)) self._issetup = True + def value_helper(self, value): + """ This should really be pushed back to the database??? XXX """ + if not isinstance(self.arraytype, lltype.Primitive): + # Create a dummy constant hack XXX + value = self.db.repr_arg(Constant(value, self.arraytype)) + else: + if isinstance(value, str) and len(value) == 1: + value = ord(value) + value = str(value) + return value + def getall(self): - arraylen = len(self.value.items) + """ Returns the type and value for this node. """ + items = self.value.items + typeval = self.db.repr_arg_type(self.arraytype) + arraylen = len(items) + + type_ = "{ int, [%s x %s] }" % (arraylen, typeval) + arrayvalues = ["%s %s" % (typeval, + self.value_helper(v)) for v in items] - res = [] - - T = self.value._TYPE.OF - typval = self.db.repr_arg_type(self.value._TYPE.OF) - for value in self.value.items: - if not isinstance(T, lltype.Primitive): - # Create a dummy constant hack XXX - value = self.db.repr_arg(Constant(value, T)) - else: - value = repr(value) - res.append((typval, value)) - - arrayvalues = ", ".join(["%s %s" % (t, v) for t, v in res]) - - type_ = "{ int, [%s x %s] }" % (len(self.value.items), - self.db.repr_arg_type(self.value._TYPE.OF)) - value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, - typval, - arrayvalues) + typeval, + ", ".join(arrayvalues)) return type_, value + # ______________________________________________________________________ + # entry points from genllvm + def writeglobalconstants(self, codewriter): type_, values = self.getall() codewriter.globalinstance(self.ref, type_, values) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/atomic.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/atomic.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/atomic.py Tue Jul 5 20:13:26 2005 @@ -1,16 +1,20 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.structnode import StructTypeNode from pypy.translator.llvm2.arraynode import ArrayTypeNode +from pypy.rpython import lltype log = log.atomic def is_atomic(node): + # XXX is the below really right? if isinstance(node, StructTypeNode): - fields = str([getattr(node.struct, name) for name in node.struct._names_without_voids()]) - if '*' not in fields: + fields = [getattr(node.struct, name) + for name in node.struct._names_without_voids()] + fields = [x for x in fields if isinstance(x, lltype.Ptr)] + if not fields: return True #non-pointers only return False #contains pointer(s) elif isinstance(node, ArrayTypeNode): - return False #because they actually are arrays of pointers + return not isinstance(node.array.OF, lltype.Ptr) log("unknown type %s, assuming non-atomic" % str(type(node))) return False Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/codewriter.py Tue Jul 5 20:13:26 2005 @@ -4,7 +4,7 @@ from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.codewriter -show_line_numbers = True +show_line_numbers = False # True count = count().next class CodeWriter(object): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py Tue Jul 5 20:13:26 2005 @@ -84,7 +84,6 @@ if isinstance(ct, lltype.Struct): if ct._arrayfld: - assert False, "HERE" self.addpending(const_or_var, StructVarsizeNode(self, value)) else: self.addpending(const_or_var, StructNode(self, value)) @@ -153,6 +152,10 @@ def repr_arg(self, arg): if (isinstance(arg, Constant) and isinstance(arg.concretetype, lltype.Primitive)): + + # XXX generalize and test this + if isinstance(arg.value, str) and len(arg.value) == 1: + return str(ord(arg.value)) return str(arg.value).lower() #False --> false elif isinstance(arg, Variable): return "%" + str(arg) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py Tue Jul 5 20:13:26 2005 @@ -7,19 +7,16 @@ from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log +nextnum = py.std.itertools.count().next log = log.funcnode class FuncTypeNode(LLVMNode): - func_type_node_counter = 0 - def __init__(self, db, type_): self.db = db assert isinstance(type_, lltype.FuncType) self.type_ = type_ - ref = '"ft.%s.%s"' % (type_, FuncTypeNode.func_type_node_counter) - self.ref = ref.replace(" ", "") - FuncTypeNode.func_type_node_counter += 1 + self.ref = 'ft.%s.%s' % (type_, nextnum()) def __str__(self): return "" % self.ref @@ -132,6 +129,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: + codewriter.comment(str(op)) opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) @@ -197,6 +195,15 @@ assert meth is not None, "operation %r not found" %(op.opname,) meth(op) + def int_neg(self, op): + self.codewriter.binaryop("sub", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + "0", + self.db.repr_arg(op.args[0]), + ) + + def binaryop(self, op): name = self.binary_operations[op.opname] assert len(op.args) == 2 @@ -216,6 +223,7 @@ cast_bool_to_int = cast_primitive cast_bool_to_uint = uint_is_true = cast_primitive + cast_int_to_char = cast_char_to_int = cast_primitive def int_is_true(self, op): self.codewriter.binaryop("setne", @@ -260,7 +268,7 @@ targetvar = self.db.repr_arg(op.result) arg_type = op.args[0] assert (isinstance(arg_type, Constant) and - isinstance(arg_type.value, lltype.Array)) + isinstance(arg_type.value, (lltype.Array, lltype.Struct))) #XXX unclean struct_type = self.db.obj2node[arg_type.value].ref struct_cons = self.db.obj2node[arg_type.value].constructor_ref @@ -279,14 +287,19 @@ targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" - if isinstance(op.result.concretetype, lltype.ContainerType): - # noop - self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - else: - self.codewriter.load(targetvar, targettype, tmpvar) - - getsubstruct = getfield + self.codewriter.load(targetvar, targettype, tmpvar) + def getsubstruct(self, op): + typ = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + targetvar = self.db.repr_arg(op.result) + self.codewriter.getelementptr(targetvar, typ, + typevar, ("uint", index)) + targettype = self.db.repr_arg_type(op.result) + assert targettype != "void" + def setfield(self, op): tmpvar = self.db.repr_tmpvar() type = self.db.repr_arg_type(op.args[0]) @@ -309,11 +322,7 @@ ("uint", 1), (indextype, index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - if isinstance(op.result.concretetype, lltype.ContainerType): - # noop - self.codewriter.cast(targetvar, targettype, tmpvar, targettype) - else: - self.codewriter.load(targetvar, targettype, tmpvar) + self.codewriter.load(targetvar, targettype, tmpvar) def setarrayitem(self, op): array = self.db.repr_arg(op.args[0]) @@ -327,6 +336,7 @@ valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) + assert valuevar.strip() != '-' self.codewriter.store(valuetype, valuevar, tmpvar) def getarraysize(self, op): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/node.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/node.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/node.py Tue Jul 5 20:13:26 2005 @@ -1,12 +1,30 @@ class LLVMNode(object): - def _get_ref(self): - return self._ref - def _set_ref(self, ref): - if hasattr(self, "_ref"): - raise TypeError, ("can only set ref once! currently: %s" % - (self._ref,)) - self._ref = ref - ref = property(_get_ref, _set_ref) + + def ref(): + def _get_ref(self): + return self._ref + def _set_ref(self, ref): + if hasattr(self, "_ref"): + raise TypeError, ("can only set ref once! currently: %s" % + (self._ref,)) + if " " in ref: + ref = '"%s"' % (ref,) + self._ref = ref + return property(_get_ref, _set_ref) + ref = ref() + + def constructor_ref(): + def _get_ref(self): + return self._constructor_ref + def _set_ref(self, ref): + if hasattr(self, "_constructor_ref"): + raise TypeError, ("can only set constructor_ref once!" + " currently: %s" % (self._constructor_ref,)) + if " " in ref: + ref = '"%s"' % (ref,) + self._constructor_ref = ref + return property(_get_ref, _set_ref) + constructor_ref = constructor_ref() # __________________ before "implementation" ____________________ def writedatatypedecl(self, codewriter): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/structnode.py Tue Jul 5 20:13:26 2005 @@ -2,21 +2,23 @@ from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2 import varsize from pypy.rpython import lltype +import itertools +nextnum = itertools.count().next + log = log.structnode class StructTypeNode(LLVMNode): _issetup = False - struct_counter = 0 def __init__(self, db, struct): assert isinstance(struct, lltype.Struct) self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name, StructTypeNode.struct_counter) + self.name = "%s.%s" % (self.struct._name, nextnum()) self.ref = "%%st.%s" % self.name - StructTypeNode.struct_counter += 1 def __str__(self): return "" %(self.ref,) @@ -40,50 +42,37 @@ def __init__(self, db, struct): super(StructVarsizeTypeNode, self).__init__(db, struct) - new_var_name = "%%new.st.var.%s" % self.name - self.constructor_name = "%s * %s(int %%len)" % (self.ref, new_var_name) + self.constructor_ref = "%%new.st.var.%s" % (self.name) + self.constructor_decl = "%s * %s(int %%len)" % \ + (self.ref, self.constructor_ref) def __str__(self): return "" %(self.ref,) def writedecl(self, codewriter): # declaration for constructor - codewriter.declare(self.constructor_name) + codewriter.declare(self.constructor_decl) def writeimpl(self, codewriter): from pypy.translator.llvm2.atomic import is_atomic log.writeimpl(self.ref) - codewriter.openfunc(self.constructor_name) - codewriter.label("block0") - indices_to_array = [("int", 0)] - s = self.struct - while isinstance(s, lltype.Struct): - last_pos = len(self.struct._names_without_voids()) - 1 - indices_to_array.append(("uint", last_pos)) - s = s._flds.values()[-1] - - # Into array and length - indices = indices_to_array + [("uint", 1), ("int", "%len")] - codewriter.getelementptr("%size", self.ref + "*", - "null", *indices) - - #XXX is this ok for 64bit? - codewriter.cast("%sizeu", arraytype + "*", "%size", "uint") - codewriter.malloc("%resulttmp", "sbyte", "%sizeu", atomic=is_atomic(self)) - codewriter.cast("%result", "sbyte*", "%resulttmp", self.ref + "*") - - # remember the allocated length for later use. - indices = indices_to_array + [("uint", 0)] - codewriter.getelementptr("%size_ptr", self.ref + "*", - "%result", *indices) - - codewriter.cast("%signedsize", "uint", "%sizeu", "int") - codewriter.store("int", "%signedsize", "%size_ptr") - - codewriter.ret(self.ref + "*", "%result") - codewriter.closefunc() + # build up a list of indices to get to the last + # var-sized struct (or rather the according array) + indices_to_array = [] + current = self.struct + while isinstance(current, lltype.Struct): + last_pos = len(current._names_without_voids()) - 1 + indices_to_array.append(("uint", last_pos)) + name = current._names_without_voids()[-1] + current = current._flds[name] + assert isinstance(current, lltype.Array) + arraytype = self.db.repr_arg_type(current.OF) + # XXX write type info as a comment + varsize.write_constructor(codewriter, + self.ref, self.constructor_decl, arraytype, + indices_to_array) def cast_global(toptr, from_, name): s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, @@ -94,14 +83,11 @@ class StructNode(LLVMNode): _issetup = False - struct_counter = 0 def __init__(self, db, value): self.db = db - name = "%s.%s" % (value._TYPE._name, StructNode.struct_counter) - self.ref = "%%stinstance.%s" % name self.value = value - StructNode.struct_counter += 1 + self.ref = "%%stinstance.%s.%s" % (value._TYPE._name, nextnum()) def __str__(self): return "" %(self.ref,) @@ -127,6 +113,8 @@ if not isinstance(T, lltype.Primitive): # Create a dummy constant hack XXX c = Constant(value, T) + + # Needs some sanitisation x = self.db.obj2node[c] value = self.db.repr_arg(c) t, v = x.getall() @@ -149,10 +137,10 @@ return "" %(self.ref,) def getall(self): - res = [] - for name in self.value._TYPE._names_without_voids()[:-1]: - T = self.value._TYPE._flds[name] + type_ = self.value._TYPE + for name in type_._names_without_voids()[:-1]: + T = type_._flds[name] value = getattr(self.value, name) if not isinstance(T, lltype.Primitive): # Create a dummy constant hack XXX @@ -162,16 +150,19 @@ res.append((self.db.repr_arg_type(T), value)) # Special case for varsized arrays - self.value._TYPE._names_without_voids()[-1] - x = self.db.obj2node[Constant(value, T)] - t, v = x.get_values() - res.append((t, "{%s}" % v)) + name = type_._names_without_voids()[-1] + T = type_._flds[name] + assert not isinstance(T, lltype.Primitive) + value = getattr(self.value, name) + c = Constant(value, T) + x = self.db.obj2node[c] + t, v = x.getall() + + #value = self.db.repr_arg(c) + value = cast_global(self.db.repr_arg_type(T), t, "{%s}" % v) + res.append((self.db.repr_arg_type(T), value)) - s = self.value._TYPE - fields = [getattr(s, name) for name in s._names_without_voids()[-1]] - l = [self.db.repr_arg_type(field) for field in fields] - l += t - typestr = "{ %s }" % ", ".join(l) + typestr = self.db.repr_arg_type(type_) values = ", ".join(["%s %s" % (t, v) for t, v in res]) return typestr, values Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 20:13:26 2005 @@ -12,7 +12,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rarithmetic import r_uint -py.log.setconsumer("genllvm", py.log.STDOUT) +#py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) @@ -288,7 +288,7 @@ f = compile_function(list_getitem_pbc, [int]) assert f(0) == 1 assert f(1) == 2 - + def test_list_list_getitem_pbc(): l = [[0, 1], [0, 1]] def list_list_getitem_pbc(i): @@ -314,11 +314,17 @@ for j in range(6): assert f(i,j) == list_basic_ops(i,j) +def test_string_simple(): + def string_simple(i): + return ord(str(i)) + f = compile_function(string_simple, [int], view=False) + assert f(0) + def Xtest_string_getitem1(): l = "Hello, World" - def string_test(i): + def string_getitem1(i): return l[i] - f = compile_function(string_test, [int], view=True) + f = compile_function(string_getitem1, [int], view=True) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From ericvrp at codespeak.net Tue Jul 5 20:13:51 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 5 Jul 2005 20:13:51 +0200 (CEST) Subject: [pypy-svn] r14308 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050705181351.C82A327B45@code1.codespeak.net> Author: ericvrp Date: Tue Jul 5 20:13:50 2005 New Revision: 14308 Added: pypy/dist/pypy/translator/llvm2/extfunctions.py Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Initial version of external function calls working. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Tue Jul 5 20:13:50 2005 @@ -76,7 +76,10 @@ ct = ct.TO if isinstance(ct, lltype.FuncType): - self.addpending(const_or_var, FuncNode(self, const_or_var)) + if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'): + log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj))) + else: + self.addpending(const_or_var, FuncNode(self, const_or_var)) else: value = const_or_var.value while hasattr(value, "_obj"): Added: pypy/dist/pypy/translator/llvm2/extfunctions.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/extfunctions.py Tue Jul 5 20:13:50 2005 @@ -0,0 +1,17 @@ +extdeclarations = """; External declarations + +declare int %dup(int) + +; End of external declarations +""" + +extfunctions = """; External functions (will be inlined by LLVM) + +int %ll_os_dup__Signed(int %i) { +block0: + %i.0 = call int %dup(int %i) + ret int %i.0 +} + +; End of external functions +""" Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Tue Jul 5 20:13:50 2005 @@ -7,6 +7,7 @@ from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log +from pypy.rpython.extfunctable import table as extfunctable nextnum = py.std.itertools.count().next log = log.funcnode @@ -38,6 +39,7 @@ def __init__(self, db, const_ptr_func): self.db = db + self.const_ptr_func = const_ptr_func self.ref = "%" + const_ptr_func.value._obj._name self.graph = const_ptr_func.value._obj.graph remove_same_as(self.graph) @@ -65,6 +67,12 @@ codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): + _callable = self.const_ptr_func.value._obj._callable + for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? + if _callable is extfuncinfo.ll_function: + log('skipped output of external function %s' % self.const_ptr_func.value._obj._name) + return + assert self._issetup graph = self.graph log.writeimpl(graph.name) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Tue Jul 5 20:13:50 2005 @@ -12,6 +12,7 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void +from pypy.translator.llvm2.extfunctions import extdeclarations, extfunctions function_count = {} @@ -39,6 +40,8 @@ typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() + for extdecl in extdeclarations.split('\n'): + codewriter.append(extdecl) if use_boehm_gc: codewriter.declare('sbyte* %GC_malloc(uint)') codewriter.declare('sbyte* %GC_malloc_atomic(uint)') @@ -49,6 +52,8 @@ #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() + for extfunc in extfunctions.split('\n'): + codewriter.append(extfunc) for typ_decl in db.getobjects(): typ_decl.writeimpl(codewriter) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 5 20:13:50 2005 @@ -37,6 +37,13 @@ f = getattr(mod, function.func_name + "_wrapper") return mod, f +def test_external_function(): + import os + def fn(): + return os.dup(0) + f = compile_function(fn, [], view=False) + assert os.path.sameopenfile(f(), fn()) + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") @@ -324,7 +331,7 @@ l = "Hello, World" def string_getitem1(i): return l[i] - f = compile_function(string_getitem1, [int], view=True) + f = compile_function(string_getitem1, [int], view=False) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From arigo at codespeak.net Tue Jul 5 20:40:50 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 20:40:50 +0200 (CEST) Subject: [pypy-svn] r14310 - pypy/branch/dist-2.4.1/pypy/interpreter/pyparser Message-ID: <20050705184050.1ADD027B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 20:40:49 2005 New Revision: 14310 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py Log: Patch the automata to recognize the triple-quote constuctions r''', u''', etc. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pytokenize.py Tue Jul 5 20:40:49 2005 @@ -87,7 +87,7 @@ 't': 1, 'u': 1, 'v': 1, 'w': 1, 'x': 1, 'y': 1, 'z': 1}, - {'"': 20, "'": 19, '0': 1, '1': 1, + {'"': 16, "'": 15, '0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '7': 1, '8': 1, '9': 1, 'A': 1, 'B': 1, 'C': 1, 'D': 1, @@ -105,7 +105,7 @@ 'v': 1, 'w': 1, 'x': 1, 'y': 1, 'z': 1}, - {'"': 20, "'": 19, '0': 1, '1': 1, + {'"': 16, "'": 15, '0': 1, '1': 1, '2': 1, '3': 1, '4': 1, '5': 1, '6': 1, '7': 1, '8': 1, '9': 1, 'A': 1, 'B': 1, 'C': 1, 'D': 1, From arigo at codespeak.net Tue Jul 5 20:53:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 20:53:31 +0200 (CEST) Subject: [pypy-svn] r14311 - pypy/branch/dist-2.4.1/pypy/interpreter/pyparser Message-ID: <20050705185331.9231227B44@code1.codespeak.net> Author: arigo Date: Tue Jul 5 20:53:31 2005 New Revision: 14311 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/syntaxtree.py Log: Intermediate check-in: streamlining exceptions Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 20:53:31 2005 @@ -71,8 +71,8 @@ tokenmod.COMMENT = tokenmod.N_TOKENS tokenmod.NL = tokenmod.N_TOKENS + 1 -class TokenError(SyntaxError): - """Raised when EOF is found prematuerly""" +class TokenError(Exception): + """Raised for lexer errors, e.g. when EOF is found prematurely""" def __init__(self, msg, line, strstart, token_stack): self.lineno, self.offset = strstart self.text = line @@ -312,7 +312,7 @@ def next(self): """Returns the next parsed token""" if self.stack_pos >= len(self.token_stack): - raise StopIteration("Remove me") + raise StopIteration tok, line, lnum, pos = self.token_stack[self.stack_pos] self.stack_pos += 1 self._current_line = line Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/syntaxtree.py Tue Jul 5 20:53:31 2005 @@ -113,7 +113,7 @@ # helper function for nodes that have only one subnode: if len(self.nodes) == 1: return self.nodes[0].visit(visitor) - raise RuntimeError("Unknonw Visitor for %r" % self.name) + raise RuntimeError("Unknown Visitor for %r" % self.name) def expand(self): """expand the syntax node to its content, From arigo at codespeak.net Tue Jul 5 21:35:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 21:35:14 +0200 (CEST) Subject: [pypy-svn] r14312 - in pypy/branch/dist-2.4.1/pypy: interpreter interpreter/pyparser module/recparser Message-ID: <20050705193514.9D73927B40@code1.codespeak.net> Author: arigo Date: Tue Jul 5 21:35:09 2005 New Revision: 14312 Added: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/error.py (contents, props changed) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py Log: Unified the exceptions raised by the parser. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Tue Jul 5 21:35:09 2005 @@ -178,18 +178,30 @@ the whole source after having only added a new '\n') """ def compile(self, source, filename, mode, flags): + from pyparser.error import ParseError + from pyparser.pythonutil import ast_from_input + flags |= __future__.generators.compiler_flag # always on (2.2 compat) + # XXX use 'flags' + space = self.space + transformer = Transformer() + try: + tree = ast_from_input(source, mode, transformer) + except ParseError, e: + raise OperationError(space.w_SyntaxError, + e.wrap_info(space, filename)) + c = self.compile_tree(tree, filename, mode) + from pypy.interpreter.pycode import PyCode + return space.wrap(PyCode(space)._from_code(c)) + + def compile_tree(self, tree, filename, mode): + # __________ + # XXX this uses the non-annotatable stablecompiler at interp-level from pypy.interpreter import stablecompiler from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator from pypy.interpreter.stablecompiler.transformer import Transformer - from pyparser.pythonutil import ast_from_input - - flags |= __future__.generators.compiler_flag # always on (2.2 compat) - space = self.space try: - transformer = Transformer() - tree = ast_from_input(source, mode, transformer) stablecompiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) @@ -198,9 +210,6 @@ else: # mode == 'eval': codegenerator = ExpressionCodeGenerator(tree) c = codegenerator.getCode() - # It would be nice to propagate all exceptions to app level, - # but here we only propagate the 'usual' ones, until we figure - # out how to do it generically. except SyntaxError, e: w_synerr = space.newtuple([space.wrap(e.msg), space.newtuple([space.wrap(e.filename), @@ -212,8 +221,9 @@ raise OperationError(space.w_ValueError,space.wrap(str(e))) except TypeError,e: raise OperationError(space.w_TypeError,space.wrap(str(e))) - from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) + # __________ end of XXX above + return c + compile_tree._annspecialcase_ = 'override:cpy_stablecompiler' class PyPyCompiler(CPythonCompiler): Added: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/error.py ============================================================================== --- (empty file) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/error.py Tue Jul 5 21:35:09 2005 @@ -0,0 +1,24 @@ +from pypy.interpreter.error import OperationError + + +class ParseError(Exception): + """Base class for exceptions raised by the parser.""" + + def __init__(self, msg, lineno, offset, text): + self.msg = msg + self.lineno = lineno + self.offset = offset + self.text = text + + def wrap_info(self, space, filename): + return space.newtuple([space.wrap(self.msg), + space.newtuple([space.wrap(filename), + space.wrap(self.lineno), + space.wrap(self.offset), + space.wrap(self.text)])]) + + def __str__(self): + return "%s at pos (%d, %d) in %r" % (self.__class__.__name__, + self.lineno, + self.offset, + self.text) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 21:35:09 2005 @@ -5,6 +5,7 @@ import symbol, sys from pypy.interpreter.pyparser.grammar import TokenSource, Token +from pypy.interpreter.pyparser.error import ParseError # Don't import string for that ... NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' NUMCHARS = '0123456789' @@ -71,15 +72,11 @@ tokenmod.COMMENT = tokenmod.N_TOKENS tokenmod.NL = tokenmod.N_TOKENS + 1 -class TokenError(Exception): +class TokenError(ParseError): """Raised for lexer errors, e.g. when EOF is found prematurely""" def __init__(self, msg, line, strstart, token_stack): - self.lineno, self.offset = strstart - self.text = line - self.errlabel = msg - self.msg = "TokenError at pos (%d, %d) in %r" % (self.lineno, - self.offset, - line) + lineno, offset = strstart + ParseError.__init__(self, msg, lineno, offset, line) self.token_stack = token_stack def generate_tokens(lines): Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py Tue Jul 5 21:35:09 2005 @@ -6,6 +6,7 @@ using file_input, single_input and eval_input targets """ from pypy.interpreter.error import OperationError, debug_print +from pypy.interpreter.pyparser.error import ParseError from pypy.tool.option import Options from pythonlexer import Source @@ -44,10 +45,9 @@ builder.source_encoding = src.encoding # if not result: - # raising a SyntaxError here is not annotable, and it can - # probably be handled in an other way line, lineno = src.debug() - raise BuilderError(line, lineno) + # XXX needs better error messages + raise ParseError("error", lineno, -1, line) # return None return builder @@ -108,14 +108,6 @@ -class BuilderError(SyntaxError): - def __init__(self, line, lineno): - self.filename = 'XXX.py' - self.line = self.text = line - self.lineno = lineno - self.offset = -1 - self.msg = "SyntaxError at line %d: %r" % (self.lineno, self.line) - def parse_file_input(pyf, gram, builder=None): """Parse a python file""" return gram.parse_source( pyf.read(), "file_input", builder ) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py Tue Jul 5 21:35:09 2005 @@ -5,6 +5,7 @@ import pythonparse from tuplebuilder import TupleBuilder +from pypy.interpreter.pyparser.error import ParseError PYTHON_PARSER = pythonparse.PYTHON_PARSER TARGET_DICT = { Modified: pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/recparser/pyparser.py Tue Jul 5 21:35:09 2005 @@ -8,7 +8,7 @@ from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import SyntaxNode -from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER +from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER, ParseError __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -98,16 +98,23 @@ totuple = interp2app(STType.descr_totuple), ) +def parse_python_source(space, source, goal): + try: + return PYTHON_PARSER.parse_source(source, goal) + except ParseError, e: + raise OperationError(space.w_SyntaxError, + e.wrap_info(space, '')) + def suite( space, source ): # make the annotator life easier (don't use str.splitlines()) - builder = PYTHON_PARSER.parse_source( source, "file_input" ) + builder = parse_python_source( space, source, "file_input" ) return space.wrap( STType(space, builder.stack[-1]) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): # make the annotator life easier (don't use str.splitlines()) - builder = PYTHON_PARSER.parse_source( source, "eval_input" ) + builder = parse_python_source( space, source, "eval_input" ) return space.wrap( STType(space, builder.stack[-1]) ) expr.unwrap_spec = [ObjSpace, str] From arigo at codespeak.net Tue Jul 5 21:43:48 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 21:43:48 +0200 (CEST) Subject: [pypy-svn] r14313 - pypy/branch/dist-2.4.1/pypy/interpreter Message-ID: <20050705194348.1BD2C27B40@code1.codespeak.net> Author: arigo Date: Tue Jul 5 21:43:45 2005 New Revision: 14313 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/error.py Log: Avoiding to crash PyPy when displaying an exception raises an exception. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/error.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/error.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/error.py Tue Jul 5 21:43:45 2005 @@ -51,7 +51,11 @@ if self.w_value == space.w_None: exc_value = None else: - exc_value = space.str_w(space.str(self.w_value)) + try: + exc_value = space.str_w(space.str(self.w_value)) + except OperationError: + # oups, cannot __str__ the exception object + exc_value = "" if not exc_value: return exc_typename else: From arigo at codespeak.net Tue Jul 5 21:51:35 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 21:51:35 +0200 (CEST) Subject: [pypy-svn] r14314 - pypy/branch/dist-2.4.1/pypy/interpreter Message-ID: <20050705195135.BB90A27B40@code1.codespeak.net> Author: arigo Date: Tue Jul 5 21:51:34 2005 New Revision: 14314 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Log: Oups, should have tested before. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Tue Jul 5 21:51:34 2005 @@ -68,7 +68,7 @@ if not err2.match(space, space.w_SyntaxError): raise - if mode != 'single' and space.eq_w(err1.w_value, err2.w_value): + if space.eq_w(err1.w_value, err2.w_value): raise # twice the same error, re-raise return None # two different errors, expect more @@ -179,21 +179,20 @@ """ def compile(self, source, filename, mode, flags): from pyparser.error import ParseError - from pyparser.pythonutil import ast_from_input + from pyparser.pythonutil import pypy_parse flags |= __future__.generators.compiler_flag # always on (2.2 compat) # XXX use 'flags' space = self.space - transformer = Transformer() try: - tree = ast_from_input(source, mode, transformer) + tuples = pypy_parse(source, mode, True) except ParseError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, filename)) - c = self.compile_tree(tree, filename, mode) + c = self.compile_tuples(tuples, filename, mode) from pypy.interpreter.pycode import PyCode return space.wrap(PyCode(space)._from_code(c)) - def compile_tree(self, tree, filename, mode): + def compile_tuples(self, tuples, filename, mode): # __________ # XXX this uses the non-annotatable stablecompiler at interp-level from pypy.interpreter import stablecompiler @@ -202,6 +201,8 @@ from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator from pypy.interpreter.stablecompiler.transformer import Transformer try: + transformer = Transformer() + tree = transformer.compile_node(tuples) stablecompiler.misc.set_filename(filename, tree) if mode == 'exec': codegenerator = ModuleCodeGenerator(tree) @@ -223,7 +224,7 @@ raise OperationError(space.w_TypeError,space.wrap(str(e))) # __________ end of XXX above return c - compile_tree._annspecialcase_ = 'override:cpy_stablecompiler' + compile_tuples._annspecialcase_ = 'override:cpy_stablecompiler' class PyPyCompiler(CPythonCompiler): From hpk at codespeak.net Tue Jul 5 22:14:04 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Jul 2005 22:14:04 +0200 (CEST) Subject: [pypy-svn] r14315 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050705201404.C45A927B42@code1.codespeak.net> Author: hpk Date: Tue Jul 5 22:14:02 2005 New Revision: 14315 Added: pypy/dist/pypy/translator/llvm2/pickleformat.txt (contents, props changed) Log: a draft outlining an example how initializiation data could be read from a string. Added: pypy/dist/pypy/translator/llvm2/pickleformat.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/pickleformat.txt Tue Jul 5 22:14:02 2005 @@ -0,0 +1,61 @@ +x = ptr({6, 7}) +a = {4, 5, x} +b = {8, 9, x} +c = {a,b} + +GET_Tx can be either LOAD_Tx or REF_Tx_index + +LOAD_T1 4 5 (LOAD_T0 6 7) # REF_T1_0 +LOAD_T1 8 9 REF_T0_0 # REF_T1_1 +LOAD_T2 REF_T1_0 REF_T1_1 # REF_T2_0 + +T0 = GcStruct(...) + +T0TBL = Array(Ptr(T0)) +T1TBL = Array(Ptr(T1)) + +ALL_LISTS = GcStruct('all_lists', + ('t0s', Ptr(T0TBL)), + ('t1s', Ptr(T1TBL)), + ('count0', Signed), + ('count1', Signed)) + +def ll_dispatch(fd): + while 1: + instr = ll_read_instr(fd) + if iseof(instr): + break + assert isload(instr) + typeindex = getindex(instr) + ll_get = ll_GET_FUNCTION_LIST[typeindex] + ll_get(fd, instr, all_lists) + +def ll_GET_T0(fd, instr, all_lists): + if isload(instr): + val1 = ll_read_int(fd) + val2 = ll_read_int(fd) + x = malloc(T0) + x.val1 = val1 + x.val2 = val2 + all_lists.t0s[all_lists.count0] = x + all_lists.count0 += 1 + return x + else: + if is_zero_ptr(instr): + return nullptr(T0) + return all_lists.t0s[getindex(instr)] + +def ll_GET_T1(fd, instr, all_lists): + if isload(instr): + val1 = ll_read_int(fd) + val2 = ll_read_int(fd) + instr = ll_read_instr(fd) + val3 = ll_get_T0(fd, instr) + x = malloc(T1) + x.val1 = val1 + x.val2 = val2 + x.val3 = val3 + T1.append(x) + return x + else: + return T1[getindex(instr)] From tismer at codespeak.net Tue Jul 5 22:30:38 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 5 Jul 2005 22:30:38 +0200 (CEST) Subject: [pypy-svn] r14316 - pypy/dist/pypy/objspace/std Message-ID: <20050705203038.BEB3C27B42@code1.codespeak.net> Author: tismer Date: Tue Jul 5 22:30:37 2005 New Revision: 14316 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: formatting seems to work (the cpython test takes hours, can't wait) Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 5 22:30:37 2005 @@ -63,7 +63,7 @@ def _setshort(self, index, short): a = self.digits[index // 2] - ##!!assert isinstance(short, r_uint) + assert isinstance(short, r_uint) assert short & SHORT_MASK == short if index % 2 == 0: self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short @@ -135,8 +135,8 @@ raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to float")) -def long__Float(space, w_floatobj): #YYYYYY - return W_LongObject(space, *args_from_long(long(w_floatobj.floatval))) +def long__Float(space, w_floatobj): + return _FromDouble(space, w_floatobj.floatval) def int_w__Long(space, w_value): if len(w_value.digits) == 1: @@ -156,11 +156,11 @@ raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to unsigned int")) -def repr__Long(space, w_long): #YYYYYY - return space.wrap(repr(w_long.longval())) +def repr__Long(space, w_long): + return space.wrap(_format(w_long, 10, True)) -def str__Long(space, w_long): #YYYYYY - return space.wrap(str(w_long.longval())) +def str__Long(space, w_long): + return space.wrap(_format(w_long, 10, False)) def eq__Long_Long(space, w_long1, w_long2): if (w_long1.sign != w_long2.sign or @@ -617,14 +617,16 @@ z._normalize() return z -def _inplace_divrem1(pout, pin, n): +def _inplace_divrem1(pout, pin, n, size=0): """ Divide long pin by non-zero digit n, storing quotient in pout, and returning the remainder. It's OK for pin == pout on entry. """ rem = r_uint(0) assert n > 0 and n <= SHORT_MASK - size = len(pin.digits) * 2 - 1 + if not size: + size = len(pin.digits) * 2 + size -= 1 while size >= 0: rem = (rem << SHORT_BIT) + pin._getshort(size) hi = rem // n @@ -774,7 +776,7 @@ vj = r_uint(0) else: vj = v._getshort(j) - carry = r_suint(0) # note: this must hold two digits and sign! + carry = r_suint(0) # note: this must hold two digits and a sign! if vj == w._getshort(size_w-1): q = r_uint(SHORT_MASK) @@ -792,7 +794,7 @@ ) << SHORT_BIT) + v._getshort(j-2)): q -= 1 - + print '***', q##!! i = 0 while i < size_w and i+k < size_v: z = w._getshort(i) * q @@ -809,10 +811,10 @@ v._setshort(i+k, r_uint(0)) if carry == 0: - a._setshort(k, q) + a._setshort(k, q & SHORT_MASK) else: assert carry == -1 - a._setshort(k, q-1) + a._setshort(k, (q-1) & SHORT_MASK) carry = r_suint(0) i = 0 @@ -999,3 +1001,147 @@ one = W_LongObject(space, [r_uint(1)], 1) div = sub__Long_Long(space, div, one) return div, mod + + +def _format(a, base, addL): + """ + Convert a long int object to a string, using a given conversion base. + Return a string object. + If base is 8 or 16, add the proper prefix '0' or '0x'. + """ + size_a = len(a.digits) * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + + assert base >= 2 and base <= 36 + + sign = chr(0) + + # Compute a rough upper bound for the length of the string + i = base + bits = 0 + while i > 1: + bits += 1 + i >>= 1 + i = 5 + int(bool(addL)) + (size_a*LONG_BIT + bits-1) // bits + s = [chr(0)] * i + p = i + if addL: + p -= 1 + s[p] = 'L' + if a.sign < 0: + sign = '-' + + if a.sign == 0: + p -= 1 + s[p] = '0' + elif (base & (base - 1)) == 0: + # JRH: special case for power-of-2 bases + accum = r_uint(0) + accumbits = 0 # # of bits in accum + basebits = 1 # # of bits in base-1 + i = base + while 1: + i >>= 1 + if i <= 1: + break + basebits += 1 + + for i in range(size_a): + accum |= a._getshort(i) << accumbits + accumbits += SHORT_BIT + assert accumbits >= basebits + while 1: + cdigit = accum & (base - 1) + if cdigit < 10: + cdigit += ord('0') + else: + cdigit += ord('A') - 10 + assert p > 0 + p -= 1 + s[p] = chr(cdigit) + accumbits -= basebits + accum >>= basebits + if i < size_a - 1: + if accumbits < basebits: + break + else: + if accum <= 0: + break + else: + # Not 0, and base not a power of 2. Divide repeatedly by + # base, but for speed use the highest power of base that + # fits in a digit. + size = size_a + pin = a # just for similarity to C source which uses the array + # powbasw <- largest power of base that fits in a digit. + powbase = base # powbase == base ** power + power = 1 + while 1: + newpow = powbase * r_uint(base) + if newpow >> SHORT_BIT: # doesn't fit in a digit + break + powbase = newpow + power += 1 + + # Get a scratch area for repeated division. + digitpairs = (size + 1) // 2 + scratch = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + + # Repeatedly divide by powbase. + while 1: + ntostore = power + rem = _inplace_divrem1(scratch, pin, powbase, size) + pin = scratch # no need to use a again + if pin._getshort(size - 1) == 0: + size -= 1 + + # Break rem into digits. + assert ntostore > 0 + while 1: + nextrem = rem // base + c = rem - nextrem * base + assert p > 0 + if c < 10: + c += ord('0') + else: + c += ord('A') - 10 + p -= 1 + s[p] = chr(c) + rem = nextrem + ntostore -= 1 + # Termination is a bit delicate: must not + # store leading zeroes, so must get out if + # remaining quotient and rem are both 0. + if not (ntostore and (size or rem)): + break + if size == 0: + break + + if base == 8: + if size_a != 0: + p -= 1 + s[p] = '0' + elif base == 16: + p -= 1 + s[p] ='x' + p -= 1 + s[p] = '0' + elif base != 10: + p -= 1 + s[p] = '#' + p -= 1 + s[p] = chr(ord('0') + base % 10) + if base > 10: + p -= 1 + s[p] = chr(ord('0') + base // 10) + if sign: + p -= 1 + s[p] = sign + + if p == 0: + return ''.join(s) + else: + return ''.join(s[p:]) + + From arigo at codespeak.net Tue Jul 5 23:33:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 23:33:46 +0200 (CEST) Subject: [pypy-svn] r14319 - in pypy/branch/dist-2.4.1/pypy/interpreter: . pyparser Message-ID: <20050705213346.ACA7027B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 23:33:43 2005 New Revision: 14319 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py Log: Some hacks to make the interactive --pyparse work. Don't look too closely. XXX needs to have the test_samples pass again... Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Tue Jul 5 23:33:43 2005 @@ -184,7 +184,7 @@ # XXX use 'flags' space = self.space try: - tuples = pypy_parse(source, mode, True) + tuples = pypy_parse(source, mode, True, flags) except ParseError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, filename)) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Tue Jul 5 23:33:43 2005 @@ -3,6 +3,7 @@ analyser in grammar.py """ import symbol, sys +from codeop import PyCF_DONT_IMPLY_DEDENT from pypy.interpreter.pyparser.grammar import TokenSource, Token from pypy.interpreter.pyparser.error import ParseError @@ -79,7 +80,7 @@ ParseError.__init__(self, msg, lineno, offset, line) self.token_stack = token_stack -def generate_tokens(lines): +def generate_tokens(lines, flags): """ This is a rewrite of pypy.module.parser.pytokenize.generate_tokens since the original function is not RPYTHON (uses yield) @@ -282,23 +283,25 @@ pos = pos + 1 lnum -= 1 - for indent in indents[1:]: # pop remaining indent levels - tok = token_from_values(tokenmod.DEDENT, '') - token_list.append((tok, line, lnum, pos)) - - ## adim: this can't be (only) that, can it ? - if token_list and token_list[-1] != symbol.file_input: - token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) - ## + if not (flags & PyCF_DONT_IMPLY_DEDENT): + if token_list and token_list[-1][0].name != 'NEWLINE': + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + for indent in indents[1:]: # pop remaining indent levels + tok = token_from_values(tokenmod.DEDENT, '') + token_list.append((tok, line, lnum, pos)) + if token_list and token_list[-1][0].name == 'NEWLINE': + token_list.pop() + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) return token_list, encoding class PythonSource(TokenSource): """This source uses Jonathan's tokenizer""" - def __init__(self, strings): + def __init__(self, strings, flags=0): # TokenSource.__init__(self) - tokens, encoding = generate_tokens(strings) + tokens, encoding = generate_tokens(strings, flags) self.token_stack = tokens self.encoding = encoding self._current_line = '' # the current line (as a string) @@ -313,7 +316,7 @@ tok, line, lnum, pos = self.token_stack[self.stack_pos] self.stack_pos += 1 self._current_line = line - self._lineno = lnum + self._lineno = max(self._lineno, lnum) self._offset = pos return tok Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonparse.py Tue Jul 5 23:33:43 2005 @@ -15,6 +15,7 @@ import os import grammar import symbol +from codeop import PyCF_DONT_IMPLY_DEDENT class PythonParser(object): """Wrapper class for python grammar""" @@ -24,19 +25,20 @@ # Build first sets for each rule (including anonymous ones) grammar.build_first_sets(self.items) - def parse_source(self, textsrc, goal, builder=None): + def parse_source(self, textsrc, goal, builder=None, flags=0): """Parse a python source according to goal""" lines = [line + '\n' for line in textsrc.split('\n')] - if textsrc == '\n': + if textsrc.endswith('\n'): lines.pop() + flags &= ~PyCF_DONT_IMPLY_DEDENT else: last_line = lines[-1] lines[-1] = last_line[:-1] - return self.parse_lines(lines, goal, builder) + return self.parse_lines(lines, goal, builder, flags) - def parse_lines(self, lines, goal, builder=None): + def parse_lines(self, lines, goal, builder=None, flags=0): target = self.rules[goal] - src = Source(lines) + src = Source(lines, flags) if builder is None: builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonutil.py Tue Jul 5 23:33:43 2005 @@ -50,7 +50,7 @@ pyf.close() return pypy_parse(source, 'exec', lineno) -def pypy_parse(source, mode='exec', lineno=False): +def pypy_parse(source, mode='exec', lineno=False, flags=0): """parse using PyPy's parser module and return a tuple of three elements : - The encoding declaration symbol or None if there were no encoding @@ -63,7 +63,7 @@ """ builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) target_rule = TARGET_DICT[mode] - PYTHON_PARSER.parse_source(source, target_rule, builder) + PYTHON_PARSER.parse_source(source, target_rule, builder, flags) stack_element = builder.stack[-1] # convert the stack element into nested tuples (caution, the annotator # can't follow this call) From arigo at codespeak.net Tue Jul 5 23:57:48 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Jul 2005 23:57:48 +0200 (CEST) Subject: [pypy-svn] r14320 - pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test Message-ID: <20050705215748.CFD7C27B42@code1.codespeak.net> Author: arigo Date: Tue Jul 5 23:57:47 2005 New Revision: 14320 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py Log: Made test_samples more stable using the following hack: the two concrete syntax trees are turned into ASTs using their respective compiler packages (PyPy's or CPython's), and the repr of the ASTs are compared. This makes the test independent of the details of the concrete ST. In particular we can re-enable the SKIP_IF_NOT_NATIVE tests. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/test/test_samples.py Tue Jul 5 23:57:47 2005 @@ -17,8 +17,8 @@ # the version of the grammar we use GRAMMAR_MISMATCH = PYTHON_VERSION != PYPY_VERSION SKIP_IF_NOT_NATIVE = [ - "snippet_samples.py", - "snippet_import_statements.py", + #"snippet_samples.py", + #"snippet_import_statements.py", ] @@ -73,7 +73,7 @@ abspath = osp.join(samples_dir, fname) yield check_parse, abspath -def _check_tuples_equality(pypy_tuples, python_tuples, testname): +def DISABLED_check_tuples_equality(pypy_tuples, python_tuples, testname): """XXX FIXME: refactor with assert_tuples_equal()""" try: assert_tuples_equal(pypy_tuples, python_tuples) @@ -86,15 +86,38 @@ print ''.join(print_sym_tuple(python_tuples, names=True, trace=error_path)) assert False, testname + +from pypy.interpreter.stablecompiler.transformer import Transformer as PyPyTransformer +from compiler.transformer import Transformer as PythonTransformer + +def _check_tuples_equality(pypy_tuples, python_tuples, testname): + # compare the two tuples by transforming them into AST, to hide irrelevant + # differences -- typically newlines at the end of the tree. + print 'Comparing the ASTs of', testname + transformer1 = PyPyTransformer() + transformer2 = PythonTransformer() + ast_pypy = transformer1.compile_node(pypy_tuples) + ast_python = transformer2.compile_node(python_tuples) + repr_pypy = repr(ast_pypy) + repr_python = repr(ast_python) + if GRAMMAR_MISMATCH: + # XXX hack: + # hide the more common difference between 2.3 and 2.4, which is + # Function(None, ...) where 'None' stands for no decorator in 2.4 + repr_pypy = repr_pypy .replace("Function(None, ", "Function(") + repr_python = repr_python.replace("Function(None, ", "Function(") + assert repr_pypy == repr_python + + def check_parse(filepath): - pypy_tuples = pypy_parsefile(filepath) - python_tuples = python_parsefile(filepath) + pypy_tuples = pypy_parsefile(filepath, lineno=True) + python_tuples = python_parsefile(filepath, lineno=True) _check_tuples_equality(pypy_tuples, python_tuples, filepath) -def check_parse_input(snippet, mode, lineno=False): - pypy_tuples = pypy_parse(snippet, mode, lineno) - python_tuples = python_parse(snippet, mode, lineno) +def check_parse_input(snippet, mode): + pypy_tuples = pypy_parse(snippet, mode, lineno=True) + python_tuples = python_parse(snippet, mode, lineno=True) _check_tuples_equality(pypy_tuples, python_tuples, snippet) def test_eval_inputs(): @@ -104,8 +127,7 @@ 'True and False', ] for snippet in snippets: - yield check_parse_input, snippet, 'eval', True - yield check_parse_input, snippet, 'eval', False + yield check_parse_input, snippet, 'eval' def test_exec_inputs(): snippets = [ @@ -113,14 +135,12 @@ 'print 6*7', 'if 1:\n x\n', ] for snippet in snippets: - yield check_parse_input, snippet, 'exec', True - yield check_parse_input, snippet, 'exec', False + yield check_parse_input, snippet, 'exec' def test_single_inputs(): snippets = ['a=1', 'True', 'def f(a):\n return a+1\n\n'] for snippet in snippets: - yield check_parse_input, snippet, 'single', True - yield check_parse_input, snippet, 'single', False + yield check_parse_input, snippet, 'single' def test_bad_inputs(): From arigo at codespeak.net Wed Jul 6 00:12:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 00:12:55 +0200 (CEST) Subject: [pypy-svn] r14321 - in pypy/branch/dist-2.4.1/pypy/interpreter: pyparser test Message-ID: <20050705221255.DCA5B27B42@code1.codespeak.net> Author: arigo Date: Wed Jul 6 00:12:53 2005 New Revision: 14321 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py Log: Report the error position for an EOF in multi-line string at the end of the file instead of at the beginning of the """, to make the interactive mode happy. Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pyparser/pythonlexer.py Wed Jul 6 00:12:53 2005 @@ -110,7 +110,6 @@ indents = [0] last_comment = '' encoding = None - strstart = (0, 0) # make the annotator happy pos = -1 lines.append('') # XXX HACK probably not needed @@ -124,8 +123,8 @@ if contstr: # continued string if not line: - raise TokenError("EOF in multi-line string", line, strstart, - token_list) + raise TokenError("EOF in multi-line string", line, + (lnum, 0), token_list) endmatch = endDFA.recognize(line) if -1 != endmatch: pos = end = endmatch @@ -243,7 +242,6 @@ token_list.append((tok, line, lnum, pos)) last_comment = '' else: - strstart = (lnum, start) # multiple lines contstr = line[start:] contline = line break @@ -251,7 +249,6 @@ token[:2] in single_quoted or \ token[:3] in single_quoted: if token[-1] == '\n': # continued string - strstart = (lnum, start) endDFA = (endDFAs[initial] or endDFAs[token[1]] or endDFAs[token[2]]) contstr, needcont = line[start:], 1 @@ -289,9 +286,8 @@ for indent in indents[1:]: # pop remaining indent levels tok = token_from_values(tokenmod.DEDENT, '') token_list.append((tok, line, lnum, pos)) - if token_list and token_list[-1][0].name == 'NEWLINE': - token_list.pop() - token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + if token_list and token_list[-1][0].name != 'NEWLINE': + token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) tok = token_from_values(tokenmod.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/test/test_compiler.py Wed Jul 6 00:12:53 2005 @@ -28,10 +28,12 @@ c4 = self.compiler.compile_command('x = (', '?', 'exec', 0) c5 = self.compiler.compile_command('x = (\n', '?', 'exec', 0) c6 = self.compiler.compile_command('x = (\n\n', '?', 'exec', 0) + c7 = self.compiler.compile_command('x = """a\n', '?', 'exec', 0) assert c3 is None assert c4 is None assert c5 is None assert c6 is None + assert c7 is None space = self.space space.raises_w(space.w_SyntaxError, self.compiler.compile_command, 'if 1:\n x x', '?', 'exec', 0) From cfbolz at codespeak.net Wed Jul 6 00:17:01 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Jul 2005 00:17:01 +0200 (CEST) Subject: [pypy-svn] r14322 - pypy/dist/pypy/objspace/std/test Message-ID: <20050705221701.DFA4627B42@code1.codespeak.net> Author: cfbolz Date: Wed Jul 6 00:17:01 2005 New Revision: 14322 Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py Log: added (failing) test for long to string conversion 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 Wed Jul 6 00:17:01 2005 @@ -320,3 +320,8 @@ print "checking division for %s, %s" % (x, y) check_division(x, y) raises(ZeroDivisionError, "x // 0L") + + def test_str(self): + assert str(-123456789L) == "-123456789" + assert str(123456789L) == "123456789" + From tismer at codespeak.net Wed Jul 6 00:40:41 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 00:40:41 +0200 (CEST) Subject: [pypy-svn] r14323 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050705224041.B5E4427B42@code1.codespeak.net> Author: tismer Date: Wed Jul 6 00:40:40 2005 New Revision: 14323 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: quite a lot more is implemented, basically hash and pow are missing. remaining problem: there is still a special case where we overflow. the intermediate "q" has one bit more. See the comments in longintrepr.h; I fear we finally need tobite and use 15 b Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 6 00:40:40 2005 @@ -435,31 +435,20 @@ w_result._normalize() return w_result -def and__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a & b - return W_LongObject(space, *args_from_long(res)) - -def xor__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a ^ b - return W_LongObject(space, *args_from_long(res)) - -def or__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a | b - return W_LongObject(space, *args_from_long(res)) - -def oct__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(oct(x)) - -def hex__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(hex(x)) +def and__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '&', w_long2) + +def xor__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '^', w_long2) + +def or__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '|', w_long2) + +def oct__Long(space, w_long1): + return space.wrap(_format(w_long1, 8, True)) + +def hex__Long(space, w_long1): + 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)]) @@ -794,7 +783,6 @@ ) << SHORT_BIT) + v._getshort(j-2)): q -= 1 - print '***', q##!! i = 0 while i < size_w and i+k < size_v: z = w._getshort(i) * q @@ -1015,7 +1003,7 @@ assert base >= 2 and base <= 36 - sign = chr(0) + sign = False # Compute a rough upper bound for the length of the string i = base @@ -1030,7 +1018,7 @@ p -= 1 s[p] = 'L' if a.sign < 0: - sign = '-' + sign = True if a.sign == 0: p -= 1 @@ -1137,7 +1125,7 @@ s[p] = chr(ord('0') + base // 10) if sign: p -= 1 - s[p] = sign + s[p] = '-' if p == 0: return ''.join(s) @@ -1145,3 +1133,83 @@ return ''.join(s[p:]) +def _bitwise(a, op, n): # '&', '|', '^' + """ Bitwise and/xor/or operations """ + + if a.sign < 0: + a = invert__Long(a.space, a) + maska = r_uint(SHORT_MASK) + else: + maska = r_uint(0) + if b.sign < 0: + b = invert__Long(b.space, b) + maskb = r_uint(SHORT_MASK) + else: + maskb = r_uint(0) + + negz = 0 + if op == '^': + if maska != maskb: + maska ^= SHORT_MASK + negz = -1 + elif op == '&': + if maska and maskb: + op = '|' + maska ^= SHORT_MASK + maskb ^= SHORT_MASK + negz = -1 + elif op == '|': + if maska or maskb: + op = '&' + maska ^= SHORT_MASK + maskb ^= SHORT_MASK + negz = -1 + + # JRH: The original logic here was to allocate the result value (z) + # as the longer of the two operands. However, there are some cases + # where the result is guaranteed to be shorter than that: AND of two + # positives, OR of two negatives: use the shorter number. AND with + # mixed signs: use the positive number. OR with mixed signs: use the + # negative number. After the transformations above, op will be '&' + # iff one of these cases applies, and mask will be non-0 for operands + # whose length should be ignored. + + size_a = len(a.digits) * 2 + if a._getshort(size_a - 1) == 0: + size_a -= 1 + if b._getshort(size_b - 1) == 0: + size_b -= 1 + if op == '&': + if maska: + size_z = size_b + else: + if maskb: + size_z = size_a + else: + size_z = min(size_a, size_b) + else: + size_z = max(size_a, size_b) + + digitpairs = (size_z + 1) // 2 + z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + + for i in range(size_z): + if i < size_a: + diga = a._getshort(i) ^ maska + else: + diga = maska + if i < size_b: + digb = b._getshort(i) ^ maskb + else: + digb = maskb + if op == '&': + z._setshort(i, diga & digb) + elif op == '|': + z._setshort(i, diga | digb) + elif op == '^': + z._setshort(i, diga ^ digb) + + z_normalize() + if negz == 0: + return z + return invert__Long(z) 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 Wed Jul 6 00:40:40 2005 @@ -161,7 +161,7 @@ def test_conversions(self): space = self.space - for v in (0,1,-1,sys.maxint,-sys.maxint-1): + for v in (0, 1, -1, sys.maxint, -sys.maxint-1): assert lobj.W_LongObject(self.space, *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)): @@ -319,9 +319,15 @@ for y in [-105566530L, -1L, 1L, 1034522340L]: print "checking division for %s, %s" % (x, y) check_division(x, y) - raises(ZeroDivisionError, "x // 0L") - - def test_str(self): - assert str(-123456789L) == "-123456789" - assert str(123456789L) == "123456789" - + # special case from python tests: + x = 16565645174462751485571442763871865344588923363439663038777355323778298703228675004033774331442052275771343018700586987657790981527457655176938756028872904152013524821759375058141439 + y = 10953035502453784575 + print "special case" + check_division(x, y) + raises(ZeroDivisionError, "x // 0L") + + def test_format(self): + assert repr(12345678901234567890) == '12345678901234567890L' + assert str(12345678901234567890) == '12345678901234567890' + assert hex(0x1234567890ABCDEFL) == '0x1234567890ABCDEFL' + assert oct(01234567012345670L) == '01234567012345670L' From arigo at codespeak.net Wed Jul 6 13:17:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 13:17:53 +0200 (CEST) Subject: [pypy-svn] r14324 - in pypy/branch/dist-2.4.1/pypy: interpreter interpreter/test module/__builtin__ tool Message-ID: <20050706111753.1BC1927B40@code1.codespeak.net> Author: arigo Date: Wed Jul 6 13:17:48 2005 New Revision: 14324 Modified: pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/compiling.py pypy/branch/dist-2.4.1/pypy/tool/option.py Log: - simplified for now the command-line options (--compiler and --parsermodule) - made test_interpreter independent of the default --compiler option - skip the huge expression test with the recparser - bug fix in pycompiler.py - check before crashing if the app-level compile() is called with a invalid 'mode' Modified: pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/baseobjspace.py Wed Jul 6 13:17:48 2005 @@ -185,17 +185,14 @@ def createcompiler(self): "Factory function creating a compiler object." - if self.options.parser == 'recparser': - if self.options.compiler == 'cpython': - return PythonCompiler(self) - else: - return PyPyCompiler(self) - elif self.options.compiler == 'pyparse': - # <=> options.parser == 'cpython' + # XXX simple selection logic for now + if self.options.compiler == 'pyparse': return PythonCompiler(self) - else: - # <=> options.compiler == 'cpython' and options.parser == 'cpython' + elif self.options.compiler == 'cpython': return CPythonCompiler(self) + else: + raise ValueError('unknown --compiler option value: %r' % ( + self.options.compiler,)) # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses Modified: pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/pycompiler.py Wed Jul 6 13:17:48 2005 @@ -200,6 +200,7 @@ from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator from pypy.interpreter.stablecompiler.transformer import Transformer + space = self.space try: transformer = Transformer() tree = transformer.compile_node(tuples) Modified: pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/dist-2.4.1/pypy/interpreter/test/test_interpreter.py Wed Jul 6 13:17:48 2005 @@ -1,12 +1,13 @@ import py import sys -from pypy.interpreter.pycompiler import PythonCompiler class TestInterpreter: + from pypy.interpreter.pycompiler import CPythonCompiler as CompilerClass + def codetest(self, source, functionname, args): """Compile and run the given code string, and then call its function named by 'functionname' with arguments 'args'.""" - from pypy.interpreter import baseobjspace, executioncontext + from pypy.interpreter import baseobjspace from pypy.interpreter import pyframe, gateway, module space = self.space @@ -33,11 +34,14 @@ else: return space.unwrap(w_output) - #def setup_class(cls): - # cls.space = testit.objspace() + def setup_method(self, arg): + ec = self.space.getexecutioncontext() + self.saved_compiler = ec.compiler + ec.compiler = self.CompilerClass(self.space) - #def teardown_class(cls): - # del cls.space + def teardown_method(self, arg): + ec = self.space.getexecutioncontext() + ec.compiler = self.saved_compiler def test_exception_trivial(self): x = self.codetest('''\ @@ -227,19 +231,14 @@ assert self.codetest(code, 'g', [12, {}]) == () assert self.codetest(code, 'g', [12, {3:1}]) == (3,) + class TestPyPyInterpreter(TestInterpreter): """Runs the previous test with the pypy parser""" - def setup_class(klass): - sys.setrecursionlimit(10000) + from pypy.interpreter.pycompiler import PythonCompiler as CompilerClass - def setup_method(self,arg): - ec = self.space.getexecutioncontext() - self.saved_compiler = ec.compiler - ec.compiler = PythonCompiler(self.space) + def test_extended_arg(self): + py.test.skip("expression too large for the recursive parser") - def teardown_method(self,arg): - ec = self.space.getexecutioncontext() - ec.compiler = self.saved_compiler class AppTestInterpreter: def test_trivial(self): Modified: pypy/branch/dist-2.4.1/pypy/module/__builtin__/compiling.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/module/__builtin__/compiling.py (original) +++ pypy/branch/dist-2.4.1/pypy/module/__builtin__/compiling.py Wed Jul 6 13:17:48 2005 @@ -22,6 +22,11 @@ else: flags |= ec.compiler.getcodeflags(caller.code) + if mode not in ('exec', 'eval', 'single'): + raise OperationError(space.w_ValueError, + space.wrap("compile() arg 3 must be 'exec' " + "or 'eval' or 'single'")) + code = ec.compiler.compile(str_, filename, mode, flags) return space.wrap(code) # Modified: pypy/branch/dist-2.4.1/pypy/tool/option.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/tool/option.py (original) +++ pypy/branch/dist-2.4.1/pypy/tool/option.py Wed Jul 6 13:17:48 2005 @@ -10,9 +10,8 @@ spaces = [] oldstyle = 0 uselibfile = 0 - useparsermodule = "cpython" # "cpython" / "recparser" / "parser" - parser = "cpython" # "cpython" / "pyparse" - compiler = "cpython" # "cpython" + useparsermodule = "recparser" # "cpython" / "recparser" / "parser" + compiler = "pyparse" # "cpython" # "pyparse" pypy parser, cpython compiler # "pycomp" pypy parser and compiler (TBD) version = "2.4" # "native" / "2.3" / "2.4" @@ -46,8 +45,9 @@ callback=run_tb_server, help="use web browser for traceback info")) options.append(make_option( - '--pyparse', action="store_const", dest="compiler", const="pyparse", - help="enable the internal pypy parser with CPython compiler")) + '--compiler', action="store", type="string", dest="compiler", + help="select the parser/compiler to use internally", + metavar="[cpython|pyparse]")) options.append(make_option( '--parsermodule', action="store",type="string", dest="useparsermodule", help="select the parser module to use", From arigo at codespeak.net Wed Jul 6 13:30:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 13:30:32 +0200 (CEST) Subject: [pypy-svn] r14325 - in pypy/branch/dist-2.4.1/pypy: objspace/std objspace/std/test translator/llvm2 translator/llvm2/test Message-ID: <20050706113032.C442F27B47@code1.codespeak.net> Author: arigo Date: Wed Jul 6 13:30:32 2005 New Revision: 14325 Added: pypy/branch/dist-2.4.1/pypy/translator/llvm2/extfunctions.py - copied unchanged from r14324, pypy/dist/pypy/translator/llvm2/extfunctions.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/pickleformat.txt - copied unchanged from r14324, pypy/dist/pypy/translator/llvm2/pickleformat.txt Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Log: svn merge -r14306:14324 http://codespeak.net/svn/pypy/dist Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py Wed Jul 6 13:30:32 2005 @@ -63,7 +63,7 @@ def _setshort(self, index, short): a = self.digits[index // 2] - ##!!assert isinstance(short, r_uint) + assert isinstance(short, r_uint) assert short & SHORT_MASK == short if index % 2 == 0: self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short @@ -135,8 +135,8 @@ raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to float")) -def long__Float(space, w_floatobj): #YYYYYY - return W_LongObject(space, *args_from_long(long(w_floatobj.floatval))) +def long__Float(space, w_floatobj): + return _FromDouble(space, w_floatobj.floatval) def int_w__Long(space, w_value): if len(w_value.digits) == 1: @@ -156,11 +156,11 @@ raise OperationError(space.w_OverflowError, space.wrap("long int too large to convert to unsigned int")) -def repr__Long(space, w_long): #YYYYYY - return space.wrap(repr(w_long.longval())) +def repr__Long(space, w_long): + return space.wrap(_format(w_long, 10, True)) -def str__Long(space, w_long): #YYYYYY - return space.wrap(str(w_long.longval())) +def str__Long(space, w_long): + return space.wrap(_format(w_long, 10, False)) def eq__Long_Long(space, w_long1, w_long2): if (w_long1.sign != w_long2.sign or @@ -435,31 +435,20 @@ w_result._normalize() return w_result -def and__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a & b - return W_LongObject(space, *args_from_long(res)) - -def xor__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a ^ b - return W_LongObject(space, *args_from_long(res)) - -def or__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a | b - return W_LongObject(space, *args_from_long(res)) - -def oct__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(oct(x)) - -def hex__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(hex(x)) +def and__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '&', w_long2) + +def xor__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '^', w_long2) + +def or__Long_Long(space, w_long1, w_long2): + return _bitwise(w_long1, '|', w_long2) + +def oct__Long(space, w_long1): + return space.wrap(_format(w_long1, 8, True)) + +def hex__Long(space, w_long1): + 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)]) @@ -617,14 +606,16 @@ z._normalize() return z -def _inplace_divrem1(pout, pin, n): +def _inplace_divrem1(pout, pin, n, size=0): """ Divide long pin by non-zero digit n, storing quotient in pout, and returning the remainder. It's OK for pin == pout on entry. """ rem = r_uint(0) assert n > 0 and n <= SHORT_MASK - size = len(pin.digits) * 2 - 1 + if not size: + size = len(pin.digits) * 2 + size -= 1 while size >= 0: rem = (rem << SHORT_BIT) + pin._getshort(size) hi = rem // n @@ -774,7 +765,7 @@ vj = r_uint(0) else: vj = v._getshort(j) - carry = r_suint(0) # note: this must hold two digits and sign! + carry = r_suint(0) # note: this must hold two digits and a sign! if vj == w._getshort(size_w-1): q = r_uint(SHORT_MASK) @@ -792,7 +783,6 @@ ) << SHORT_BIT) + v._getshort(j-2)): q -= 1 - i = 0 while i < size_w and i+k < size_v: z = w._getshort(i) * q @@ -809,10 +799,10 @@ v._setshort(i+k, r_uint(0)) if carry == 0: - a._setshort(k, q) + a._setshort(k, q & SHORT_MASK) else: assert carry == -1 - a._setshort(k, q-1) + a._setshort(k, (q-1) & SHORT_MASK) carry = r_suint(0) i = 0 @@ -999,3 +989,227 @@ one = W_LongObject(space, [r_uint(1)], 1) div = sub__Long_Long(space, div, one) return div, mod + + +def _format(a, base, addL): + """ + Convert a long int object to a string, using a given conversion base. + Return a string object. + If base is 8 or 16, add the proper prefix '0' or '0x'. + """ + size_a = len(a.digits) * 2 + if a._getshort(size_a-1) == 0: + size_a -= 1 + + assert base >= 2 and base <= 36 + + sign = False + + # Compute a rough upper bound for the length of the string + i = base + bits = 0 + while i > 1: + bits += 1 + i >>= 1 + i = 5 + int(bool(addL)) + (size_a*LONG_BIT + bits-1) // bits + s = [chr(0)] * i + p = i + if addL: + p -= 1 + s[p] = 'L' + if a.sign < 0: + sign = True + + if a.sign == 0: + p -= 1 + s[p] = '0' + elif (base & (base - 1)) == 0: + # JRH: special case for power-of-2 bases + accum = r_uint(0) + accumbits = 0 # # of bits in accum + basebits = 1 # # of bits in base-1 + i = base + while 1: + i >>= 1 + if i <= 1: + break + basebits += 1 + + for i in range(size_a): + accum |= a._getshort(i) << accumbits + accumbits += SHORT_BIT + assert accumbits >= basebits + while 1: + cdigit = accum & (base - 1) + if cdigit < 10: + cdigit += ord('0') + else: + cdigit += ord('A') - 10 + assert p > 0 + p -= 1 + s[p] = chr(cdigit) + accumbits -= basebits + accum >>= basebits + if i < size_a - 1: + if accumbits < basebits: + break + else: + if accum <= 0: + break + else: + # Not 0, and base not a power of 2. Divide repeatedly by + # base, but for speed use the highest power of base that + # fits in a digit. + size = size_a + pin = a # just for similarity to C source which uses the array + # powbasw <- largest power of base that fits in a digit. + powbase = base # powbase == base ** power + power = 1 + while 1: + newpow = powbase * r_uint(base) + if newpow >> SHORT_BIT: # doesn't fit in a digit + break + powbase = newpow + power += 1 + + # Get a scratch area for repeated division. + digitpairs = (size + 1) // 2 + scratch = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + + # Repeatedly divide by powbase. + while 1: + ntostore = power + rem = _inplace_divrem1(scratch, pin, powbase, size) + pin = scratch # no need to use a again + if pin._getshort(size - 1) == 0: + size -= 1 + + # Break rem into digits. + assert ntostore > 0 + while 1: + nextrem = rem // base + c = rem - nextrem * base + assert p > 0 + if c < 10: + c += ord('0') + else: + c += ord('A') - 10 + p -= 1 + s[p] = chr(c) + rem = nextrem + ntostore -= 1 + # Termination is a bit delicate: must not + # store leading zeroes, so must get out if + # remaining quotient and rem are both 0. + if not (ntostore and (size or rem)): + break + if size == 0: + break + + if base == 8: + if size_a != 0: + p -= 1 + s[p] = '0' + elif base == 16: + p -= 1 + s[p] ='x' + p -= 1 + s[p] = '0' + elif base != 10: + p -= 1 + s[p] = '#' + p -= 1 + s[p] = chr(ord('0') + base % 10) + if base > 10: + p -= 1 + s[p] = chr(ord('0') + base // 10) + if sign: + p -= 1 + s[p] = '-' + + if p == 0: + return ''.join(s) + else: + return ''.join(s[p:]) + + +def _bitwise(a, op, n): # '&', '|', '^' + """ Bitwise and/xor/or operations """ + + if a.sign < 0: + a = invert__Long(a.space, a) + maska = r_uint(SHORT_MASK) + else: + maska = r_uint(0) + if b.sign < 0: + b = invert__Long(b.space, b) + maskb = r_uint(SHORT_MASK) + else: + maskb = r_uint(0) + + negz = 0 + if op == '^': + if maska != maskb: + maska ^= SHORT_MASK + negz = -1 + elif op == '&': + if maska and maskb: + op = '|' + maska ^= SHORT_MASK + maskb ^= SHORT_MASK + negz = -1 + elif op == '|': + if maska or maskb: + op = '&' + maska ^= SHORT_MASK + maskb ^= SHORT_MASK + negz = -1 + + # JRH: The original logic here was to allocate the result value (z) + # as the longer of the two operands. However, there are some cases + # where the result is guaranteed to be shorter than that: AND of two + # positives, OR of two negatives: use the shorter number. AND with + # mixed signs: use the positive number. OR with mixed signs: use the + # negative number. After the transformations above, op will be '&' + # iff one of these cases applies, and mask will be non-0 for operands + # whose length should be ignored. + + size_a = len(a.digits) * 2 + if a._getshort(size_a - 1) == 0: + size_a -= 1 + if b._getshort(size_b - 1) == 0: + size_b -= 1 + if op == '&': + if maska: + size_z = size_b + else: + if maskb: + size_z = size_a + else: + size_z = min(size_a, size_b) + else: + size_z = max(size_a, size_b) + + digitpairs = (size_z + 1) // 2 + z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + + for i in range(size_z): + if i < size_a: + diga = a._getshort(i) ^ maska + else: + diga = maska + if i < size_b: + digb = b._getshort(i) ^ maskb + else: + digb = maskb + if op == '&': + z._setshort(i, diga & digb) + elif op == '|': + z._setshort(i, diga | digb) + elif op == '^': + z._setshort(i, diga ^ digb) + + z_normalize() + if negz == 0: + return z + return invert__Long(z) Modified: pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py Wed Jul 6 13:30:32 2005 @@ -161,7 +161,7 @@ def test_conversions(self): space = self.space - for v in (0,1,-1,sys.maxint,-sys.maxint-1): + for v in (0, 1, -1, sys.maxint, -sys.maxint-1): assert lobj.W_LongObject(self.space, *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)): @@ -319,4 +319,15 @@ for y in [-105566530L, -1L, 1L, 1034522340L]: print "checking division for %s, %s" % (x, y) check_division(x, y) - raises(ZeroDivisionError, "x // 0L") + # special case from python tests: + x = 16565645174462751485571442763871865344588923363439663038777355323778298703228675004033774331442052275771343018700586987657790981527457655176938756028872904152013524821759375058141439 + y = 10953035502453784575 + print "special case" + check_division(x, y) + raises(ZeroDivisionError, "x // 0L") + + def test_format(self): + assert repr(12345678901234567890) == '12345678901234567890L' + assert str(12345678901234567890) == '12345678901234567890' + assert hex(0x1234567890ABCDEFL) == '0x1234567890ABCDEFL' + assert oct(01234567012345670L) == '01234567012345670L' Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/database.py Wed Jul 6 13:30:32 2005 @@ -76,7 +76,10 @@ ct = ct.TO if isinstance(ct, lltype.FuncType): - self.addpending(const_or_var, FuncNode(self, const_or_var)) + if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'): + log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj))) + else: + self.addpending(const_or_var, FuncNode(self, const_or_var)) else: value = const_or_var.value while hasattr(value, "_obj"): Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/funcnode.py Wed Jul 6 13:30:32 2005 @@ -7,6 +7,7 @@ from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log +from pypy.rpython.extfunctable import table as extfunctable nextnum = py.std.itertools.count().next log = log.funcnode @@ -38,6 +39,7 @@ def __init__(self, db, const_ptr_func): self.db = db + self.const_ptr_func = const_ptr_func self.ref = "%" + const_ptr_func.value._obj._name self.graph = const_ptr_func.value._obj.graph remove_same_as(self.graph) @@ -65,6 +67,12 @@ codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): + _callable = self.const_ptr_func.value._obj._callable + for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? + if _callable is extfuncinfo.ll_function: + log('skipped output of external function %s' % self.const_ptr_func.value._obj._name) + return + assert self._issetup graph = self.graph log.writeimpl(graph.name) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/genllvm.py Wed Jul 6 13:30:32 2005 @@ -12,6 +12,7 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void +from pypy.translator.llvm2.extfunctions import extdeclarations, extfunctions function_count = {} @@ -39,6 +40,8 @@ typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() + for extdecl in extdeclarations.split('\n'): + codewriter.append(extdecl) if use_boehm_gc: codewriter.declare('sbyte* %GC_malloc(uint)') codewriter.declare('sbyte* %GC_malloc_atomic(uint)') @@ -49,6 +52,8 @@ #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() + for extfunc in extfunctions.split('\n'): + codewriter.append(extfunc) for typ_decl in db.getobjects(): typ_decl.writeimpl(codewriter) Modified: pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/branch/dist-2.4.1/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 6 13:30:32 2005 @@ -37,6 +37,13 @@ f = getattr(mod, function.func_name + "_wrapper") return mod, f +def test_external_function(): + import os + def fn(): + return os.dup(0) + f = compile_function(fn, [], view=False) + assert os.path.sameopenfile(f(), fn()) + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") @@ -324,7 +331,7 @@ l = "Hello, World" def string_getitem1(i): return l[i] - f = compile_function(string_getitem1, [int], view=True) + f = compile_function(string_getitem1, [int], view=False) assert f(0) == ord("H") def DONOT_test_string_getitem2(): From rxe at codespeak.net Wed Jul 6 13:36:12 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 6 Jul 2005 13:36:12 +0200 (CEST) Subject: [pypy-svn] r14326 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050706113612.13E3927B47@code1.codespeak.net> Author: rxe Date: Wed Jul 6 13:36:10 2005 New Revision: 14326 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Rationalisation of how prebuilt constants interact with the database. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Wed Jul 6 13:36:10 2005 @@ -2,7 +2,6 @@ from pypy.rpython import lltype from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode -from pypy.objspace.flow.model import Constant from pypy.translator.llvm2 import varsize import itertools log = log.structnode @@ -53,44 +52,29 @@ fromtype) class ArrayNode(LLVMNode): - _issetup = False + _issetup = True def __init__(self, db, value): + assert isinstance(lltype.typeOf(value), lltype.Array) self.db = db self.value = value - self.arraytype = value._TYPE.OF - self.ref = "%%arrayinstance.%s.%s" % (value._TYPE.OF, nextnum()) + self.arraytype = lltype.typeOf(value).OF + self.ref = "%%arrayinstance.%s.%s" % (self.arraytype, nextnum()) + if isinstance(self.arraytype, lltype.Ptr): + for item in self.value.items: + self.db.addptrvalue(item) def __str__(self): return "" %(self.ref,) - - def setup(self): - for item in self.value.items: - if not isinstance(self.arraytype, lltype.Primitive): - # Create a dummy constant hack XXX - self.db.prepare_arg(Constant(item, self.arraytype)) - self._issetup = True - - def value_helper(self, value): - """ This should really be pushed back to the database??? XXX """ - if not isinstance(self.arraytype, lltype.Primitive): - # Create a dummy constant hack XXX - value = self.db.repr_arg(Constant(value, self.arraytype)) - else: - if isinstance(value, str) and len(value) == 1: - value = ord(value) - value = str(value) - return value - def getall(self): + def typeandvalue(self): """ Returns the type and value for this node. """ items = self.value.items - typeval = self.db.repr_arg_type(self.arraytype) arraylen = len(items) - type_ = "{ int, [%s x %s] }" % (arraylen, typeval) - arrayvalues = ["%s %s" % (typeval, - self.value_helper(v)) for v in items] + typeval = self.db.repr_arg_type(self.arraytype) + type_ = "{ int, [%s x %s] }" % (arraylen, typeval) + arrayvalues = ["%s %s" % self.db.reprs_constant(v) for v in items] value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, typeval, @@ -101,5 +85,5 @@ # entry points from genllvm def writeglobalconstants(self, codewriter): - type_, values = self.getall() + type_, values = self.typeandvalue() codewriter.globalinstance(self.ref, type_, values) Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Wed Jul 6 13:36:10 2005 @@ -30,7 +30,7 @@ self.append(" %s:" % name) def globalinstance(self, name, type, data): - self.append("%s = internal constant %s {%s}" % (name, type, data)) + self.append("%s = constant %s {%s}" % (name, type, data)) def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Wed Jul 6 13:36:10 2005 @@ -53,8 +53,56 @@ def __init__(self, translator): self._translator = translator self.obj2node = NormalizingDict() + self.ptr2nodevalue = {} self._pendingsetup = [] self._tmpcount = 1 + + def addptrvalue(self, ptrvalue): + value = ptrvalue._obj + node = self.create_constant_node(value) + self.ptr2nodevalue[value] = self.create_constant_node(value) + + def getptrnode(self, ptrvalue): + return self.ptr2nodevalue[ptrvalue._obj] + + def getptrref(self, ptrvalue): + return self.ptr2nodevalue[ptrvalue._obj].ref + + def reprs_constant(self, value): + type_ = lltype.typeOf(value) + if isinstance(type_, lltype.Primitive): + if isinstance(value, str) and len(value) == 1: + res = ord(value) + res = str(value) + elif isinstance(type_, lltype.Ptr): + res = self.getptrref(value) + #elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): + #XXX res = self.value.typeandvalue() + else: + assert False, "not supported XXX" + return self.repr_arg_type(type_), res + + def create_constant_node(self, value): + type_ = lltype.typeOf(value) + node = None + if isinstance(type_, lltype.FuncType): + + if value._callable \ + and not hasattr(value, 'graph'): + log('EXTERNAL FUNCTION' + str(dir(value))) + else: + node = FuncNode(self, value) + + elif isinstance(type_, lltype.Struct): + if type_._arrayfld: + node = StructVarsizeNode(self, value) + else: + node = StructNode(self, value) + + elif isinstance(type_, lltype.Array): + node = ArrayNode(self, value) + assert node is not None, "%s not supported" % lltype.typeOf(value) + return node def addpending(self, key, node): assert key not in self.obj2node, ( @@ -69,37 +117,19 @@ self._pendingsetup and to self.obj2node""" if const_or_var in self.obj2node: return + if isinstance(const_or_var, Constant): - ct = const_or_var.concretetype - while isinstance(ct, lltype.Ptr): - ct = ct.TO - - if isinstance(ct, lltype.FuncType): - if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'): - log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj))) - else: - self.addpending(const_or_var, FuncNode(self, const_or_var)) - else: - value = const_or_var.value - while hasattr(value, "_obj"): - value = value._obj - - if isinstance(ct, lltype.Struct): - if ct._arrayfld: - self.addpending(const_or_var, StructVarsizeNode(self, value)) - else: - self.addpending(const_or_var, StructNode(self, value)) - - elif isinstance(ct, lltype.Array): - self.addpending(const_or_var, ArrayNode(self, value)) - - elif isinstance(ct, lltype.Primitive): - log.prepare(const_or_var, "(is primitive)") - else: - log.XXX("not sure what to do about %s(%s)" % (ct, const_or_var)) + + if isinstance(ct, lltype.Primitive): + log.prepare(const_or_var, "(is primitive)") + return + + assert isinstance(ct, lltype.Ptr), "Preperation of non primitive and non pointer" + value = const_or_var.value._obj + self.addpending(const_or_var, self.create_constant_node(value)) else: - log.prepare(const_or_var, type(const_or_var)) #XXX dont checkin + log.prepare(const_or_var, type(const_or_var)) def prepare_repr_arg_multi(self, args): for const_or_var in args: @@ -144,7 +174,7 @@ def getobjects(self, subset_types=None): res = [] - for v in self.obj2node.values(): + for v in self.obj2node.values() + self.ptr2nodevalue.values(): if subset_types is None or isinstance(v, subset_types): res.append(v) return res Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Wed Jul 6 13:36:10 2005 @@ -37,11 +37,11 @@ class FuncNode(LLVMNode): _issetup = False - def __init__(self, db, const_ptr_func): + def __init__(self, db, value): self.db = db - self.const_ptr_func = const_ptr_func - self.ref = "%" + const_ptr_func.value._obj._name - self.graph = const_ptr_func.value._obj.graph + self.value = value + self.ref = "%" + value._name + self.graph = value.graph remove_same_as(self.graph) remove_double_links(self.db._translator, self.graph) @@ -67,10 +67,10 @@ codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): - _callable = self.const_ptr_func.value._obj._callable + _callable = self.value._callable for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? if _callable is extfuncinfo.ll_function: - log('skipped output of external function %s' % self.const_ptr_func.value._obj._name) + log('skipped output of external function %s' % self.value._name) return assert self._issetup Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Wed Jul 6 13:36:10 2005 @@ -1,6 +1,9 @@ from os.path import exists use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') +#XXXTmp +use_boehm_gc = False + import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Wed Jul 6 13:36:10 2005 @@ -26,6 +26,10 @@ return property(_get_ref, _set_ref) constructor_ref = constructor_ref() + + def setup(self): + pass + # __________________ before "implementation" ____________________ def writedatatypedecl(self, codewriter): """ write out declare names of data types Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Wed Jul 6 13:36:10 2005 @@ -1,5 +1,4 @@ import py -from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2 import varsize @@ -74,6 +73,9 @@ self.ref, self.constructor_decl, arraytype, indices_to_array) + +#XXX Everything downwind of here is experimental code + def cast_global(toptr, from_, name): s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, from_, @@ -88,36 +90,28 @@ self.db = db self.value = value self.ref = "%%stinstance.%s.%s" % (value._TYPE._name, nextnum()) + for name in self.value._TYPE._names_without_voids(): + T = self.value._TYPE._flds[name] + assert T is not lltype.Void + if isinstance(T, lltype.Ptr): + self.db.addptrvalue(getattr(self.value, name)) def __str__(self): return "" %(self.ref,) def setup(self): - for name in self.value._TYPE._names_without_voids(): - T = self.value._TYPE._flds[name] - assert T is not lltype.Void - if not isinstance(T, lltype.Primitive): - value = getattr(self.value, name) - # Create a dummy constant hack XXX - c = Constant(value, T) - self.db.prepare_arg(c) - self._issetup = True - def getall(self): + def typeandvalue(self): res = [] type_ = self.value._TYPE for name in type_._names_without_voids(): T = type_._flds[name] value = getattr(self.value, name) - if not isinstance(T, lltype.Primitive): - # Create a dummy constant hack XXX - c = Constant(value, T) - - # Needs some sanitisation - x = self.db.obj2node[c] - value = self.db.repr_arg(c) - t, v = x.getall() + if isinstance(T, lltype.Ptr): + x = self.db.getptrnode(value) + value = self.db.getptrref(value) + t, v = x.typeandvalue() value = cast_global(self.db.repr_arg_type(T), t, value) else: @@ -129,14 +123,16 @@ return typestr, values def writeglobalconstants(self, codewriter): - type_, values = self.getall() + type_, values = self.typeandvalue() codewriter.globalinstance(self.ref, type_, values) + +#XXX Everything downwind of here is very experimental code and no tests pass class StructVarsizeNode(StructNode): def __str__(self): return "" %(self.ref,) - def getall(self): + def typeandvalue(self): res = [] type_ = self.value._TYPE for name in type_._names_without_voids()[:-1]: @@ -156,7 +152,7 @@ value = getattr(self.value, name) c = Constant(value, T) x = self.db.obj2node[c] - t, v = x.getall() + t, v = x.typeandvalue() #value = self.db.repr_arg(c) value = cast_global(self.db.repr_arg_type(T), t, "{%s}" % v) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 6 13:36:10 2005 @@ -12,7 +12,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rarithmetic import r_uint -#py.log.setconsumer("genllvm", py.log.STDOUT) +py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) @@ -114,7 +114,7 @@ f = compile_function(ops, [int]) assert f(1) == 1 assert f(2) == 2 - + def test_while_loop(): def factorial(i): r = 1 From arigo at codespeak.net Wed Jul 6 14:40:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 14:40:18 +0200 (CEST) Subject: [pypy-svn] r14328 - in pypy/branch/dist-2.4.1: . demo lib-python/2.3.4 lib-python/attic lib-python/modified-2.3.4 pypy pypy/annotation pypy/bin pypy/documentation pypy/interpreter pypy/interpreter/test pypy/interpreter/test/mixedmodule pypy/lib pypy/lib/test2 pypy/module pypy/module/__builtin__ pypy/module/__builtin__/test pypy/module/__builtin__/test/impsubdir pypy/module/_codecs pypy/module/_sre_pypy pypy/module/parser pypy/module/recparser pypy/module/recparser/leftout pypy/module/sys pypy/module/sys/test pypy/module/unicodedata pypy/objspace pypy/objspace/flow pypy/objspace/std pypy/objspace/std/test pypy/objspace/test pypy/rpython pypy/tool pypy/tool/pytest pypy/tool/pytest/test pypy/tool/tb_server pypy/tool/test pypy/translator Message-ID: <20050706124018.2F90327B44@code1.codespeak.net> Author: arigo Date: Wed Jul 6 14:40:14 2005 New Revision: 14328 Added: pypy/branch/dist-2.4.1/LICENSE - copied unchanged from r14327, pypy/dist/LICENSE pypy/branch/dist-2.4.1/README - copied unchanged from r14327, pypy/dist/README pypy/branch/dist-2.4.1/demo/ - copied from r14327, pypy/dist/demo/ pypy/branch/dist-2.4.1/lib-python/2.3.4/ - copied from r14327, pypy/dist/lib-python/2.3.4/ pypy/branch/dist-2.4.1/lib-python/attic/README.regex - copied unchanged from r14327, pypy/dist/lib-python/attic/README.regex pypy/branch/dist-2.4.1/lib-python/attic/dumbre.py - copied unchanged from r14327, pypy/dist/lib-python/attic/dumbre.py pypy/branch/dist-2.4.1/lib-python/attic/plexre.py - copied unchanged from r14327, pypy/dist/lib-python/attic/plexre.py pypy/branch/dist-2.4.1/lib-python/attic/re.py - copied unchanged from r14327, pypy/dist/lib-python/attic/re.py pypy/branch/dist-2.4.1/lib-python/attic/sre_adapt.py - copied unchanged from r14327, pypy/dist/lib-python/attic/sre_adapt.py pypy/branch/dist-2.4.1/lib-python/attic/test_cmathmodule.py - copied unchanged from r14327, pypy/dist/lib-python/attic/test_cmathmodule.py pypy/branch/dist-2.4.1/lib-python/modified-2.3.4/ - copied from r14327, pypy/dist/lib-python/modified-2.3.4/ pypy/branch/dist-2.4.1/pypy/__init__.py - copied unchanged from r14327, pypy/dist/pypy/__init__.py pypy/branch/dist-2.4.1/pypy/annotation/ - copied from r14327, pypy/dist/pypy/annotation/ pypy/branch/dist-2.4.1/pypy/bin/ - copied from r14327, pypy/dist/pypy/bin/ pypy/branch/dist-2.4.1/pypy/conftest.py - copied unchanged from r14327, pypy/dist/pypy/conftest.py pypy/branch/dist-2.4.1/pypy/documentation/ - copied from r14327, pypy/dist/pypy/documentation/ pypy/branch/dist-2.4.1/pypy/interpreter/__init__.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/__init__.py pypy/branch/dist-2.4.1/pypy/interpreter/argument.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/argument.py pypy/branch/dist-2.4.1/pypy/interpreter/autopath.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/autopath.py pypy/branch/dist-2.4.1/pypy/interpreter/debug.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/debug.py pypy/branch/dist-2.4.1/pypy/interpreter/eval.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/eval.py pypy/branch/dist-2.4.1/pypy/interpreter/gateway.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/gateway.py pypy/branch/dist-2.4.1/pypy/interpreter/generator.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/generator.py pypy/branch/dist-2.4.1/pypy/interpreter/interactive.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/interactive.py pypy/branch/dist-2.4.1/pypy/interpreter/main.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/main.py pypy/branch/dist-2.4.1/pypy/interpreter/miscutils.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/miscutils.py pypy/branch/dist-2.4.1/pypy/interpreter/mixedmodule.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/mixedmodule.py pypy/branch/dist-2.4.1/pypy/interpreter/module.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/module.py pypy/branch/dist-2.4.1/pypy/interpreter/nestedscope.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/nestedscope.py pypy/branch/dist-2.4.1/pypy/interpreter/pycode.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/pycode.py pypy/branch/dist-2.4.1/pypy/interpreter/pyframe.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/pyframe.py pypy/branch/dist-2.4.1/pypy/interpreter/pyopcode.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/pyopcode.py pypy/branch/dist-2.4.1/pypy/interpreter/pytraceback.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/pytraceback.py pypy/branch/dist-2.4.1/pypy/interpreter/special.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/special.py pypy/branch/dist-2.4.1/pypy/interpreter/test/__init__.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/__init__.py pypy/branch/dist-2.4.1/pypy/interpreter/test/autopath.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/autopath.py pypy/branch/dist-2.4.1/pypy/interpreter/test/foointerp.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/foointerp.py pypy/branch/dist-2.4.1/pypy/interpreter/test/hello_world.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/hello_world.py pypy/branch/dist-2.4.1/pypy/interpreter/test/mixedmodule/ - copied from r14327, pypy/dist/pypy/interpreter/test/mixedmodule/ pypy/branch/dist-2.4.1/pypy/interpreter/test/s1.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/s1.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_appinterp.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_appinterp.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_class.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_class.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_code.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_code.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_descrtypecheck.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_descrtypecheck.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_eval.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_eval.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_exceptcomp.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_exceptcomp.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_exec.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_exec.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_function.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_function.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_gateway.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_gateway.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_generator.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_generator.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_main.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_main.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_module.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_module.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_nestedscope.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_nestedscope.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_objspace.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_objspace.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_py.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_py.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_pyframe.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_pyframe.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_raise.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_raise.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_special.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_special.py pypy/branch/dist-2.4.1/pypy/interpreter/test/test_typedef.py - copied unchanged from r14327, pypy/dist/pypy/interpreter/test/test_typedef.py pypy/branch/dist-2.4.1/pypy/lib/__init__.py - copied unchanged from r14327, pypy/dist/pypy/lib/__init__.py pypy/branch/dist-2.4.1/pypy/lib/_classobj.py - copied unchanged from r14327, pypy/dist/pypy/lib/_classobj.py pypy/branch/dist-2.4.1/pypy/lib/_file.py - copied unchanged from r14327, pypy/dist/pypy/lib/_file.py pypy/branch/dist-2.4.1/pypy/lib/_float_formatting.py - copied unchanged from r14327, pypy/dist/pypy/lib/_float_formatting.py pypy/branch/dist-2.4.1/pypy/lib/_formatting.py - copied unchanged from r14327, pypy/dist/pypy/lib/_formatting.py pypy/branch/dist-2.4.1/pypy/lib/_sio.py - copied unchanged from r14327, pypy/dist/pypy/lib/_sio.py pypy/branch/dist-2.4.1/pypy/lib/cPickle.py - copied unchanged from r14327, pypy/dist/pypy/lib/cPickle.py pypy/branch/dist-2.4.1/pypy/lib/cStringIO.py - copied unchanged from r14327, pypy/dist/pypy/lib/cStringIO.py pypy/branch/dist-2.4.1/pypy/lib/datetime.py - copied unchanged from r14327, pypy/dist/pypy/lib/datetime.py pypy/branch/dist-2.4.1/pypy/lib/decimal.py - copied unchanged from r14327, pypy/dist/pypy/lib/decimal.py pypy/branch/dist-2.4.1/pypy/lib/gc.py - copied unchanged from r14327, pypy/dist/pypy/lib/gc.py pypy/branch/dist-2.4.1/pypy/lib/imp.py - copied unchanged from r14327, pypy/dist/pypy/lib/imp.py pypy/branch/dist-2.4.1/pypy/lib/itertools.py - copied unchanged from r14327, pypy/dist/pypy/lib/itertools.py pypy/branch/dist-2.4.1/pypy/lib/marshal.py - copied unchanged from r14327, pypy/dist/pypy/lib/marshal.py pypy/branch/dist-2.4.1/pypy/lib/md5.py - copied unchanged from r14327, pypy/dist/pypy/lib/md5.py pypy/branch/dist-2.4.1/pypy/lib/random.py - copied unchanged from r14327, pypy/dist/pypy/lib/random.py pypy/branch/dist-2.4.1/pypy/lib/sha.py - copied unchanged from r14327, pypy/dist/pypy/lib/sha.py pypy/branch/dist-2.4.1/pypy/lib/struct.py - copied unchanged from r14327, pypy/dist/pypy/lib/struct.py pypy/branch/dist-2.4.1/pypy/lib/test2/ - copied from r14327, pypy/dist/pypy/lib/test2/ pypy/branch/dist-2.4.1/pypy/module/README.txt - copied unchanged from r14327, pypy/dist/pypy/module/README.txt pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_complex.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_complex.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_descriptor.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_descriptor.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_functional.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_functional.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_help.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_help.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_inspect.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_inspect.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_io.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_io.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/app_misc.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/app_misc.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/importing.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/importing.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/operation.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/operation.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/__init__.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/__init__.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/autopath.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/autopath.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/impsubdir/ - copied from r14327, pypy/dist/pypy/module/__builtin__/test/impsubdir/ pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_apply.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_apply.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_complexobject.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_complexobject.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_descriptor.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_descriptor.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_filter.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_filter.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_functional.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_functional.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_import.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_import.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_minmax.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_minmax.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_range.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_range.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_reduce.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_reduce.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_vars.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_vars.py pypy/branch/dist-2.4.1/pypy/module/__builtin__/test/test_zip.py - copied unchanged from r14327, pypy/dist/pypy/module/__builtin__/test/test_zip.py pypy/branch/dist-2.4.1/pypy/module/__init__.py - copied unchanged from r14327, pypy/dist/pypy/module/__init__.py pypy/branch/dist-2.4.1/pypy/module/_codecs/ - copied from r14327, pypy/dist/pypy/module/_codecs/ pypy/branch/dist-2.4.1/pypy/module/_sre_pypy/ - copied from r14327, pypy/dist/pypy/module/_sre_pypy/ pypy/branch/dist-2.4.1/pypy/module/parser/ - copied from r14327, pypy/dist/pypy/module/parser/ pypy/branch/dist-2.4.1/pypy/module/recparser/README - copied unchanged from r14327, pypy/dist/pypy/module/recparser/README pypy/branch/dist-2.4.1/pypy/module/recparser/__init__.py - copied unchanged from r14327, pypy/dist/pypy/module/recparser/__init__.py pypy/branch/dist-2.4.1/pypy/module/recparser/compat.py - copied unchanged from r14327, pypy/dist/pypy/module/recparser/compat.py pypy/branch/dist-2.4.1/pypy/module/recparser/leftout/ - copied from r14327, pypy/dist/pypy/module/recparser/leftout/ pypy/branch/dist-2.4.1/pypy/module/sys/app.py - copied unchanged from r14327, pypy/dist/pypy/module/sys/app.py pypy/branch/dist-2.4.1/pypy/module/sys/hook.py - copied unchanged from r14327, pypy/dist/pypy/module/sys/hook.py pypy/branch/dist-2.4.1/pypy/module/sys/test/ - copied from r14327, pypy/dist/pypy/module/sys/test/ pypy/branch/dist-2.4.1/pypy/module/sys/vm.py - copied unchanged from r14327, pypy/dist/pypy/module/sys/vm.py pypy/branch/dist-2.4.1/pypy/module/unicodedata/ - copied from r14327, pypy/dist/pypy/module/unicodedata/ pypy/branch/dist-2.4.1/pypy/objspace/__init__.py - copied unchanged from r14327, pypy/dist/pypy/objspace/__init__.py pypy/branch/dist-2.4.1/pypy/objspace/flow/ - copied from r14327, pypy/dist/pypy/objspace/flow/ pypy/branch/dist-2.4.1/pypy/objspace/proxy.py - copied unchanged from r14327, pypy/dist/pypy/objspace/proxy.py pypy/branch/dist-2.4.1/pypy/objspace/std/__init__.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/__init__.py pypy/branch/dist-2.4.1/pypy/objspace/std/autopath.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/autopath.py pypy/branch/dist-2.4.1/pypy/objspace/std/basestringtype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/basestringtype.py pypy/branch/dist-2.4.1/pypy/objspace/std/boolobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/boolobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/booltype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/booltype.py pypy/branch/dist-2.4.1/pypy/objspace/std/default.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/default.py pypy/branch/dist-2.4.1/pypy/objspace/std/dictproxyobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/dictproxyobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/dictproxytype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/dictproxytype.py pypy/branch/dist-2.4.1/pypy/objspace/std/dicttype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/dicttype.py pypy/branch/dist-2.4.1/pypy/objspace/std/dump_multimethod.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/dump_multimethod.py pypy/branch/dist-2.4.1/pypy/objspace/std/fake.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/fake.py pypy/branch/dist-2.4.1/pypy/objspace/std/floatobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/floatobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/floattype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/floattype.py pypy/branch/dist-2.4.1/pypy/objspace/std/intobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/intobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/inttype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/inttype.py pypy/branch/dist-2.4.1/pypy/objspace/std/iterobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/iterobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/itertype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/itertype.py pypy/branch/dist-2.4.1/pypy/objspace/std/listobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/listobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/listsort.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/listsort.py pypy/branch/dist-2.4.1/pypy/objspace/std/listtype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/listtype.py pypy/branch/dist-2.4.1/pypy/objspace/std/longobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/longtype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/longtype.py pypy/branch/dist-2.4.1/pypy/objspace/std/model.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/model.py pypy/branch/dist-2.4.1/pypy/objspace/std/mro.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/mro.py pypy/branch/dist-2.4.1/pypy/objspace/std/multimethod.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/multimethod.py pypy/branch/dist-2.4.1/pypy/objspace/std/noneobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/noneobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/nonetype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/nonetype.py pypy/branch/dist-2.4.1/pypy/objspace/std/objectobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/objectobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/objecttype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/objecttype.py pypy/branch/dist-2.4.1/pypy/objspace/std/register_all.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/register_all.py pypy/branch/dist-2.4.1/pypy/objspace/std/sliceobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/sliceobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/slicetype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/slicetype.py pypy/branch/dist-2.4.1/pypy/objspace/std/stdtypedef.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/stdtypedef.py pypy/branch/dist-2.4.1/pypy/objspace/std/strutil.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/strutil.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/__init__.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/__init__.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/autopath.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/autopath.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/broken_test_floatobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/broken_test_floatobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/broken_test_template.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/broken_test_template.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_boolobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_boolobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_dictobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_dictobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_dictproxy.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_dictproxy.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_fake.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_fake.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_floatobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_floatobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_instmethobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_instmethobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_intobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_intobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_iterobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_iterobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_listobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_listobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_listsort.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_listsort.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_longobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_longobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_multimethod.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_multimethod.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_noneobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_noneobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_obj.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_obj.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_operation.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_operation.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_sliceobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_sliceobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stdobjspace.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_stdobjspace.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_stringformat.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_stringformat.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_strutil.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_strutil.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_tupleobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_tupleobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_typeobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_typeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/test/test_userobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/test/test_userobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/tupleobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/tupleobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/tupletype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/tupletype.py pypy/branch/dist-2.4.1/pypy/objspace/std/typeobject.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/typeobject.py pypy/branch/dist-2.4.1/pypy/objspace/std/typetype.py - copied unchanged from r14327, pypy/dist/pypy/objspace/std/typetype.py pypy/branch/dist-2.4.1/pypy/objspace/test/ - copied from r14327, pypy/dist/pypy/objspace/test/ pypy/branch/dist-2.4.1/pypy/objspace/thunk.py - copied unchanged from r14327, pypy/dist/pypy/objspace/thunk.py pypy/branch/dist-2.4.1/pypy/objspace/trace.py - copied unchanged from r14327, pypy/dist/pypy/objspace/trace.py pypy/branch/dist-2.4.1/pypy/rpython/ - copied from r14327, pypy/dist/pypy/rpython/ pypy/branch/dist-2.4.1/pypy/test_all.py - copied unchanged from r14327, pypy/dist/pypy/test_all.py pypy/branch/dist-2.4.1/pypy/tool/__init__.py - copied unchanged from r14327, pypy/dist/pypy/tool/__init__.py pypy/branch/dist-2.4.1/pypy/tool/alarm.py - copied unchanged from r14327, pypy/dist/pypy/tool/alarm.py pypy/branch/dist-2.4.1/pypy/tool/ansi_print.py - copied unchanged from r14327, pypy/dist/pypy/tool/ansi_print.py pypy/branch/dist-2.4.1/pypy/tool/asterisk.py - copied unchanged from r14327, pypy/dist/pypy/tool/asterisk.py pypy/branch/dist-2.4.1/pypy/tool/autopath.py - copied unchanged from r14327, pypy/dist/pypy/tool/autopath.py pypy/branch/dist-2.4.1/pypy/tool/cache.py - copied unchanged from r14327, pypy/dist/pypy/tool/cache.py pypy/branch/dist-2.4.1/pypy/tool/fixeol - copied unchanged from r14327, pypy/dist/pypy/tool/fixeol pypy/branch/dist-2.4.1/pypy/tool/import_graph.py - copied unchanged from r14327, pypy/dist/pypy/tool/import_graph.py pypy/branch/dist-2.4.1/pypy/tool/opcode.py - copied unchanged from r14327, pypy/dist/pypy/tool/opcode.py pypy/branch/dist-2.4.1/pypy/tool/optik.py - copied unchanged from r14327, pypy/dist/pypy/tool/optik.py pypy/branch/dist-2.4.1/pypy/tool/pydis.py - copied unchanged from r14327, pypy/dist/pypy/tool/pydis.py pypy/branch/dist-2.4.1/pypy/tool/pypyrev.py - copied unchanged from r14327, pypy/dist/pypy/tool/pypyrev.py pypy/branch/dist-2.4.1/pypy/tool/pytest/__init__.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/__init__.py pypy/branch/dist-2.4.1/pypy/tool/pytest/appsupport.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/appsupport.py pypy/branch/dist-2.4.1/pypy/tool/pytest/autopath.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/autopath.py pypy/branch/dist-2.4.1/pypy/tool/pytest/genreportdata.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/genreportdata.py pypy/branch/dist-2.4.1/pypy/tool/pytest/htmlreport.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/htmlreport.py pypy/branch/dist-2.4.1/pypy/tool/pytest/overview.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/overview.py pypy/branch/dist-2.4.1/pypy/tool/pytest/pypy_test_failure_demo.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/pypy_test_failure_demo.py pypy/branch/dist-2.4.1/pypy/tool/pytest/regrverbose.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/regrverbose.py pypy/branch/dist-2.4.1/pypy/tool/pytest/result.py - copied unchanged from r14327, pypy/dist/pypy/tool/pytest/result.py pypy/branch/dist-2.4.1/pypy/tool/pytest/test/ - copied from r14327, pypy/dist/pypy/tool/pytest/test/ pypy/branch/dist-2.4.1/pypy/tool/sourcetools.py - copied unchanged from r14327, pypy/dist/pypy/tool/sourcetools.py pypy/branch/dist-2.4.1/pypy/tool/tb_server/ - copied from r14327, pypy/dist/pypy/tool/tb_server/ pypy/branch/dist-2.4.1/pypy/tool/test/ - copied from r14327, pypy/dist/pypy/tool/test/ pypy/branch/dist-2.4.1/pypy/tool/tls.py - copied unchanged from r14327, pypy/dist/pypy/tool/tls.py pypy/branch/dist-2.4.1/pypy/tool/traceconfig.py - copied unchanged from r14327, pypy/dist/pypy/tool/traceconfig.py pypy/branch/dist-2.4.1/pypy/tool/traceop.py - copied unchanged from r14327, pypy/dist/pypy/tool/traceop.py pypy/branch/dist-2.4.1/pypy/tool/udir.py - copied unchanged from r14327, pypy/dist/pypy/tool/udir.py pypy/branch/dist-2.4.1/pypy/tool/uid.py - copied unchanged from r14327, pypy/dist/pypy/tool/uid.py pypy/branch/dist-2.4.1/pypy/tool/unionfind.py - copied unchanged from r14327, pypy/dist/pypy/tool/unionfind.py pypy/branch/dist-2.4.1/pypy/translator/ - copied from r14327, pypy/dist/pypy/translator/ Log: Merging the trunk into the branch, step 2: re-adding the files and directories that have not been modified in the branch. From arigo at codespeak.net Wed Jul 6 14:42:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 14:42:39 +0200 (CEST) Subject: [pypy-svn] r14330 - in pypy: branch/dist-2.4.1 dist Message-ID: <20050706124239.89DA627B44@code1.codespeak.net> Author: arigo Date: Wed Jul 6 14:42:39 2005 New Revision: 14330 Added: pypy/dist/ - copied from r14329, pypy/branch/dist-2.4.1/ Removed: pypy/branch/dist-2.4.1/ Log: Moving the branch as the trunk, last step. From arigo at codespeak.net Wed Jul 6 14:56:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 14:56:09 +0200 (CEST) Subject: [pypy-svn] r14331 - in pypy/dist/lib-python: 2.3.4 attic modified-2.3.4 Message-ID: <20050706125609.944AA27B44@code1.codespeak.net> Author: arigo Date: Wed Jul 6 14:56:08 2005 New Revision: 14331 Removed: pypy/dist/lib-python/2.3.4/ pypy/dist/lib-python/attic/ pypy/dist/lib-python/modified-2.3.4/ Log: Removed the 2.3.4 directories for now. From hpk at codespeak.net Wed Jul 6 15:09:31 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 6 Jul 2005 15:09:31 +0200 (CEST) Subject: [pypy-svn] r14332 - pypy/dist/pypy/rpython Message-ID: <20050706130931.C98A627B47@code1.codespeak.net> Author: hpk Date: Wed Jul 6 15:09:31 2005 New Revision: 14332 Modified: pypy/dist/pypy/rpython/rtyper.py Log: remember dynamically generated code to have better tracebacks Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jul 6 15:09:31 2005 @@ -308,19 +308,19 @@ def _registeroperations(loc): # All unary operations for opname in annmodel.UNARY_OPERATIONS: - exec """ -def translate_op_%s(self, hop): - r_arg1 = hop.args_r[0] - return r_arg1.rtype_%s(hop) -""" % (opname, opname) in globals(), loc + exec py.code.compile(""" + def translate_op_%s(self, hop): + r_arg1 = hop.args_r[0] + return r_arg1.rtype_%s(hop) + """ % (opname, opname)) in globals(), loc # All binary operations for opname in annmodel.BINARY_OPERATIONS: - exec """ -def translate_op_%s(self, hop): - r_arg1 = hop.args_r[0] - r_arg2 = hop.args_r[1] - return pair(r_arg1, r_arg2).rtype_%s(hop) -""" % (opname, opname) in globals(), loc + exec py.code.compile(""" + def translate_op_%s(self, hop): + r_arg1 = hop.args_r[0] + r_arg2 = hop.args_r[1] + return pair(r_arg1, r_arg2).rtype_%s(hop) + """ % (opname, opname)) in globals(), loc _registeroperations(locals()) del _registeroperations From hpk at codespeak.net Wed Jul 6 15:22:45 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 6 Jul 2005 15:22:45 +0200 (CEST) Subject: [pypy-svn] r14333 - in pypy/dist/pypy/rpython: . test Message-ID: <20050706132245.A0A7527B40@code1.codespeak.net> Author: hpk Date: Wed Jul 6 15:22:43 2005 New Revision: 14333 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: (arre, hpk, thanks samuele) implemented issubtype (which you get from using issubclass) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jul 6 15:22:43 2005 @@ -281,6 +281,10 @@ raise MissingRTypeAttribute(attr) self.rbase.setclsfield(vcls, attr, vvalue, llops) + def rtype_issubtype(self, hop): + class_repr = get_type_repr(self.rtyper) + v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr) + return hop.gendirectcall(ll_issubclass, v_cls1, v_cls2) def get_type_repr(rtyper): return getclassrepr(rtyper, None) Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Wed Jul 6 15:22:43 2005 @@ -144,3 +144,27 @@ return a.meth() + b.meth() res = interpret(f, []) assert res == 246 + +def test_issubclass_type(): + class A: + pass + class B(A): + pass + def f(i): + if i == 0: + c1 = A() + else: + c1 = B() + return issubclass(type(c1), B) + assert interpret(f, [0], view=False, viewbefore=False) == False + assert interpret(f, [1], view=False, viewbefore=False) == True + + def g(i): + if i == 0: + c1 = A() + else: + c1 = B() + return issubclass(type(c1), A) + assert interpret(g, [0], view=False, viewbefore=False) == True + assert interpret(g, [1], view=False, viewbefore=False) == True + From hpk at codespeak.net Wed Jul 6 15:24:06 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 6 Jul 2005 15:24:06 +0200 (CEST) Subject: [pypy-svn] r14334 - pypy/extradoc/sprintinfo Message-ID: <20050706132406.112B727B4B@code1.codespeak.net> Author: hpk Date: Wed Jul 6 15:24:05 2005 New Revision: 14334 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: updates Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Wed Jul 6 15:24:05 2005 @@ -65,7 +65,7 @@ -------- DONE: (arre, bert) implement int(string) and int(string, 16) - rclass: (easy) issubtype (use issubclass to generate + DONE: rclass: (easy) issubtype (use issubclass to generate an example that has issubtype in the annotated flow graph) (strange)(delegating to backend?) sys.getrefcount @@ -104,11 +104,11 @@ experiment in a branch with using Python 2.4 semantics and the standard library -* (MOSTLY DONE) use lib-python/2.4.1 instead of 2.3.4, review all +* (DONE) use lib-python/2.4.1 instead of 2.3.4, review all modified tests and library modules (good progress, we still need to review ca. 1 modified test files) -* Merge 2.4.1 branch (blocked by parser/compiler being able +* (DONE) Merge 2.4.1 branch (blocked by parser/compiler being able to process 2.4.1 files on top of CPython 2.3.4, Armin looks into that) From tismer at codespeak.net Wed Jul 6 15:24:37 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 15:24:37 +0200 (CEST) Subject: [pypy-svn] r14335 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050706132437.1F26A27B53@code1.codespeak.net> Author: tismer Date: Wed Jul 6 15:24:35 2005 New Revision: 14335 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: moving towards an optionally CPython compatible implementation. There is still a problem with division. CPython seems to abuse a bit in some cases. I will try to prove that CPython actually produces unnormalized numbers, i.e. a digits holds one bit more than it should after normalization. Going to replace half-word access by a subclass of r_uint which has less bits. Things must become more configurable, since I need to do exact matching against CPython. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 6 15:24:35 2005 @@ -8,20 +8,26 @@ import math -SHORT_BIT = int(LONG_BIT // 2) -SHORT_MASK = int((1 << SHORT_BIT) - 1) +# the following describe a plain digit +SHIFT = int(LONG_BIT // 2) #- 1 +MASK = int((1 << SHIFT) - 1) +# masks for normal signed integer SIGN_BIT = LONG_BIT-1 SIGN_MASK = r_uint(1) << SIGN_BIT NONSIGN_MASK = ~SIGN_MASK +# masks for half-word access +SHORT_BIT = LONG_BIT // 2 +SHORT_MASK = int((1 << SHORT_BIT) - 1) + # XXX some operations below return one of their input arguments # without checking that it's really of type long (and not a subclass). class W_LongObject(W_Object): """This is a reimplementation of longs using a list of r_uints.""" - #All functions that still rely on the underlying Python's longs are marked - #with YYYYYY + # All functions that still rely on the underlying Python's longs are marked + # with YYYYYY from pypy.objspace.std.longtype import long_typedef as typedef def __init__(w_self, space, digits, sign=0): @@ -64,6 +70,7 @@ def _setshort(self, index, short): a = self.digits[index // 2] assert isinstance(short, r_uint) + # note that this is possibly one bit more than a digit assert short & SHORT_MASK == short if index % 2 == 0: self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short @@ -71,8 +78,6 @@ self.digits[index // 2] = (a & SHORT_MASK) + (short << SHORT_BIT) - - registerimplementation(W_LongObject) # bool-to-long @@ -149,12 +154,17 @@ def uint_w__Long(space, w_value): if w_value.sign == -1: - raise OperationError(space.w_ValueError, - space.wrap("cannot convert negative integer to unsigned")) - if len(w_value.digits) == 1: - return w_value.digits[0] - raise OperationError(space.w_OverflowError, - space.wrap("long int too large to convert to unsigned int")) + raise OperationError(space.w_ValueError, space.wrap( + "cannot convert negative integer to unsigned int")) + x = r_uint(0) + i = len(w_value.digits) * 2 - 1 + while i >= 0: + prev = x + x = (x << SHIFT) + v._getshort(i) + if (x >> SHIFT) != prev: + raise OperationError(space.w_OverflowError, space.wrap( + "long int too large to convert to unsigned int")) + return x def repr__Long(space, w_long): return space.wrap(_format(w_long, 10, True)) @@ -221,56 +231,56 @@ def add__Long_Long(space, w_long1, w_long2): if w_long1.sign < 0: if w_long2.sign < 0: - result = _x_add(w_long1, w_long2, space) + result = _x_add(w_long1, w_long2) if result.sign != 0: result.sign = -result.sign else: - result = _x_sub(w_long2, w_long1, space) + result = _x_sub(w_long2, w_long1) else: if w_long2.sign < 0: - result = _x_sub(w_long1, w_long2, space) + result = _x_sub(w_long1, w_long2) else: - result = _x_add(w_long1, w_long2, space) + result = _x_add(w_long1, w_long2) result._normalize() return result def sub__Long_Long(space, w_long1, w_long2): if w_long1.sign < 0: if w_long2.sign < 0: - result = _x_sub(w_long1, w_long2, space) + result = _x_sub(w_long1, w_long2) else: - result = _x_add(w_long1, w_long2, space) + result = _x_add(w_long1, w_long2) result.sign = -result.sign else: if w_long2.sign < 0: - result = _x_add(w_long1, w_long2, space) + result = _x_add(w_long1, w_long2) else: - result = _x_sub(w_long1, w_long2, space) + result = _x_sub(w_long1, w_long2) result._normalize() return result def mul__Long_Long(space, w_long1, w_long2): - result = _x_mul(w_long1, w_long2, space) + result = _x_mul(w_long1, w_long2) result.sign = w_long1.sign * w_long2.sign return result def truediv__Long_Long(space, w_long1, w_long2): - div = _long_true_divide(space, w_long1, w_long2) + div = _long_true_divide(w_long1, w_long2) return space.newfloat(div) def floordiv__Long_Long(space, w_long1, w_long2): - div, mod = _l_divmod(space, w_long1, w_long2) + div, mod = _l_divmod(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(space, w_long1, w_long2) + div, mod = _l_divmod(w_long1, w_long2) return mod def divmod__Long_Long(space, w_long1, w_long2): - div, mod = _l_divmod(space, w_long1, w_long2) + div, mod = _l_divmod(w_long1, w_long2) return space.newtuple([div, mod]) # helper for pow() #YYYYYY: still needs longval if second argument is negative @@ -494,7 +504,7 @@ StdObjSpace.MM.pow.register(pow_ovr__Int_Int_Long, W_IntObject, W_IntObject, W_LongObject, order=1) -#Helper Functions +# Helper Functions def args_from_long(l): #YYYYYY if l < 0: sign = -1 @@ -513,79 +523,84 @@ return digits, sign -#Add the absolute values of two longs -def _x_add(a, b, space): - size_a = len(a.digits) - size_b = len(b.digits) +def _x_add(a, b): + """ Add the absolute values of two long integers. """ + size_a = len(a.digits) * 2 + size_b = len(b.digits) * 2 + + # Ensure a is the larger of the two: if size_a < size_b: a, b = b, a size_a, size_b = size_b, size_a - z = W_LongObject(space, [r_uint(0)] * (len(a.digits) + 1), 1) + z = W_LongObject(a.space, [r_uint(0)] * (len(a.digits) + 1), 1) i = 0 carry = r_uint(0) while i < size_b: - ad = a.digits[i] - s = ad + b.digits[i] - res = s + carry - carry = r_uint(res < s) + r_uint(s < ad) - z.digits[i] = res + carry += a._getshort(i) + b._getshort(i) + z._setshort(i, carry & MASK) + carry >>= SHIFT i += 1 while i < size_a: - s = a.digits[i] - carry = s + carry - z.digits[i] = carry - carry = r_uint(s > carry) + carry += a._getshort(i) + z._setshort(i, carry & MASK) + carry >>= SHIFT i += 1 - z.digits[i] = carry + z._setshort(i, carry) + z._normalize() return z - -# Substract the absolute values of two longs -def _x_sub(a, b, space): - size_a = len(a.digits) - size_b = len(b.digits) +def _x_sub(a, b): + """ Subtract the absolute values of two integers. """ + size_a = len(a.digits) * 2 + size_b = len(b.digits) * 2 sign = 1 - i = 0 + borrow = 0 + + # Ensure a is the larger of the two: if size_a < size_b: sign = -1 - a, b = b, a + a,b=b, a size_a, size_b = size_b, size_a elif size_a == size_b: - i = size_a - 1; - while i > 0 and a.digits[i] == b.digits[i]: + # Find highest digit where a and b differ: + i = size_a - 1 + while i >= 0 and a._getshort(i) == b._getshort(i): i -= 1 - if (i == -1): - return W_LongObject(space, [r_uint(0)]) - if a.digits[i] < b.digits[i]: + if i < 0: + return W_LongObject(a.space, [r_uint(0)], 0) + if a._getshort(i) < b._getshort(i): sign = -1 a, b = b, a - size_a = size_b = i + 1 - z = W_LongObject(space, [r_uint(0)] * len(a.digits), 1) + size_a = size_b = i+1 + digitpairs = (size_a + 1) // 2 + z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) i = 0 - borrow = r_uint(0) while i < size_b: - ad = a.digits[i] - s = ad - b.digits[i] - res = s - borrow - z.digits[i] = res - borrow = r_uint(res > s) + r_uint(s > ad) + # The following assumes unsigned arithmetic + # works modulo 2**N for some N>SHIFT. + borrow = a._getshort(i) - b._getshort(i) - borrow + z._setshort(i, borrow & MASK) + borrow >>= SHIFT + borrow &= 1 # Keep only one sign bit i += 1 while i < size_a: - ad = a.digits[i] - res = ad - borrow - borrow = r_uint(res > ad) - z.digits[i] = res + borrow = a._getshort(i) - borrow + z._setshort(i, borrow & MASK) + borrow >>= SHIFT + borrow &= 1 # Keep only one sign bit i += 1 assert borrow == 0 - z.sign = sign + if sign < 0: + z.sign = -1 + z._normalize() return z #Multiply the absolute values of two longs -def _x_mul(a, b, space): +def _x_mul(a, b): size_a = len(a.digits) * 2 size_b = len(b.digits) * 2 - z = W_LongObject(space, [r_uint(0)] * ((size_a + size_b) // 2), 1) + z = W_LongObject(a.space, [r_uint(0)] * ((size_a + size_b) // 2), 1) i = 0 while i < size_a: carry = r_uint(0) @@ -593,14 +608,14 @@ j = 0 while j < size_b: carry += z._getshort(i + j) + b._getshort(j) * f - z._setshort(i + j, carry & SHORT_MASK) - carry = carry >> SHORT_BIT + z._setshort(i + j, carry & MASK) + carry = carry >> SHIFT j += 1 while carry != 0: assert i + j < size_a + size_b carry += z._getshort(i + j) - z._setshort(i + j, carry & SHORT_MASK) - carry = carry >> SHORT_BIT + z._setshort(i + j, carry & MASK) + carry = carry >> SHIFT j += 1 i += 1 z._normalize() @@ -612,44 +627,44 @@ in pout, and returning the remainder. It's OK for pin == pout on entry. """ rem = r_uint(0) - assert n > 0 and n <= SHORT_MASK + assert n > 0 and n <= MASK if not size: size = len(pin.digits) * 2 size -= 1 while size >= 0: - rem = (rem << SHORT_BIT) + pin._getshort(size) + rem = (rem << SHIFT) + pin._getshort(size) hi = rem // n pout._setshort(size, hi) rem -= hi * n size -= 1 return rem -def _divrem1(space, a, n): +def _divrem1(a, n): """ Divide a long integer by a digit, returning both the quotient and the remainder as a tuple. The sign of a is ignored; n should not be zero. """ - assert n > 0 and n <= SHORT_MASK + assert n > 0 and n <= MASK size = len(a.digits) - z = W_LongObject(space, [r_uint(0)] * size, 1) + z = W_LongObject(a.space, [r_uint(0)] * size, 1) rem = _inplace_divrem1(z, a, n) z._normalize() return z, rem -def _muladd1(space, a, n, extra): +def _muladd1(a, n, extra): """Multiply by a single digit and add a single digit, ignoring the sign. """ digitpairs = len(a.digits) size_a = digitpairs * 2 if a._getshort(size_a-1) == 0: size_a -= 1 - z = W_LongObject(space, [r_uint(0)] * (digitpairs+1), 1) + z = W_LongObject(a.space, [r_uint(0)] * (digitpairs+1), 1) carry = extra for i in range(size_a): carry += a._getshort(i) * n - z._setshort(i, carry & SHORT_MASK) - carry >>= SHORT_BIT + z._setshort(i, carry & MASK) + carry >>= SHIFT i += 1 z._setshort(i, carry) z._normalize() @@ -711,7 +726,7 @@ def __irshift__(self, n): self.value >>= n if self.sign: - self.value += LONG_MASK << (LONG_BIT - n) + self.value += r_uint(LONG_MASK) << (LONG_BIT - n) return self def __rshift__(self, n): @@ -737,15 +752,15 @@ other = r_suint(other) return self.sign == other.sign and self.value == other.value -def _x_divrem(space, v1, w1): +def _x_divrem(v1, w1): size_w = len(w1.digits) * 2 # hack for the moment: # find where w1 is really nonzero if w1._getshort(size_w-1) == 0: size_w -= 1 - d = (SHORT_MASK+1) // (w1._getshort(size_w-1) + 1) - v = _muladd1(space, v1, d, r_uint(0)) - w = _muladd1(space, w1, d, r_uint(0)) + d = (MASK+1) // (w1._getshort(size_w-1) + 1) + v = _muladd1(v1, d, r_uint(0)) + w = _muladd1(w1, d, r_uint(0)) size_v = len(v.digits) * 2 if v._getshort(size_v-1) == 0: size_v -= 1 @@ -756,7 +771,7 @@ size_a = size_v - size_w + 1 digitpairs = (size_a + 1) // 2 - a = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + a = W_LongObject(v.space, [r_uint(0)] * digitpairs, 1) j = size_v k = size_a - 1 @@ -768,29 +783,32 @@ carry = r_suint(0) # note: this must hold two digits and a sign! if vj == w._getshort(size_w-1): - q = r_uint(SHORT_MASK) + q = r_uint(MASK) else: - q = ((vj << SHORT_BIT) + v._getshort(j-1)) // w._getshort(size_w-1) + q = ((vj << SHIFT) + v._getshort(j-1)) // w._getshort(size_w-1) # notabene! # this check needs a signed two digits result # or we get an overflow. while (w._getshort(size_w-2) * q > (( - r_suint(vj << SHORT_BIT) # this one dominates + r_suint(vj << SHIFT) # this one dominates + v._getshort(j-1) - - q * w._getshort(size_w-1) - ) << SHORT_BIT) + - long(q) * long(w._getshort(size_w-1)) + ) << SHIFT) + v._getshort(j-2)): q -= 1 i = 0 while i < size_w and i+k < size_v: z = w._getshort(i) * q - zz = z >> SHORT_BIT - carry += v._getshort(i+k) + (zz << SHORT_BIT) + zz = z >> SHIFT + carry += v._getshort(i+k) + (zz << SHIFT) carry -= z - v._setshort(i+k, r_uint(carry.value & SHORT_MASK)) - carry >>= SHORT_BIT + if hasattr(carry, 'value'): + v._setshort(i+k, r_uint(carry.value & MASK)) + else: + v._setshort(i+k, r_uint(carry & MASK)) + carry >>= SHIFT carry -= zz i += 1 @@ -799,27 +817,27 @@ v._setshort(i+k, r_uint(0)) if carry == 0: - a._setshort(k, q & SHORT_MASK) + a._setshort(k, q & MASK) else: - assert carry == -1 - a._setshort(k, (q-1) & SHORT_MASK) + ##!!assert carry == -1 + a._setshort(k, (q-1) & MASK) carry = r_suint(0) i = 0 while i < size_w and i+k < size_v: carry += v._getshort(i+k) + w._getshort(i) - v._setshort(i+k, r_uint(carry.value) & SHORT_MASK) - carry >>= SHORT_BIT + v._setshort(i+k, r_uint(carry.value) & MASK) + carry >>= SHIFT i += 1 j -= 1 k -= 1 a._normalize() - rem, _ = _divrem1(space, v, d) + rem, _ = _divrem1(v, d) return a, rem -def _divrem(space, a, b): +def _divrem(a, b): """ Long division with remainder, top-level routine """ size_a = len(a.digits) * 2 size_b = len(b.digits) * 2 @@ -829,21 +847,21 @@ size_b -= 1 if b.sign == 0: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division or modulo by zero")) + raise OperationError(a.space.w_ZeroDivisionError, + a.space.wrap("long division or modulo by zero")) if (size_a < size_b or (size_a == size_b and a._getshort(size_a-1) < b._getshort(size_b-1))): # |a| < |b| - z = W_LongObject(space, [r_uint(0)], 0) + z = W_LongObject(a.space, [r_uint(0)], 0) rem = a return z, rem if size_b == 1: - z, urem = _divrem1(space, a, b._getshort(0)) - rem = W_LongObject(space, [urem], int(urem != 0)) + z, urem = _divrem1(a, b._getshort(0)) + rem = W_LongObject(a.space, [urem], int(urem != 0)) else: - z, rem = _x_divrem(space, a, b) + z, rem = _x_divrem(a, b) # Set the signs. # The quotient z has the sign of a*b; # the remainder r has the sign of a, @@ -869,7 +887,7 @@ least one round bit to stand in for the ignored least-significant bits. """ NBITS_WANTED = 57 - multiplier = float(1 << SHORT_BIT) + multiplier = float(1 << SHIFT) if v.sign == 0: return 0.0, 0 i = len(v.digits) * 2 - 1 @@ -882,7 +900,7 @@ while i > 0 and nbitsneeded > 0: i -= 1 x = x * multiplier + float(v._getshort(i)) - nbitsneeded -= SHORT_BIT + nbitsneeded -= SHIFT # There are i digits we didn't shift in. Pretending they're all # zeroes, the true value is x * 2**(i*SHIFT). exponent = i @@ -904,41 +922,42 @@ ## return x # note that math.ldexp checks for overflows, -# while the C ldexp is not guaranteed to. +# while the C ldexp is not guaranteed to do. +# XXX make sure that we don't ignore this! def _AsDouble(v): """ Get a C double from a long int object. """ x, e = _AsScaledDouble(v) - if e <= sys.maxint / SHORT_BIT: - x = math.ldexp(x, e * SHORT_BIT) + if e <= sys.maxint / SHIFT: + x = math.ldexp(x, e * SHIFT) #if not isinf(x): # this is checked by math.ldexp return x - raise OverflowError# sorry, "long int too large to convert to float" + raise OverflowError # can't say "long int too large to convert to float" -def _long_true_divide(space, a, b): +def _long_true_divide(a, b): try: ad, aexp = _AsScaledDouble(a) bd, bexp = _AsScaledDouble(b) if bd == 0.0: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division or modulo by zero")) + raise OperationError(a.space.w_ZeroDivisionError, + a.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 aexp -= bexp - if aexp > sys.maxint / SHORT_BIT: + if aexp > sys.maxint / SHIFT: raise OverflowError - elif aexp < -(sys.maxint / SHORT_BIT): + elif aexp < -(sys.maxint / SHIFT): return 0.0 # underflow to 0 - ad = math.ldexp(ad, aexp * SHORT_BIT) - #if isinf(ad): # ignore underflow to 0.0 - # raise OverflowError + ad = math.ldexp(ad, aexp * SHIFT) + ##if isinf(ad): # ignore underflow to 0.0 + ## raise OverflowError # math.ldexp checks and raises return ad except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("long/long too large for a float")) + raise OperationError(a.space.w_OverflowError, + a.space.wrap("long/long too large for a float")) def _FromDouble(space, dval): @@ -953,20 +972,20 @@ frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 if expo <= 0: return W_LongObject(space, [r_uint(0)], 0) - ndig = (expo-1) // SHORT_BIT + 1 # Number of 'digits' in result + ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result digitpairs = (ndig + 1) // 2 v = W_LongObject(space, [r_uint(0)] * digitpairs, 1) - frac = math.ldexp(frac, (expo-1) % SHORT_BIT + 1) + frac = math.ldexp(frac, (expo-1) % SHIFT + 1) for i in range(ndig-1, -1, -1): bits = int(frac) v._setshort(i, r_uint(bits)) frac -= float(bits) - frac = math.ldexp(frac, SHORT_BIT) + frac = math.ldexp(frac, SHIFT) if neg: v.sign = -1 return v -def _l_divmod(space, v, w): +def _l_divmod(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). @@ -983,11 +1002,11 @@ have different signs. We then subtract one from the 'div' part of the outcome to keep the invariant intact. """ - div, mod = _divrem(space, v, w) + div, mod = _divrem(v, w) if mod.sign * w.sign == -1: - mod = add__Long_Long(space, mod, w) - one = W_LongObject(space, [r_uint(1)], 1) - div = sub__Long_Long(space, div, one) + mod = add__Long_Long(v.space, mod, w) + one = W_LongObject(v.space, [r_uint(1)], 1) + div = sub__Long_Long(v.space, div, one) return div, mod @@ -1037,7 +1056,7 @@ for i in range(size_a): accum |= a._getshort(i) << accumbits - accumbits += SHORT_BIT + accumbits += SHIFT assert accumbits >= basebits while 1: cdigit = accum & (base - 1) @@ -1062,12 +1081,12 @@ # fits in a digit. size = size_a pin = a # just for similarity to C source which uses the array - # powbasw <- largest power of base that fits in a digit. + # powbase <- largest power of base that fits in a digit. powbase = base # powbase == base ** power power = 1 while 1: newpow = powbase * r_uint(base) - if newpow >> SHORT_BIT: # doesn't fit in a digit + if newpow >> SHIFT: # doesn't fit in a digit break powbase = newpow power += 1 @@ -1133,36 +1152,36 @@ return ''.join(s[p:]) -def _bitwise(a, op, n): # '&', '|', '^' - """ Bitwise and/xor/or operations """ +def _bitwise(a, op, b): # '&', '|', '^' + """ Bitwise and/or/xor operations """ if a.sign < 0: a = invert__Long(a.space, a) - maska = r_uint(SHORT_MASK) + maska = r_uint(MASK) else: maska = r_uint(0) if b.sign < 0: b = invert__Long(b.space, b) - maskb = r_uint(SHORT_MASK) + maskb = r_uint(MASK) else: maskb = r_uint(0) negz = 0 if op == '^': if maska != maskb: - maska ^= SHORT_MASK + maska ^= MASK negz = -1 elif op == '&': if maska and maskb: op = '|' - maska ^= SHORT_MASK - maskb ^= SHORT_MASK + maska ^= MASK + maskb ^= MASK negz = -1 elif op == '|': if maska or maskb: op = '&' - maska ^= SHORT_MASK - maskb ^= SHORT_MASK + maska ^= MASK + maskb ^= MASK negz = -1 # JRH: The original logic here was to allocate the result value (z) @@ -1177,6 +1196,7 @@ size_a = len(a.digits) * 2 if a._getshort(size_a - 1) == 0: size_a -= 1 + size_b = len(b.digits) * 2 if b._getshort(size_b - 1) == 0: size_b -= 1 if op == '&': @@ -1209,7 +1229,7 @@ elif op == '^': z._setshort(i, diga ^ digb) - z_normalize() + z._normalize() if negz == 0: return z - return invert__Long(z) + return invert__Long(z.space, z) 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 Wed Jul 6 15:24:35 2005 @@ -66,7 +66,7 @@ y = 3 f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) f2 = r_uint(y) - div, rem = lobj._divrem1(self.space, f1, f2) + div, rem = lobj._divrem1(f1, f2) assert (div.longval(), rem) == divmod(x, y) def test__muladd1(self): @@ -76,7 +76,7 @@ f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) f2 = r_uint(y) f3 = r_uint(z) - prod = lobj._muladd1(self.space, f1, f2, f3) + prod = lobj._muladd1(f1, f2, f3) assert prod.longval() == x * y + z def test__x_divrem(self): @@ -87,7 +87,7 @@ 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)) - div, rem = lobj._x_divrem(self.space, f1, f2) + div, rem = lobj._x_divrem(f1, f2) assert div.longval(), rem.longval() == divmod(x, y) def test__divrem(self): @@ -101,7 +101,7 @@ sy *= y f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(sx)) f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(sy)) - div, rem = lobj._x_divrem(self.space, f1, f2) + div, rem = lobj._x_divrem(f1, f2) assert div.longval(), rem.longval() == divmod(sx, sy) def test__AsDouble(self): @@ -317,11 +317,18 @@ assert y < r <= 0 for x in [-1L, 0L, 1L, 2L ** 100 - 1, -2L ** 100 - 1]: for y in [-105566530L, -1L, 1L, 1034522340L]: + continue print "checking division for %s, %s" % (x, y) check_division(x, y) # special case from python tests: + s1 = 33 + s2 = 2 x = 16565645174462751485571442763871865344588923363439663038777355323778298703228675004033774331442052275771343018700586987657790981527457655176938756028872904152013524821759375058141439 + x >>= s1*16 y = 10953035502453784575 + y >>= s2*16 + x = 0x3FE0003FFFFC0001FFFL + y = 0x9800FFC1L print "special case" check_division(x, y) raises(ZeroDivisionError, "x // 0L") @@ -331,3 +338,12 @@ assert str(12345678901234567890) == '12345678901234567890' assert hex(0x1234567890ABCDEFL) == '0x1234567890ABCDEFL' assert oct(01234567012345670L) == '01234567012345670L' + + def test_bits(self): + assert 0xAAAAAAAAL | 0x55555555L == 0xFFFFFFFFL + assert 0xAAAAAAAAL & 0x55555555L == 0x00000000L + assert 0xAAAAAAAAL ^ 0x55555555L == 0xFFFFFFFFL + assert -0xAAAAAAAAL | 0x55555555L == -0xAAAAAAA9L + assert 0xAAAAAAAAL | 0x555555555L == 0x5FFFFFFFFL + assert 0xAAAAAAAAL & 0x555555555L == 0x000000000L + assert 0xAAAAAAAAL ^ 0x555555555L == 0x5FFFFFFFFL From pedronis at codespeak.net Wed Jul 6 16:04:36 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 6 Jul 2005 16:04:36 +0200 (CEST) Subject: [pypy-svn] r14336 - pypy/dist/pypy/annotation Message-ID: <20050706140436.D371727B4A@code1.codespeak.net> Author: pedronis Date: Wed Jul 6 16:04:33 2005 New Revision: 14336 Modified: pypy/dist/pypy/annotation/builtin.py Log: annotating some math.* ops. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Jul 6 16:04:33 2005 @@ -271,7 +271,8 @@ BUILTIN_ANALYZERS[math.fmod] = math_fmod BUILTIN_ANALYZERS[math.floor] = math_floor BUILTIN_ANALYZERS[math.exp] = math_any - +BUILTIN_ANALYZERS[math.ldexp] = math_any +BUILTIN_ANALYZERS[math.frexp] = math_any BUILTIN_ANALYZERS[sys.getrefcount] = count BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf import unicodedata From arigo at codespeak.net Wed Jul 6 16:05:02 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 16:05:02 +0200 (CEST) Subject: [pypy-svn] r14337 - in pypy/dist/pypy/rpython: . test Message-ID: <20050706140502.23E3327B4A@code1.codespeak.net> Author: arigo Date: Wed Jul 6 16:04:57 2005 New Revision: 14337 Added: pypy/dist/pypy/rpython/rspecialcase.py (contents, props changed) pypy/dist/pypy/rpython/test/test_rspecialcase.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: (arigo, quest) Handle special-casing of instantiate(). FunctionsPBCRepr only calls getsignature() if needed, to avoid spurious un-annotated flow graphs for such special-cased functions. test_llinterp takes a 'policy' argument. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jul 6 16:04:57 2005 @@ -543,10 +543,10 @@ # ____________________________________________________________ -def rtype_new_instance(cls, hop): - classdef = hop.rtyper.annotator.getuserclasses()[cls] - rinstance = getinstancerepr(hop.rtyper, classdef) - return rinstance.new_instance(hop.llops) +def rtype_new_instance(rtyper, cls, llops): + classdef = rtyper.annotator.getuserclasses()[cls] + rinstance = getinstancerepr(rtyper, classdef) + return rinstance.new_instance(llops) def instance_annotation_for_cls(rtyper, cls): try: Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 6 16:04:57 2005 @@ -278,52 +278,42 @@ def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.s_pbc = s_pbc - self.function_signatures = {} - for func in s_pbc.prebuiltinstances: - self.function_signatures[func] = getsignature(rtyper, func) - - if len(self.function_signatures) == 1: + self._function_signatures = None + if len(s_pbc.prebuiltinstances) == 1: # a single function self.lowleveltype = Void else: - signatures = self.function_signatures.values() + signatures = self.function_signatures().values() sig0 = signatures[0] for sig1 in signatures[1:]: assert typeOf(sig0[0]) == typeOf(sig1[0]) # XXX not implemented assert sig0[1:] == sig1[1:] # XXX not implemented self.lowleveltype = typeOf(sig0[0]) -## callfamilies = rtyper.annotator.getpbccallfamilies() -## try: -## _, _, callfamily = callfamilies[None, functions[0]] -## except KeyError: -## self.lowleveltype = Void # no call family found -## else: -## shapes = callfamily.patterns -## assert len(shapes) == 1, "XXX not implemented" -## shape, = shapes -## shape_cnt, shape_keys, shape_star, shape_stst = shape -## assert not shape_keys, "XXX not implemented" -## assert not shape_star, "XXX not implemented" -## assert not shape_stst, "XXX not implemented" + def function_signatures(self): + if self._function_signatures is None: + self._function_signatures = {} + for func in self.s_pbc.prebuiltinstances: + self._function_signatures[func] = getsignature(self.rtyper,func) + return self._function_signatures def convert_const(self, value): if isinstance(value, types.MethodType) and value.im_self is None: value = value.im_func # unbound method -> bare function - if value not in self.function_signatures: + if value not in self.function_signatures(): raise TyperError("%r not in %r" % (value, self.s_pbc.prebuiltinstances)) - f, rinputs, rresult = self.function_signatures[value] + f, rinputs, rresult = self.function_signatures()[value] return f def rtype_simple_call(self, hop): - f, rinputs, rresult = self.function_signatures.itervalues().next() + f, rinputs, rresult = self.function_signatures().itervalues().next() defaultclist = [] if len(rinputs) != hop.nb_args-1: # argument count mismatch assert not getattr(f._obj.graph, 'normalized_for_calls', False), ( "normalization bug") - assert len(self.function_signatures) == 1, "normalization bug too" - func, = self.function_signatures.keys() + assert len(self.function_signatures()) == 1, "normalization bug too" + func, = self.function_signatures().keys() defaults = func.func_defaults or () if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs): rinputs = list(rinputs) @@ -338,13 +328,13 @@ raise RTyperError("not enough arguments in function call") vlist = hop.inputargs(self, *rinputs) + defaultclist if self.lowleveltype == Void: - assert len(self.function_signatures) == 1 + assert len(self.function_signatures()) == 1 vlist[0] = hop.inputconst(typeOf(f), f) v = hop.genop('direct_call', vlist, resulttype = rresult) return hop.llops.convertvar(v, rresult, hop.r_result) def rtype_call_args(self, hop): - f, rinputs, rresult = self.function_signatures.itervalues().next() + f, rinputs, rresult = self.function_signatures().itervalues().next() # the function arguments may have been normalized by normalizecalls() # already if not f._obj.graph.normalized_for_calls: @@ -453,7 +443,7 @@ def rtype_simple_call(self, hop): klass = self.s_pbc.const - v_instance = rclass.rtype_new_instance(klass, hop) + v_instance = rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) try: initfunc = klass.__init__.im_func except AttributeError: Added: pypy/dist/pypy/rpython/rspecialcase.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rspecialcase.py Wed Jul 6 16:04:57 2005 @@ -0,0 +1,32 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.rpython import rclass + + +def rtype_call_specialcase(hop): + v_function = hop.args_v[0] + if not isinstance(v_function, Constant): + raise TyperError("call_specialcase on a variable function") + func = v_function.value + tag = func._annspecialcase_ + if not tag.startswith("override:"): + raise TyperError("call_specialcase only supports 'override:' functions") + tag = tag[9:] + try: + rtype_override_fn = globals()['rtype_override_' + tag] + except KeyError: + raise TyperError("call_specialcase: unknown tag override:" + tag) + hop2 = hop.copy() + hop2.r_s_popfirstarg() + return rtype_override_fn(hop2) + + +def rtype_override_instantiate(hop): + s_class = hop.args_s[0] + assert isinstance(s_class, annmodel.SomePBC) + if len(s_class.prebuiltinstances) != 1: + raise TyperError("instantiate() on a variable class") + + klass = s_class.const + return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jul 6 16:04:57 2005 @@ -351,6 +351,9 @@ def translate_op_call_memo(self, hop): return rpbc.rtype_call_memo(hop) + def translate_op_call_specialcase(self, hop): + return rspecialcase.rtype_call_specialcase(hop) + def missing_operation(self, hop): raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname) @@ -541,7 +544,7 @@ from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rslice from pypy.rpython import rlist, rstr, rtuple, rdict -from pypy.rpython import rclass, rbuiltin, rpbc +from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase from pypy.rpython import rptr RPythonTyper.fixednames = {} 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 Wed Jul 6 16:04:57 2005 @@ -27,19 +27,19 @@ if func(pyobjectptr(cls)).typeptr == klass: return cls -def timelog(prefix, call, *args): +def timelog(prefix, call, *args, **kwds): #import time #print prefix, "...", #start = time.time() - res = call(*args) + res = call(*args, **kwds) #elapsed = time.time() - start #print "%.2f secs" %(elapsed,) return res -def gengraph(func, argtypes=[], viewbefore=False): +def gengraph(func, argtypes=[], viewbefore=False, policy=None): t = Translator(func) - timelog("annotating", t.annotate, argtypes) + timelog("annotating", t.annotate, argtypes, policy=policy) if viewbefore: t.annotator.simplify() t.view() @@ -52,13 +52,13 @@ _lastinterpreted = [] _tcache = {} -def interpret(func, values, view=False, viewbefore=False): +def interpret(func, values, view=False, viewbefore=False, policy=None): key = (func,) + tuple([typeOf(x) for x in values]) try: (t, interp) = _tcache[key] except KeyError: t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) - for x in values], viewbefore) + for x in values], viewbefore, policy) interp = LLInterpreter(t.flowgraphs, typer) _tcache[key] = (t, interp) # keep the cache small Added: pypy/dist/pypy/rpython/test/test_rspecialcase.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Wed Jul 6 16:04:57 2005 @@ -0,0 +1,14 @@ +from pypy.rpython.lltype import * +from pypy.rpython.test.test_llinterp import interpret + +from pypy.translator.ann_override import PyPyAnnotatorPolicy +from pypy.interpreter.typedef import instantiate + + +def test_instantiate(): + class A: + pass + def f(): + return instantiate(A) + res = interpret(f, [], policy=PyPyAnnotatorPolicy()) + assert res.super.typeptr.name[0] == 'A' From tismer at codespeak.net Wed Jul 6 16:06:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 16:06:11 +0200 (CEST) Subject: [pypy-svn] r14338 - pypy/dist/pypy/objspace/std Message-ID: <20050706140611.8AB0B27B4A@code1.codespeak.net> Author: tismer Date: Wed Jul 6 16:06:10 2005 New Revision: 14338 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: smallish bugs Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 6 16:06:10 2005 @@ -160,10 +160,11 @@ i = len(w_value.digits) * 2 - 1 while i >= 0: prev = x - x = (x << SHIFT) + v._getshort(i) + x = (x << SHIFT) + w_value._getshort(i) if (x >> SHIFT) != prev: raise OperationError(space.w_OverflowError, space.wrap( "long int too large to convert to unsigned int")) + i -= 1 return x def repr__Long(space, w_long): @@ -661,11 +662,12 @@ size_a -= 1 z = W_LongObject(a.space, [r_uint(0)] * (digitpairs+1), 1) carry = extra - for i in range(size_a): + i = 0 + while i < size_a: carry += a._getshort(i) * n z._setshort(i, carry & MASK) carry >>= SHIFT - i += 1 + i += 1 z._setshort(i, carry) z._normalize() return z From tismer at codespeak.net Wed Jul 6 16:24:21 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 16:24:21 +0200 (CEST) Subject: [pypy-svn] r14339 - pypy/dist/pypy/rpython Message-ID: <20050706142421.7DAA227B40@code1.codespeak.net> Author: tismer Date: Wed Jul 6 16:24:20 2005 New Revision: 14339 Modified: pypy/dist/pypy/rpython/rarithmetic.py Log: new types r_ushort, r_ulong. old tests still pass, new one are under the way. Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Wed Jul 6 16:24:20 2005 @@ -15,6 +15,8 @@ ovfcheck_lshift << with oveflow checking catering to 2.3/2.4 differences about << +r_ushort like r_uint but half word size +r_ulong 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 @@ -188,13 +190,21 @@ def ovfcheck_lshift(a, b): return _local_ovfcheck(int(long(a) << b)) +def _widen(self, other, value): + """ + if one argument is int or long, the other type wins. + otherwise, produce the largest class to hold the result. + """ + return _typemap[ type(self), type(other) ](value) + class r_uint(long): """ fake unsigned integer implementation """ - _mask = LONG_MASK + MASK = LONG_MASK + BITS = LONG_BIT def __new__(klass, val): - return long.__new__(klass, val & klass._mask) + return long.__new__(klass, val & klass.MASK) def __int__(self): if self < LONG_TEST: @@ -205,50 +215,50 @@ def __add__(self, other): x = long(self) y = long(other) - return r_uint(x + y) + return _widen(self, other, x + y) __radd__ = __add__ def __sub__(self, other): x = long(self) y = long(other) - return r_uint(x - y) + return _widen(self, other, x - y) def __rsub__(self, other): y = long(self) x = long(other) - return r_uint(x - y) + return _widen(self, other, x - y) def __mul__(self, other): x = long(self) if not isinstance(other, (int, long)): return x * other y = long(other) - return r_uint(x * y) + return _widen(self, other, x * y) __rmul__ = __mul__ def __div__(self, other): x = long(self) y = long(other) - return r_uint(x // y) + return _widen(self, other, x // y) __floordiv__ = __div__ def __rdiv__(self, other): y = long(self) x = long(other) - return r_uint(x // y) + return _widen(self, other, x // y) __rfloordiv__ = __rdiv__ def __mod__(self, other): x = long(self) y = long(other) - return r_uint(x % y) + return _widen(self, other, x % y) def __rmod__(self, other): y = long(self) x = long(other) - return r_uint(x % y) + return _widen(self, other, x % y) def __divmod__(self, other): x = long(self) @@ -259,60 +269,88 @@ def __lshift__(self, n): x = long(self) y = long(n) - return r_uint(x << y) + return self.__class__(x << y) def __rlshift__(self, n): y = long(self) x = long(n) - return r_uint(x << y) + return _widen(self, n, x << y) def __rshift__(self, n): x = long(self) y = long(n) - return r_uint(x >> y) + return _widen(self, n, x >> y) def __rrshift__(self, n): y = long(self) x = long(n) - return r_uint(x >> y) + return _widen(self, n, x >> y) def __or__(self, other): x = long(self) y = long(other) - return r_uint(x | y) + return _widen(self, other, x | y) __ror__ = __or__ def __and__(self, other): x = long(self) y = long(other) - return r_uint(x & y) + return _widen(self, other, x & y) __rand__ = __and__ def __xor__(self, other): x = long(self) y = long(other) - return r_uint(x ^ y) + return _widen(self, other, x ^ y) __rxor__ = __xor__ def __neg__(self): x = long(self) - return r_uint(-x) + return self.__class__(-x) def __pos__(self): - return r_uint(self) + return self.__class__(self) def __invert__(self): x = long(self) - return r_uint(~x) + return self.__class__(~x) def __pow__(self, other, m=None): x = long(self) y = long(other) res = pow(x, y, m) - return r_uint(res) + return _widen(self, other, res) def __rpow__(self, other, m=None): y = long(self) x = long(other) res = pow(x, y, m) - return r_uint(res) + return _widen(self, other, res) + +class r_ushort(r_uint): + BITS = r_uint.BITS // 2 + MASK = int((1 << BITS) - 1) + +class r_ulong(r_uint): + BITS = r_uint.BITS * 2 + MASK = (1L << BITS) - 1 + +def setup_typemap(): + types = int, long, r_uint, r_ushort, r_ulong + 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 +_typemap = {} + +setup_typemap() +del setup_typemap From ericvrp at codespeak.net Wed Jul 6 16:27:16 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 16:27:16 +0200 (CEST) Subject: [pypy-svn] r14340 - pypy/dist/pypy/rpython Message-ID: <20050706142716.1FD7B27B60@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 16:27:15 2005 New Revision: 14340 Modified: pypy/dist/pypy/rpython/lltype.py Log: some cleaning up Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jul 6 16:27:15 2005 @@ -147,12 +147,11 @@ def _names_without_voids(self, at_root=True): - if at_root: #XXX debug stuff - log('_names_without_voids: ' + self._str_without_voids()) + #if at_root: #XXX debug stuff + # log('_names_without_voids: ' + self._str_without_voids()) names_without_voids = [name for name in self._names if self._flds[name] is not Void] - if names_without_voids != list(self._names): - log('_names_without_voids: removed Void(s) _names=%s, return=%s' % (str(list(self._names)), str(names_without_voids))) - #return self._names + #if names_without_voids != list(self._names): + # log('_names_without_voids: removed Void(s) _names=%s, return=%s' % (str(list(self._names)), str(names_without_voids))) return names_without_voids def _str_fields_without_voids(self): From ericvrp at codespeak.net Wed Jul 6 16:30:20 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 16:30:20 +0200 (CEST) Subject: [pypy-svn] r14341 - pypy/dist/pypy/rpython Message-ID: <20050706143020.8FBB327B60@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 16:30:19 2005 New Revision: 14341 Modified: pypy/dist/pypy/rpython/extfunctable.py Log: Added backend templates, so code-generation can actually be trivial in many cases. When type conversions are required this may not be the case. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Wed Jul 6 16:30:19 2005 @@ -5,28 +5,38 @@ import types class ExtFuncInfo: - def __init__(self, func, annotation, ll_function, ll_annotable): + def __init__(self, func, annotation, ll_function, ll_annotable, backend_functiontemplate): self.func = func self.annotation = annotation self.ll_function = ll_function self.ll_annotable = ll_annotable + self.backend_functiontemplate = backend_functiontemplate table = {} -def declare(func, annotation, ll_function, ll_annotable=True): +def declare(func, annotation, ll_function, ll_annotable=True, backend_functiontemplate=None): # annotation can be a function computing the annotation - # or a simple python type from which an annotation will be construcuted + # or a simple python type from which an annotation will be constructed global table if not isinstance(annotation, types.FunctionType): typ = annotation def annotation(*args_s): from pypy.annotation import bookkeeper return bookkeeper.getbookkeeper().valueoftype(typ) - table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable) + table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable, backend_functiontemplate) # low-level helpers representing the external functions def ll_os_open(fname, mode): return os.open(''.join(fname.chars), mode) +def ll_os_read(fd, n): + return os.read(fd, n) + +def ll_os_write(fd, astring): + return os.write(fd, astring) + +def ll_os_close(fd): + os.close(fd) + def ll_os_getcwd(): cwd = os.getcwd() from pypy.rpython import rstr @@ -39,6 +49,9 @@ return 999 # external function declarations -declare(os.open, int, ll_os_open, ll_annotable=False) -declare(os.getcwd, str, ll_os_getcwd, ll_annotable=False) -declare(os.dup, int, ll_os_dup, ll_annotable=True) +declare(os.open , int , ll_os_open , False, 'C:open' ) +declare(os.read , str , ll_os_read , False, 'C:read' ) +declare(os.write , int , ll_os_write , False, 'C:write' ) +declare(os.close , None, ll_os_close , False, 'C:close' ) +declare(os.getcwd, str , ll_os_getcwd, False, 'C:getcwd') +declare(os.dup , int , ll_os_dup , True , 'C:dup' ) From ericvrp at codespeak.net Wed Jul 6 16:35:45 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 16:35:45 +0200 (CEST) Subject: [pypy-svn] r14342 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050706143545.35F3027B61@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 16:35:43 2005 New Revision: 14342 Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/extfunctions.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Using transformation that renames external function calls when a one-to-one C equivalent is available. Cleaned op extfunction llvm code because we now handle that case (os.dup(...)) directly. Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Wed Jul 6 16:35:43 2005 @@ -37,7 +37,7 @@ if debug: print cmd cmdexec(cmd) -def make_module_from_llvm(llvmfile, pyxfile, optimize=False): +def make_module_from_llvm(llvmfile, pyxfile, optimize=True): include_dir = py.magic.autopath().dirpath() dirpath = llvmfile.dirpath() lastdir = path.local() Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Wed Jul 6 16:35:43 2005 @@ -120,6 +120,19 @@ if isinstance(const_or_var, Constant): ct = const_or_var.concretetype + while isinstance(ct, lltype.Ptr): + ct = ct.TO + + if isinstance(ct, lltype.FuncType): + if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'): + log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj))) + #XXX if it's has a one-to-one C function then we really want THAT declaration + else: + self.addpending(const_or_var, FuncNode(self, const_or_var)) + else: + value = const_or_var.value + while hasattr(value, "_obj"): + value = value._obj if isinstance(ct, lltype.Primitive): log.prepare(const_or_var, "(is primitive)") Modified: pypy/dist/pypy/translator/llvm2/extfunctions.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunctions.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunctions.py Wed Jul 6 16:35:43 2005 @@ -1,17 +1,7 @@ extdeclarations = """; External declarations - -declare int %dup(int) - ; End of external declarations """ extfunctions = """; External functions (will be inlined by LLVM) - -int %ll_os_dup__Signed(int %i) { -block0: - %i.0 = call int %dup(int %i) - ret int %i.0 -} - ; End of external functions """ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Wed Jul 6 16:35:43 2005 @@ -44,7 +44,7 @@ self.graph = value.graph remove_same_as(self.graph) remove_double_links(self.db._translator, self.graph) - + def __str__(self): return "" %(self.ref,) @@ -137,7 +137,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: - codewriter.comment(str(op)) + #codewriter.comment(str(op)) opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Wed Jul 6 16:35:43 2005 @@ -1,9 +1,6 @@ from os.path import exists use_boehm_gc = exists('/usr/lib/libgc.so') or exists('/usr/lib/libgc.a') -#XXXTmp -use_boehm_gc = False - import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database @@ -15,12 +12,14 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void +from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.extfunctions import extdeclarations, extfunctions function_count = {} def genllvm(translator): remove_void(translator) + rename_extfunc_calls(translator) func = translator.entrypoint db = Database(translator) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 6 16:35:43 2005 @@ -37,13 +37,27 @@ f = getattr(mod, function.func_name + "_wrapper") return mod, f -def test_external_function(): +def test_external_function_ll_os_dup(): import os def fn(): return os.dup(0) f = compile_function(fn, [], view=False) assert os.path.sameopenfile(f(), fn()) +def DONTtest_external_function_ll_os_getcmd(): + import os + def fn(): + return os.getcwd() + f = compile_function(fn, [], view=True) + assert os.getcwd() == 'bla' + +def DONTtest_external_function_ll_os_open(): + import os + def fn(): + return os.open(0) + f = compile_function(fn, [], view=False) + assert os.path.sameopenfile(f(), fn()) + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") From tismer at codespeak.net Wed Jul 6 16:44:13 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 16:44:13 +0200 (CEST) Subject: [pypy-svn] r14343 - in pypy/dist/pypy/rpython: . test Message-ID: <20050706144413.C846927B4A@code1.codespeak.net> Author: tismer Date: Wed Jul 6 16:44:12 2005 New Revision: 14343 Modified: pypy/dist/pypy/rpython/rarithmetic.py pypy/dist/pypy/rpython/test/test_rarithmetic.py Log: mixed types with coercion and limits test. Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Wed Jul 6 16:44:12 2005 @@ -329,7 +329,7 @@ class r_ushort(r_uint): BITS = r_uint.BITS // 2 - MASK = int((1 << BITS) - 1) + MASK = (1L << BITS) - 1 class r_ulong(r_uint): BITS = r_uint.BITS * 2 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 Wed Jul 6 16:44:12 2005 @@ -139,6 +139,27 @@ res = res & mask assert res == cmp +def test_mixed_types(): + types = [r_ushort, r_uint, r_ulong] + for left in types: + for right in types: + x = left(3) + right(5) + expected = max(types.index(left), types.index(right)) + assert types.index(type(x)) == expected + +def test_limits(): + mask = r_ushort.MASK + assert r_ushort(mask) == mask + assert r_ushort(mask+1) == 0 + mask = (mask << r_ushort.BITS) + mask + assert mask == r_uint.MASK + assert r_uint(mask == mask) + assert r_uint(mask+1) == 0 + mask = (mask << r_uint.BITS) + mask + assert mask == r_ulong.MASK + assert r_ulong(mask == mask) + assert r_ulong(mask+1) == 0 + def test_intmask(): assert intmask(1) == 1 assert intmask(sys.maxint) == sys.maxint From ericvrp at codespeak.net Wed Jul 6 16:44:31 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 16:44:31 +0200 (CEST) Subject: [pypy-svn] r14344 - pypy/dist/pypy/translator Message-ID: <20050706144431.423DA27B61@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 16:44:30 2005 New Revision: 14344 Modified: pypy/dist/pypy/translator/backendoptimization.py Log: transform extenral functions calls to their c equivalant Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Wed Jul 6 16:44:30 2005 @@ -5,6 +5,7 @@ from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph from pypy.tool.unionfind import UnionFind from pypy.rpython.lltype import Void +from pypy.rpython.extfunctable import table as extfunctable def remove_same_as(graph): """Remove all 'same_as' operations. @@ -57,6 +58,28 @@ for func, graph in translator.flowgraphs.iteritems(): traverse(visit, graph) +def rename_extfunc_calls(translator): + def visit(block): + if isinstance(block, Block): + for op in block.operations: + if op.opname != 'direct_call': + continue + functionref = op.args[0] + if not isinstance(functionref, Constant): + continue + _callable = functionref.value._obj._callable + for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? + if _callable is not extfuncinfo.ll_function or not extfuncinfo.backend_functiontemplate: + continue + language, functionname = extfuncinfo.backend_functiontemplate.split(':') + if language is 'C': + old_name = functionref.value._obj._name[:] + functionref.value._obj._name = functionname + #print 'rename_extfunc_calls: %s -> %s' % (old_name, functionref.value._obj._name) + break + for func, graph in translator.flowgraphs.iteritems(): + traverse(visit, graph) + def SSI_to_SSA(graph): """Rename the variables in a flow graph as much as possible without violating the SSA rule. 'SSI' means that each Variable in a flow graph is From ericvrp at codespeak.net Wed Jul 6 16:48:19 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 16:48:19 +0200 (CEST) Subject: [pypy-svn] r14345 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050706144819.AE89927B55@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 16:48:18 2005 New Revision: 14345 Modified: pypy/dist/pypy/translator/llvm2/database.py Log: oops Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Wed Jul 6 16:48:18 2005 @@ -120,20 +120,6 @@ if isinstance(const_or_var, Constant): ct = const_or_var.concretetype - while isinstance(ct, lltype.Ptr): - ct = ct.TO - - if isinstance(ct, lltype.FuncType): - if const_or_var.value._obj._callable and not hasattr(const_or_var.value._obj, 'graph'): - log('EXTERNAL FUNCTION' + str(dir(const_or_var.value._obj))) - #XXX if it's has a one-to-one C function then we really want THAT declaration - else: - self.addpending(const_or_var, FuncNode(self, const_or_var)) - else: - value = const_or_var.value - while hasattr(value, "_obj"): - value = value._obj - if isinstance(ct, lltype.Primitive): log.prepare(const_or_var, "(is primitive)") return From hpk at codespeak.net Wed Jul 6 17:19:37 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 6 Jul 2005 17:19:37 +0200 (CEST) Subject: [pypy-svn] r14346 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050706151937.867A627B5C@code1.codespeak.net> Author: hpk Date: Wed Jul 6 17:19:37 2005 New Revision: 14346 Added: pypy/dist/pypy/translator/llvm2/extfunction.py - copied unchanged from r14345, pypy/dist/pypy/translator/llvm2/extfunctions.py Removed: pypy/dist/pypy/translator/llvm2/extfunctions.py Modified: pypy/dist/pypy/translator/llvm2/genllvm.py Log: coding style fix Deleted: /pypy/dist/pypy/translator/llvm2/extfunctions.py ============================================================================== --- /pypy/dist/pypy/translator/llvm2/extfunctions.py Wed Jul 6 17:19:37 2005 +++ (empty file) @@ -1,7 +0,0 @@ -extdeclarations = """; External declarations -; End of external declarations -""" - -extfunctions = """; External functions (will be inlined by LLVM) -; End of external functions -""" Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Wed Jul 6 17:19:37 2005 @@ -13,7 +13,7 @@ from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void from pypy.translator.backendoptimization import rename_extfunc_calls -from pypy.translator.llvm2.extfunctions import extdeclarations, extfunctions +from pypy.translator.llvm2.extfunction import extdeclarations, extfunctions function_count = {} From ludal at codespeak.net Wed Jul 6 18:45:40 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Wed, 6 Jul 2005 18:45:40 +0200 (CEST) Subject: [pypy-svn] r14348 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20050706164540.16CE627B45@code1.codespeak.net> Author: ludal Date: Wed Jul 6 18:45:36 2005 New Revision: 14348 Added: pypy/dist/pypy/interpreter/astcompiler/ast.txt - copied unchanged from r14148, pypy/branch/pycompiler/module/recparser/compiler/ast.txt pypy/dist/pypy/interpreter/astcompiler/astgen.py - copied, changed from r14148, pypy/branch/pycompiler/module/recparser/compiler/astgen.py Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/dist/pypy/interpreter/astcompiler/transformer.py Log: (WIP) changes to the ast generator to allow an rpython visitor implementation Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.py Wed Jul 6 18:45:36 2005 @@ -31,9 +31,12 @@ return self.getChildren() def getChildNodes(self): pass # implemented by subclasses + def visit(self, visitor, *args): + return visitor.visitNode(self, *args) class EmptyNode(Node): - pass + def visit(self, visitor, *args): + return visitor.visitEmptyNode(self, *args) class Expression(Node): # Expression is an artificial node class to support "eval" @@ -50,6 +53,9 @@ def __repr__(self): return "Expression(%s)" % (repr(self.node)) + def visit(self, visitor, *args): + return visitor.visitExpression(self, *args) + class Add(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -65,6 +71,9 @@ def __repr__(self): return "Add((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitAdd(self, args) + class And(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -81,6 +90,9 @@ def __repr__(self): return "And(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitAnd(self, args) + class AssAttr(Node): def __init__(self, expr, attrname, flags, lineno=None): self.expr = expr @@ -97,6 +109,9 @@ def __repr__(self): return "AssAttr(%s, %s, %s)" % (repr(self.expr), repr(self.attrname), repr(self.flags)) + def accept(self, visitor, args): + return visitor.visitAssAttr(self, args) + class AssList(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -113,6 +128,9 @@ def __repr__(self): return "AssList(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitAssList(self, args) + class AssName(Node): def __init__(self, name, flags, lineno=None): self.name = name @@ -128,6 +146,9 @@ def __repr__(self): return "AssName(%s, %s)" % (repr(self.name), repr(self.flags)) + def accept(self, visitor, args): + return visitor.visitAssName(self, args) + class AssTuple(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -144,6 +165,9 @@ def __repr__(self): return "AssTuple(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitAssTuple(self, args) + class Assert(Node): def __init__(self, test, fail, lineno=None): self.test = test @@ -166,6 +190,9 @@ def __repr__(self): return "Assert(%s, %s)" % (repr(self.test), repr(self.fail)) + def accept(self, visitor, args): + return visitor.visitAssert(self, args) + class Assign(Node): def __init__(self, nodes, expr, lineno=None): self.nodes = nodes @@ -187,6 +214,9 @@ def __repr__(self): return "Assign(%s, %s)" % (repr(self.nodes), repr(self.expr)) + def accept(self, visitor, args): + return visitor.visitAssign(self, args) + class AugAssign(Node): def __init__(self, node, op, expr, lineno=None): self.node = node @@ -203,6 +233,9 @@ def __repr__(self): return "AugAssign(%s, %s, %s)" % (repr(self.node), repr(self.op), repr(self.expr)) + def accept(self, visitor, args): + return visitor.visitAugAssign(self, args) + class Backquote(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -217,6 +250,9 @@ def __repr__(self): return "Backquote(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitBackquote(self, args) + class Bitand(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -233,6 +269,9 @@ def __repr__(self): return "Bitand(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitBitand(self, args) + class Bitor(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -249,6 +288,9 @@ def __repr__(self): return "Bitor(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitBitor(self, args) + class Bitxor(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -265,6 +307,9 @@ def __repr__(self): return "Bitxor(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitBitxor(self, args) + class Break(Node): def __init__(self, lineno=None): self.lineno = lineno @@ -278,6 +323,9 @@ def __repr__(self): return "Break()" + def accept(self, visitor, args): + return visitor.visitBreak(self, args) + class CallFunc(Node): def __init__(self, node, args, star_args = None, dstar_args = None, lineno=None): self.node = node @@ -307,6 +355,9 @@ def __repr__(self): return "CallFunc(%s, %s, %s, %s)" % (repr(self.node), repr(self.args), repr(self.star_args), repr(self.dstar_args)) + def accept(self, visitor, args): + return visitor.visitCallFunc(self, args) + class Class(Node): def __init__(self, name, bases, doc, code, lineno=None): self.name = name @@ -332,6 +383,9 @@ def __repr__(self): return "Class(%s, %s, %s, %s)" % (repr(self.name), repr(self.bases), repr(self.doc), repr(self.code)) + def accept(self, visitor, args): + return visitor.visitClass(self, args) + class Compare(Node): def __init__(self, expr, ops, lineno=None): self.expr = expr @@ -353,6 +407,9 @@ def __repr__(self): return "Compare(%s, %s)" % (repr(self.expr), repr(self.ops)) + def accept(self, visitor, args): + return visitor.visitCompare(self, args) + class Const(Node): def __init__(self, value, lineno=None): self.value = value @@ -367,6 +424,9 @@ def __repr__(self): return "Const(%s)" % (repr(self.value),) + def accept(self, visitor, args): + return visitor.visitConst(self, args) + class Continue(Node): def __init__(self, lineno=None): self.lineno = lineno @@ -380,6 +440,9 @@ def __repr__(self): return "Continue()" + def accept(self, visitor, args): + return visitor.visitContinue(self, args) + class Decorators(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -396,6 +459,9 @@ def __repr__(self): return "Decorators(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitDecorators(self, args) + class Dict(Node): def __init__(self, items, lineno=None): self.items = items @@ -412,6 +478,9 @@ def __repr__(self): return "Dict(%s)" % (repr(self.items),) + def accept(self, visitor, args): + return visitor.visitDict(self, args) + class Discard(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -426,6 +495,9 @@ def __repr__(self): return "Discard(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitDiscard(self, args) + class Div(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -441,6 +513,9 @@ def __repr__(self): return "Div((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitDiv(self, args) + class Ellipsis(Node): def __init__(self, lineno=None): self.lineno = lineno @@ -454,6 +529,9 @@ def __repr__(self): return "Ellipsis()" + def accept(self, visitor, args): + return visitor.visitEllipsis(self, args) + class Exec(Node): def __init__(self, expr, locals, globals, lineno=None): self.expr = expr @@ -480,6 +558,9 @@ def __repr__(self): return "Exec(%s, %s, %s)" % (repr(self.expr), repr(self.locals), repr(self.globals)) + def accept(self, visitor, args): + return visitor.visitExec(self, args) + class FloorDiv(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -495,6 +576,9 @@ def __repr__(self): return "FloorDiv((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitFloorDiv(self, args) + class For(Node): def __init__(self, assign, list, body, else_, lineno=None): self.assign = assign @@ -523,6 +607,9 @@ def __repr__(self): return "For(%s, %s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.body), repr(self.else_)) + def accept(self, visitor, args): + return visitor.visitFor(self, args) + class From(Node): def __init__(self, modname, names, lineno=None): self.modname = modname @@ -538,6 +625,9 @@ def __repr__(self): return "From(%s, %s)" % (repr(self.modname), repr(self.names)) + def accept(self, visitor, args): + return visitor.visitFrom(self, args) + class Function(Node): def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None): self.decorators = decorators @@ -553,7 +643,7 @@ self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 - + def getChildren(self): @@ -578,13 +668,16 @@ def __repr__(self): return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code)) + def accept(self, visitor, args): + return visitor.visitFunction(self, args) + class GenExpr(Node): def __init__(self, code, lineno=None): self.code = code self.lineno = lineno self.argnames = ['[outmost-iterable]'] self.varargs = self.kwargs = None - + def getChildren(self): @@ -596,6 +689,9 @@ def __repr__(self): return "GenExpr(%s)" % (repr(self.code),) + def accept(self, visitor, args): + return visitor.visitGenExpr(self, args) + class GenExprFor(Node): def __init__(self, assign, iter, ifs, lineno=None): self.assign = assign @@ -622,6 +718,9 @@ def __repr__(self): return "GenExprFor(%s, %s, %s)" % (repr(self.assign), repr(self.iter), repr(self.ifs)) + def accept(self, visitor, args): + return visitor.visitGenExprFor(self, args) + class GenExprIf(Node): def __init__(self, test, lineno=None): self.test = test @@ -636,6 +735,9 @@ def __repr__(self): return "GenExprIf(%s)" % (repr(self.test),) + def accept(self, visitor, args): + return visitor.visitGenExprIf(self, args) + class GenExprInner(Node): def __init__(self, expr, quals, lineno=None): self.expr = expr @@ -657,6 +759,9 @@ def __repr__(self): return "GenExprInner(%s, %s)" % (repr(self.expr), repr(self.quals)) + def accept(self, visitor, args): + return visitor.visitGenExprInner(self, args) + class Getattr(Node): def __init__(self, expr, attrname, lineno=None): self.expr = expr @@ -672,6 +777,9 @@ def __repr__(self): return "Getattr(%s, %s)" % (repr(self.expr), repr(self.attrname)) + def accept(self, visitor, args): + return visitor.visitGetattr(self, args) + class Global(Node): def __init__(self, names, lineno=None): self.names = names @@ -686,6 +794,9 @@ def __repr__(self): return "Global(%s)" % (repr(self.names),) + def accept(self, visitor, args): + return visitor.visitGlobal(self, args) + class If(Node): def __init__(self, tests, else_, lineno=None): self.tests = tests @@ -708,6 +819,9 @@ def __repr__(self): return "If(%s, %s)" % (repr(self.tests), repr(self.else_)) + def accept(self, visitor, args): + return visitor.visitIf(self, args) + class Import(Node): def __init__(self, names, lineno=None): self.names = names @@ -722,6 +836,9 @@ def __repr__(self): return "Import(%s)" % (repr(self.names),) + def accept(self, visitor, args): + return visitor.visitImport(self, args) + class Invert(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -736,6 +853,9 @@ def __repr__(self): return "Invert(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitInvert(self, args) + class Keyword(Node): def __init__(self, name, expr, lineno=None): self.name = name @@ -751,6 +871,9 @@ def __repr__(self): return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr)) + def accept(self, visitor, args): + return visitor.visitKeyword(self, args) + class Lambda(Node): def __init__(self, argnames, defaults, flags, code, lineno=None): self.argnames = argnames @@ -763,7 +886,7 @@ self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 - + def getChildren(self): @@ -783,6 +906,9 @@ def __repr__(self): return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code)) + def accept(self, visitor, args): + return visitor.visitLambda(self, args) + class LeftShift(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -798,6 +924,9 @@ def __repr__(self): return "LeftShift((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitLeftShift(self, args) + class List(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -814,6 +943,9 @@ def __repr__(self): return "List(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitList(self, args) + class ListComp(Node): def __init__(self, expr, quals, lineno=None): self.expr = expr @@ -835,6 +967,9 @@ def __repr__(self): return "ListComp(%s, %s)" % (repr(self.expr), repr(self.quals)) + def accept(self, visitor, args): + return visitor.visitListComp(self, args) + class ListCompFor(Node): def __init__(self, assign, list, ifs, lineno=None): self.assign = assign @@ -859,6 +994,9 @@ def __repr__(self): return "ListCompFor(%s, %s, %s)" % (repr(self.assign), repr(self.list), repr(self.ifs)) + def accept(self, visitor, args): + return visitor.visitListCompFor(self, args) + class ListCompIf(Node): def __init__(self, test, lineno=None): self.test = test @@ -873,6 +1011,9 @@ def __repr__(self): return "ListCompIf(%s)" % (repr(self.test),) + def accept(self, visitor, args): + return visitor.visitListCompIf(self, args) + class Mod(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -888,6 +1029,9 @@ def __repr__(self): return "Mod((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitMod(self, args) + class Module(Node): def __init__(self, doc, node, lineno=None): self.doc = doc @@ -903,6 +1047,9 @@ def __repr__(self): return "Module(%s, %s)" % (repr(self.doc), repr(self.node)) + def accept(self, visitor, args): + return visitor.visitModule(self, args) + class Mul(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -918,6 +1065,9 @@ def __repr__(self): return "Mul((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitMul(self, args) + class Name(Node): def __init__(self, name, lineno=None): self.name = name @@ -932,6 +1082,9 @@ def __repr__(self): return "Name(%s)" % (repr(self.name),) + def accept(self, visitor, args): + return visitor.visitName(self, args) + class Not(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -946,6 +1099,9 @@ def __repr__(self): return "Not(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitNot(self, args) + class Or(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -962,6 +1118,9 @@ def __repr__(self): return "Or(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitOr(self, args) + class Pass(Node): def __init__(self, lineno=None): self.lineno = lineno @@ -975,6 +1134,9 @@ def __repr__(self): return "Pass()" + def accept(self, visitor, args): + return visitor.visitPass(self, args) + class Power(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -990,6 +1152,9 @@ def __repr__(self): return "Power((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitPower(self, args) + class Print(Node): def __init__(self, nodes, dest, lineno=None): self.nodes = nodes @@ -1012,6 +1177,9 @@ def __repr__(self): return "Print(%s, %s)" % (repr(self.nodes), repr(self.dest)) + def accept(self, visitor, args): + return visitor.visitPrint(self, args) + class Printnl(Node): def __init__(self, nodes, dest, lineno=None): self.nodes = nodes @@ -1034,6 +1202,9 @@ def __repr__(self): return "Printnl(%s, %s)" % (repr(self.nodes), repr(self.dest)) + def accept(self, visitor, args): + return visitor.visitPrintnl(self, args) + class Raise(Node): def __init__(self, expr1, expr2, expr3, lineno=None): self.expr1 = expr1 @@ -1061,6 +1232,9 @@ def __repr__(self): return "Raise(%s, %s, %s)" % (repr(self.expr1), repr(self.expr2), repr(self.expr3)) + def accept(self, visitor, args): + return visitor.visitRaise(self, args) + class Return(Node): def __init__(self, value, lineno=None): self.value = value @@ -1075,6 +1249,9 @@ def __repr__(self): return "Return(%s)" % (repr(self.value),) + def accept(self, visitor, args): + return visitor.visitReturn(self, args) + class RightShift(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -1090,6 +1267,9 @@ def __repr__(self): return "RightShift((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitRightShift(self, args) + class Slice(Node): def __init__(self, expr, flags, lower, upper, lineno=None): self.expr = expr @@ -1118,6 +1298,9 @@ def __repr__(self): return "Slice(%s, %s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.lower), repr(self.upper)) + def accept(self, visitor, args): + return visitor.visitSlice(self, args) + class Sliceobj(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -1134,6 +1317,9 @@ def __repr__(self): return "Sliceobj(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitSliceobj(self, args) + class Stmt(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -1150,6 +1336,9 @@ def __repr__(self): return "Stmt(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitStmt(self, args) + class Sub(Node): def __init__(self, (left, right), lineno=None): self.left = left @@ -1165,6 +1354,9 @@ def __repr__(self): return "Sub((%s, %s))" % (repr(self.left), repr(self.right)) + def accept(self, visitor, args): + return visitor.visitSub(self, args) + class Subscript(Node): def __init__(self, expr, flags, subs, lineno=None): self.expr = expr @@ -1188,6 +1380,9 @@ def __repr__(self): return "Subscript(%s, %s, %s)" % (repr(self.expr), repr(self.flags), repr(self.subs)) + def accept(self, visitor, args): + return visitor.visitSubscript(self, args) + class TryExcept(Node): def __init__(self, body, handlers, else_, lineno=None): self.body = body @@ -1213,6 +1408,9 @@ def __repr__(self): return "TryExcept(%s, %s, %s)" % (repr(self.body), repr(self.handlers), repr(self.else_)) + def accept(self, visitor, args): + return visitor.visitTryExcept(self, args) + class TryFinally(Node): def __init__(self, body, final, lineno=None): self.body = body @@ -1228,6 +1426,9 @@ def __repr__(self): return "TryFinally(%s, %s)" % (repr(self.body), repr(self.final)) + def accept(self, visitor, args): + return visitor.visitTryFinally(self, args) + class Tuple(Node): def __init__(self, nodes, lineno=None): self.nodes = nodes @@ -1244,6 +1445,9 @@ def __repr__(self): return "Tuple(%s)" % (repr(self.nodes),) + def accept(self, visitor, args): + return visitor.visitTuple(self, args) + class UnaryAdd(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -1258,6 +1462,9 @@ def __repr__(self): return "UnaryAdd(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitUnaryAdd(self, args) + class UnarySub(Node): def __init__(self, expr, lineno=None): self.expr = expr @@ -1272,6 +1479,9 @@ def __repr__(self): return "UnarySub(%s)" % (repr(self.expr),) + def accept(self, visitor, args): + return visitor.visitUnarySub(self, args) + class While(Node): def __init__(self, test, body, else_, lineno=None): self.test = test @@ -1297,6 +1507,9 @@ def __repr__(self): return "While(%s, %s, %s)" % (repr(self.test), repr(self.body), repr(self.else_)) + def accept(self, visitor, args): + return visitor.visitWhile(self, args) + class Yield(Node): def __init__(self, value, lineno=None): self.value = value @@ -1311,6 +1524,162 @@ def __repr__(self): return "Yield(%s)" % (repr(self.value),) + def accept(self, visitor, args): + return visitor.visitYield(self, args) + + +class ASTVisitor(object): + """This is a visitor base class used to provide the visit + method in replacement of the former visitor.visit = walker.dispatch + It could also use to identify base type for visit arguments of AST nodes + """ + + def default(self, node, args): + for child in node.getChildNodes(): + child.visit(self, args) + + + def visitAdd(self, args): + return self.default( args ) + def visitAnd(self, args): + return self.default( args ) + def visitAssAttr(self, args): + return self.default( args ) + def visitAssList(self, args): + return self.default( args ) + def visitAssName(self, args): + return self.default( args ) + def visitAssTuple(self, args): + return self.default( args ) + def visitAssert(self, args): + return self.default( args ) + def visitAssign(self, args): + return self.default( args ) + def visitAugAssign(self, args): + return self.default( args ) + def visitBackquote(self, args): + return self.default( args ) + def visitBitand(self, args): + return self.default( args ) + def visitBitor(self, args): + return self.default( args ) + def visitBitxor(self, args): + return self.default( args ) + def visitBreak(self, args): + return self.default( args ) + def visitCallFunc(self, args): + return self.default( args ) + def visitClass(self, args): + return self.default( args ) + def visitCompare(self, args): + return self.default( args ) + def visitConst(self, args): + return self.default( args ) + def visitContinue(self, args): + return self.default( args ) + def visitDecorators(self, args): + return self.default( args ) + def visitDict(self, args): + return self.default( args ) + def visitDiscard(self, args): + return self.default( args ) + def visitDiv(self, args): + return self.default( args ) + def visitEllipsis(self, args): + return self.default( args ) + def visitExec(self, args): + return self.default( args ) + def visitFloorDiv(self, args): + return self.default( args ) + def visitFor(self, args): + return self.default( args ) + def visitFrom(self, args): + return self.default( args ) + def visitFunction(self, args): + return self.default( args ) + def visitGenExpr(self, args): + return self.default( args ) + def visitGenExprFor(self, args): + return self.default( args ) + def visitGenExprIf(self, args): + return self.default( args ) + def visitGenExprInner(self, args): + return self.default( args ) + def visitGetattr(self, args): + return self.default( args ) + def visitGlobal(self, args): + return self.default( args ) + def visitIf(self, args): + return self.default( args ) + def visitImport(self, args): + return self.default( args ) + def visitInvert(self, args): + return self.default( args ) + def visitKeyword(self, args): + return self.default( args ) + def visitLambda(self, args): + return self.default( args ) + def visitLeftShift(self, args): + return self.default( args ) + def visitList(self, args): + return self.default( args ) + def visitListComp(self, args): + return self.default( args ) + def visitListCompFor(self, args): + return self.default( args ) + def visitListCompIf(self, args): + return self.default( args ) + def visitMod(self, args): + return self.default( args ) + def visitModule(self, args): + return self.default( args ) + def visitMul(self, args): + return self.default( args ) + def visitName(self, args): + return self.default( args ) + def visitNot(self, args): + return self.default( args ) + def visitOr(self, args): + return self.default( args ) + def visitPass(self, args): + return self.default( args ) + def visitPower(self, args): + return self.default( args ) + def visitPrint(self, args): + return self.default( args ) + def visitPrintnl(self, args): + return self.default( args ) + def visitRaise(self, args): + return self.default( args ) + def visitReturn(self, args): + return self.default( args ) + def visitRightShift(self, args): + return self.default( args ) + def visitSlice(self, args): + return self.default( args ) + def visitSliceobj(self, args): + return self.default( args ) + def visitStmt(self, args): + return self.default( args ) + def visitSub(self, args): + return self.default( args ) + def visitSubscript(self, args): + return self.default( args ) + def visitTryExcept(self, args): + return self.default( args ) + def visitTryFinally(self, args): + return self.default( args ) + def visitTuple(self, args): + return self.default( args ) + def visitUnaryAdd(self, args): + return self.default( args ) + def visitUnarySub(self, args): + return self.default( args ) + def visitWhile(self, args): + return self.default( args ) + def visitYield(self, args): + return self.default( args ) + for name, obj in globals().items(): if isinstance(obj, type) and issubclass(obj, Node): nodes[name.lower()] = obj Copied: pypy/dist/pypy/interpreter/astcompiler/astgen.py (from r14148, pypy/branch/pycompiler/module/recparser/compiler/astgen.py) ============================================================================== --- pypy/branch/pycompiler/module/recparser/compiler/astgen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/astgen.py Wed Jul 6 18:45:36 2005 @@ -192,8 +192,12 @@ print >> buf, ' return "%s()"' % self.name def _gen_visit(self, buf): - print >> buf, " def visit(self, visitor, *args):" - print >> buf, " return visitor.visit%s(self, *args)" % self.name + print >> buf, " def accept(self, visitor, args):" + print >> buf, " return visitor.visit%s(self, args)" % self.name + + def gen_base_visit(self, buf): + print >> buf, " def visit%s(self, args):" % self.name + print >> buf, " return self.default( args )" rx_init = re.compile('init\((.*)\):') @@ -222,6 +226,26 @@ cur = classes[name] return sorted(classes.values(), key=lambda n: n.name) +ASTVISITORCLASS=''' +class ASTVisitor(object): + """This is a visitor base class used to provide the visit + method in replacement of the former visitor.visit = walker.dispatch + It could also use to identify base type for visit arguments of AST nodes + """ + + def default(self, node, args): + for child in node.getChildNodes(): + child.visit(self, args) + +''' + +def gen_ast_visitor(classes): + print ASTVISITORCLASS + buf = StringIO() + for info in classes: + info.gen_base_visit(buf) + print buf.getvalue() + def main(): prologue, epilogue = load_boilerplate(sys.argv[-1]) print prologue @@ -229,6 +253,7 @@ classes = parse_spec(SPEC) for info in classes: print info.gen_source() + gen_ast_visitor(classes) print epilogue if __name__ == "__main__": Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/transformer.py Wed Jul 6 18:45:36 2005 @@ -21,6 +21,8 @@ # Portions of this file are: # Copyright (C) 1997-1998 Greg Stein. All Rights Reserved. # +# Modified for PYPY +# # This module is provided under a BSD-ish license. See # http://www.opensource.org/licenses/bsd-license.html # and replace OWNER, ORGANIZATION, and YEAR as appropriate. From ludal at codespeak.net Wed Jul 6 18:49:54 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Wed, 6 Jul 2005 18:49:54 +0200 (CEST) Subject: [pypy-svn] r14349 - in pypy/dist/pypy/interpreter: pyparser pyparser/test stablecompiler Message-ID: <20050706164954.ADC1427B45@code1.codespeak.net> Author: ludal Date: Wed Jul 6 18:49:51 2005 New Revision: 14349 Added: pypy/dist/pypy/interpreter/pyparser/astbuilder.py - copied, changed from r14156, pypy/branch/pycompiler/module/recparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: start working on an astbuilder Copied: pypy/dist/pypy/interpreter/pyparser/astbuilder.py (from r14156, pypy/branch/pycompiler/module/recparser/astbuilder.py) ============================================================================== --- pypy/branch/pycompiler/module/recparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Wed Jul 6 18:49:51 2005 @@ -1,48 +1,191 @@ from grammar import BaseGrammarBuilder -from compiler.ast import nodes, TokenNode -from compiler.astfactory import factory_functions, group_factory, syntaxnode_factory +import pypy.interpreter.astcompiler.ast as ast +def get_atoms( builder, nb ): + L = [] + i = nb + while i>0: + obj = builder.pop() + if isinstance(obj,RuleObject): + i+=obj.count + else: + L.append( obj ) + i -= 1 + L.reverse() + return L + + +def build_single_input( builder, nb ): + pass + +def build_atom( builder, nb ): + L = get_atoms( builder, nb ) + top = L[0] + if isinstance(top, TokenObject): + if top.name == "(": + builder. ast.Tuple(L[1:-1], top.line) + elif top.name == "[": + builder.push( ast.List( L[1:-1], top.line) ) + elif top.name == "{": + builder.push( ast.Dict( L[1:-1], top.line) ) + elif top.name == "NAME": + builder.push( ast.Name(top.value) ) + elif top.name == "NUMBER": + builder.push( ast.Const(eval(top.value)) ) + else: + raise ValueError, "unexpected tokens (%d): %s" % (nb,[ str(i) for i in L] ) + + +def build_power( builder, nb ): + L = get_atoms( builder, nb ) + if len(L) == 1: + builder.push( L[0] ) + elif len(L) == 3: + builder.push( ast.Power( [ L[0], L[2] ] ) ) + else: + raise ValueError, "unexpected tokens: %s" % L + +def build_factor( builder, nb ): + L = get_atoms( builder, nb ) + if len(L) == 1: + builder.push( L[0] ) + elif len(L) == 2 and isinstance(L[0],TokenObject): + if L[0].name == "+": + builder.push( ast.UnaryAdd( L[1] ) ) + if L[0].name == "-": + builder.push( ast.UnarySub( L[1] ) ) + if L[0].name == "~": + builder.push( ast.Invert( L[1] ) ) + +def build_term( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + left = L[0] + for i in range(2,l,2): + right = L[i] + op = L[i-1].name + if op == "*": + left = ast.Mul( [ left, right ] ) + elif op == "/": + left = ast.Div( [ left, right ] ) + elif op == "%": + left = ast.Mod( [ left, right ] ) + elif op == "//": + left = ast.FloorDiv( [ left, right ] ) + else: + raise ValueError, "unexpected token: %s" % L[i-1] + builder.push( left ) + +def build_arith_expr( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + left = L[0] + for i in range(2,l,2): + right = L[i] + op = L[i-1].name + if op == "+": + left = ast.Add( [ left, right ] ) + elif op == "-": + left = ast.Sub( [ left, right ] ) + else: + raise ValueError, "unexpected token: %s : %s" % L[i-1] + builder.push( left ) + +def build_shift_expr( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + left = L[0] + for i in range(2,l,2): + right = L[i] + op = L[i-1].name + if op == "<<": + left = ast.LeftShift( [ left, right ] ) + elif op == ">>": + left = ast.RightShift( [ left, right ] ) + else: + raise ValueError, "unexpected token: %s : %s" % L[i-1] + builder.push( left ) + + +ASTRULES = { +# "single_input" : build_single_input, + "atom" : build_atom, + "power" : build_power, + "factor" : build_factor, + "term" : build_term, + "arith_expr" : build_arith_expr, + "shift_expr" : build_shift_expr, + } + +class RuleObject(ast.Node): + """A simple object used to wrap a rule or token""" + def __init__(self, name, count, src ): + self.name = name + self.count = count + self.line = 0 # src.getline() + self.col = 0 # src.getcol() + + def __str__(self): + return "" % (self.name,) + +class TokenObject(ast.Node): + """A simple object used to wrap a rule or token""" + def __init__(self, name, value, src ): + self.name = name + self.value = value + self.count = 0 + self.line = 0 # src.getline() + self.col = 0 # src.getcol() + + def __str__(self): + return "" % (self.name, self.value) + class AstBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" def __init__( self, rules=None, debug=0 ): BaseGrammarBuilder.__init__(self, rules, debug ) + self.rule_stack = [] + + def pop(self): + return self.rule_stack.pop(-1) + + def push(self, obj): + if not isinstance(obj, RuleObject) and not isinstance(obj, TokenObject): + print "Pushed:", str(obj), len(self.rule_stack) + self.rule_stack.append( obj ) + + def push_tok(self, name, value, src ): + self.push( TokenObject( name, value, src ) ) - def top(self, n=1): - toplist = [] - for node in self.stack[-n:]: - toplist += node.expand() - return toplist + def push_rule(self, name, count, src ): + self.push( RuleObject( name, count, src ) ) def alternative( self, rule, source ): # Do nothing, keep rule on top of the stack if rule.is_root(): - ast_factory = factory_functions.get( rule.name, syntaxnode_factory ) - elems = self.top() - node = ast_factory( rule.name, source, elems ) - self.stack[-1] = node - if self.debug: - self.stack[-1].dumpstr() + print "ALT:",rule.name + F = ASTRULES.get(rule.name) + if F: + F( self, 1 ) + else: + self.push_rule( rule.name, 1, source ) return True def sequence(self, rule, source, elts_number): """ """ - items = self.top( elts_number ) if rule.is_root(): - ast_factory = factory_functions.get( rule.name, syntaxnode_factory ) - else: - ast_factory = group_factory - - node = ast_factory( rule.name, source, items ) - # replace N elements with 1 element regrouping them - if elts_number >= 1: - self.stack[-elts_number:] = node + print "SEQ:", rule.name + F = ASTRULES.get(rule.name) + if F: + F( self, elts_number ) else: - self.stack.append(node) + self.push_rule( rule.name, elts_number, source ) return True def token(self, name, value, source): - self.stack.append(TokenNode(name, source, value)) + print "TOK:", name, value + self.push_tok( name, value, source ) return True Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Wed Jul 6 18:49:51 2005 @@ -63,12 +63,6 @@ } NT_OFFSET = token.NT_OFFSET -SYMBOLS = {} -# copies the numerical mapping between symbol name and symbol value -# into SYMBOLS -for k, v in symbol.sym_name.items(): - SYMBOLS[v] = k -SYMBOLS['UNKNOWN'] = -1 class SyntaxNode(object): Added: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Wed Jul 6 18:49:51 2005 @@ -0,0 +1,26 @@ + +from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER +from pypy.interpreter.pyparser.astbuilder import AstBuilder +from pypy.interpreter.pyparser.pythonutil import ast_from_input +from pypy.interpreter.stablecompiler.transformer import Transformer +import py.test + +expr1 = "x = a + 1" + + + +def ast_parse_expr( expr ): + builder = AstBuilder() + PYTHON_PARSER.parse_source( expr, "single_input", builder ) + return builder + +def tuple_parse_expr( expr ): + t = Transformer() + return ast_from_input( expr, "single", t ) + +def test_expr1(): + py.test.skip("work in progress") + r1 = ast_parse_expr( expr1 ) + ast = tuple_parse_expr( expr1 ) + print ast + Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Wed Jul 6 18:49:51 2005 @@ -25,13 +25,13 @@ # http://www.opensource.org/licenses/bsd-license.html # and replace OWNER, ORGANIZATION, and YEAR as appropriate. +# make sure we import the parser with the correct grammar +import pypy.interpreter.pyparser.pythonparse from pypy.interpreter.stablecompiler.ast import * import parser import symbol import token import sys -# make sure we import the parser with the correct grammar -import pypy.interpreter.pyparser.pythonparse class WalkerError(StandardError): pass From ac at codespeak.net Wed Jul 6 19:49:14 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Jul 2005 19:49:14 +0200 (CEST) Subject: [pypy-svn] r14350 - pypy/dist/pypy/module/sys Message-ID: <20050706174914.70C0F27B3C@code1.codespeak.net> Author: ac Date: Wed Jul 6 19:49:13 2005 New Revision: 14350 Modified: pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/app.py pypy/dist/pypy/module/sys/state.py Log: Have out own sys.(get|set)defaultencoding. Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Wed Jul 6 19:49:13 2005 @@ -35,7 +35,6 @@ 'builtin_module_names' : 'state.get(space).w_builtin_module_names', 'pypy_getudir' : 'state.pypy_getudir', - 'getdefaultencoding' : 'state.getdefaultencoding', 'getrefcount' : 'vm.getrefcount', '_getframe' : 'vm._getframe', 'setrecursionlimit' : 'vm.setrecursionlimit', @@ -68,6 +67,8 @@ 'exit' : 'app.exit', 'getfilesystemencoding' : 'app.getfilesystemencoding', 'callstats' : 'app.callstats', + 'getdefaultencoding' : 'app.getdefaultencoding', + 'setdefaultencoding' : 'app.setdefaultencoding', } def setbuiltinmodule(self, w_module, name): Modified: pypy/dist/pypy/module/sys/app.py ============================================================================== --- pypy/dist/pypy/module/sys/app.py (original) +++ pypy/dist/pypy/module/sys/app.py Wed Jul 6 19:49:13 2005 @@ -54,3 +54,14 @@ 9. All other calls 10. Number of stack pops performed by call_function()""" return None + +defaultencoding = 'ascii' + +def getdefaultencoding(): + return defaultencoding + +def setdefaultencoding(encoding): + global defaultencoding + import codecs + codecs.lookup(encoding) + defaultencoding = encoding Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Wed Jul 6 19:49:13 2005 @@ -87,6 +87,3 @@ # directly. def pypy_getudir(space): return _pypy_getudir(space) - -def getdefaultencoding(space): - return space.wrap(sys.getdefaultencoding()) From ac at codespeak.net Wed Jul 6 19:53:38 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Jul 2005 19:53:38 +0200 (CEST) Subject: [pypy-svn] r14352 - pypy/extradoc/sprintinfo Message-ID: <20050706175338.CFDCB27B43@code1.codespeak.net> Author: ac Date: Wed Jul 6 19:53:38 2005 New Revision: 14352 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: Update. Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Wed Jul 6 19:53:38 2005 @@ -69,7 +69,7 @@ an example that has issubtype in the annotated flow graph) (strange)(delegating to backend?) sys.getrefcount - (medium) applevel sys module should not refer to + DONE: (medium) applevel sys module should not refer to interplevel sys.getdefaultencoding (generate c_api calls) os.path.exists (generate c_api calls) os.path.isdir From arigo at codespeak.net Wed Jul 6 20:01:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 20:01:39 +0200 (CEST) Subject: [pypy-svn] r14353 - pypy/dist/pypy/translator/goal Message-ID: <20050706180139.BE0AD27B40@code1.codespeak.net> Author: arigo Date: Wed Jul 6 20:01:37 2005 New Revision: 14353 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: Made targetpypymain.py importable (as opposed to only execfile-able). Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Wed Jul 6 20:01:37 2005 @@ -11,7 +11,10 @@ # There is no easy way to build all caches manually, # but the annotator can do it for us for free. -this_dir = os.path.dirname(sys.argv[0]) +try: + this_dir = os.path.dirname(__file__) +except NameError: + this_dir = os.path.dirname(sys.argv[0]) # __________ Entry point __________ From ac at codespeak.net Wed Jul 6 20:19:12 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Jul 2005 20:19:12 +0200 (CEST) Subject: [pypy-svn] r14354 - pypy/dist/pypy/module/unicodedata Message-ID: <20050706181912.EA2E227B3D@code1.codespeak.net> Author: ac Date: Wed Jul 6 20:19:10 2005 New Revision: 14354 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: Tweak the structuring of data somewhat. 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 Jul 6 20:19:10 2005 @@ -60,7 +60,7 @@ result = [] for decomp in table[code].decomposition: result.extend(get_compat_decomposition(table, decomp)) - table[code].compat_decomp = tuple(result) + table[code].compat_decomp = result return table[code].compat_decomp def get_canonical_decomposition(table, code): @@ -70,7 +70,7 @@ result = [] for decomp in table[code].decomposition: result.extend(get_canonical_decomposition(table, decomp)) - table[code].canonical_decomp = tuple(result) + table[code].canonical_decomp = result return table[code].canonical_decomp def read_unicodedata(unicodedata_file, exclusions_file, east_asian_width_file): @@ -211,10 +211,10 @@ char.db_record = (char.category, char.bidirectional, char.east_asian_width, flags, char.combining) db_records[char.db_record] = 1 db_records = db_records.keys() - print >> outfile, '_db_records = (' + print >> outfile, '_db_records = [' for record in db_records: print >> outfile, '%r,'%(record,) - print >> outfile, ')' + print >> outfile, ']' print >> outfile, '_db_pgtbl = (' pages = [] line = [] @@ -241,12 +241,11 @@ for page_string in pages: for index in range(0, len(page_string), chunksize): print >> outfile, repr(page_string[index:index + chunksize]) - print >> outfile, ',' print >> outfile, ')' print >> outfile, ''' def _get_record(code): - return _db_records[ord(_db_pages[ord(_db_pgtbl[code >> %d])][code & %d])] -'''%(pgbits, bytemask) + return _db_records[ord(_db_pages[(ord(_db_pgtbl[code >> %d]) << %d) + (code & %d)])] +'''%(pgbits, pgbits, bytemask) print >> outfile, 'def category(code): return _get_record(code)[0]' print >> outfile, 'def bidirectional(code): return _get_record(code)[1]' print >> outfile, 'def east_asian_width(code): return _get_record(code)[2]' @@ -326,12 +325,11 @@ raise KeyError return 0xAC00 + (l_code * 21 + v_code) * 28 + t_code -_hexdigits = "0123456789ABCDEF" def _lookup_cjk(cjk_code): - if len(cjk_code) not in (4,5): + if len(cjk_code) != 4 and len(cjk_code) != 5: raise KeyError for c in cjk_code: - if c not in _hexdigits: + if not ('0' <= c <= '9' or 'A' <= c <= 'F'): raise KeyError code = int(cjk_code, 16) if (0x3400 <= code <= 0x4DB5 or @@ -349,17 +347,9 @@ def name(code): if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x%X): - return "CJK UNIFIED IDEOGRAPH-" + (_hexdigits[(code >> 12) & 0xf] + - _hexdigits[(code >> 8) & 0xf] + - _hexdigits[(code >> 4) & 0xf] + - _hexdigits[code & 0xf]) - - if 0x20000 <= code <= 0x2A6D6: - return "CJK UNIFIED IDEOGRAPH-2" + (_hexdigits[(code >> 12) & 0xf] + - _hexdigits[(code >> 8) & 0xf] + - _hexdigits[(code >> 4) & 0xf] + - _hexdigits[code & 0xf]) + 0x4E00 <= code <= 0x%X or + 0x20000 <= code <= 0x2A6D6): + return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) l_code, v_code = divmod(vl_code, len(_hangul_V)) Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Wed Jul 6 20:19:10 2005 @@ -13842,12 +13842,11 @@ raise KeyError return 0xAC00 + (l_code * 21 + v_code) * 28 + t_code -_hexdigits = "0123456789ABCDEF" def _lookup_cjk(cjk_code): - if len(cjk_code) not in (4,5): + if len(cjk_code) != 4 and len(cjk_code) != 5: raise KeyError for c in cjk_code: - if c not in _hexdigits: + if not ('0' <= c <= '9' or 'A' <= c <= 'F'): raise KeyError code = int(cjk_code, 16) if (0x3400 <= code <= 0x4DB5 or @@ -13865,17 +13864,9 @@ def name(code): if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FA5): - return "CJK UNIFIED IDEOGRAPH-" + (_hexdigits[(code >> 12) & 0xf] + - _hexdigits[(code >> 8) & 0xf] + - _hexdigits[(code >> 4) & 0xf] + - _hexdigits[code & 0xf]) - - if 0x20000 <= code <= 0x2A6D6: - return "CJK UNIFIED IDEOGRAPH-2" + (_hexdigits[(code >> 12) & 0xf] + - _hexdigits[(code >> 8) & 0xf] + - _hexdigits[(code >> 4) & 0xf] + - _hexdigits[code & 0xf]) + 0x4E00 <= code <= 0x9FA5 or + 0x20000 <= code <= 0x2A6D6): + return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) l_code, v_code = divmod(vl_code, len(_hangul_V)) @@ -13884,228 +13875,228 @@ return _charnames[code] -_db_records = ( -('Pe', 'ON', 'Na', 512, 0), -('Mn', 'NSM', 'A', 0, 0), -('No', 'L', 'W', 64, 0), -('So', 'ON', 'F', 0, 0), -('So', 'AL', 'N', 0, 0), -('Zs', 'WS', 'Na', 1, 0), -('Pe', 'ON', 'W', 0, 0), -('Mn', 'NSM', 'N', 0, 30), -('Mn', 'NSM', 'N', 0, 84), -('Nd', 'AN', 'N', 448, 0), -('Po', 'ET', 'N', 0, 0), +_db_records = [ +('Mn', 'NSM', 'N', 0, 222), +('Cf', 'R', 'N', 0, 0), +('Lu', 'L', 'N', 10, 0), +('Lm', 'L', 'N', 2, 0), +('Ps', 'ON', 'Na', 512, 0), +('Cf', 'PDF', 'N', 0, 0), ('Mn', 'NSM', 'W', 0, 222), +('Cf', 'LRE', 'N', 0, 0), +('Pc', 'ON', 'F', 0, 0), ('Sm', 'ON', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 91), -('Po', 'ON', 'F', 0, 0), +('No', 'EN', 'A', 192, 0), +('Mn', 'NSM', 'N', 0, 36), +('Mn', 'NSM', 'N', 0, 15), +('So', 'ON', 'Na', 0, 0), +('Mn', 'NSM', 'N', 0, 26), +('Mn', 'NSM', 'N', 0, 19), +('Pc', 'ON', 'H', 0, 0), +('Po', 'ET', 'F', 0, 0), ('Mn', 'NSM', 'N', 0, 103), -('Ll', 'L', 'A', 34, 0), +('Pd', 'ET', 'Na', 0, 0), +('Po', 'ON', 'F', 0, 0), +('Nd', 'L', 'N', 448, 0), +('Lo', 'AL', 'N', 2, 0), +('Sm', 'ON', 'Na', 0, 0), +('Pc', 'ON', 'N', 0, 0), +('Nd', 'EN', 'Na', 448, 0), +('Pe', 'ON', 'H', 512, 0), +('Cc', 'B', 'N', 5, 0), +('Sc', 'ET', 'A', 0, 0), +('Mn', 'NSM', 'N', 0, 216), +('Zs', 'CS', 'N', 1, 0), +('Po', 'ON', 'W', 0, 0), +('So', 'ON', 'F', 0, 0), +('So', 'L', 'A', 0, 0), ('Mn', 'NSM', 'N', 0, 107), -('Ps', 'ON', 'W', 0, 0), -('Ps', 'ON', 'W', 512, 0), +('Pc', 'ON', 'Na', 0, 0), +('Po', 'ET', 'Na', 0, 0), ('Mn', 'NSM', 'N', 0, 118), -('Mn', 'NSM', 'A', 0, 1), -('Sm', 'ET', 'W', 0, 0), -('Sc', 'ET', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 122), -('No', 'EN', 'A', 448, 0), -('Cc', 'B', 'N', 5, 0), -('Mn', 'NSM', 'N', 0, 7), -('Lm', 'L', 'H', 2, 0), -('Sm', 'ON', 'F', 512, 0), -('Cf', 'BN', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 1), -('Mn', 'NSM', 'N', 0, 14), -('Mn', 'NSM', 'N', 0, 15), -('Mn', 'NSM', 'N', 0, 12), -('Mn', 'NSM', 'N', 0, 13), -('Mn', 'NSM', 'N', 0, 10), -('Cc', 'WS', 'N', 1, 0), +('Zs', 'WS', 'F', 1, 0), +('So', 'ON', 'H', 0, 0), +('Sm', 'ET', 'F', 0, 0), +('Pe', 'ON', 'N', 512, 0), +('Mc', 'L', 'N', 0, 226), ('Mn', 'NSM', 'N', 0, 9), -('Mn', 'NSM', 'N', 0, 22), -('Mn', 'NSM', 'N', 0, 23), -('Mn', 'NSM', 'N', 0, 20), -('Mn', 'NSM', 'N', 0, 21), -('Mn', 'NSM', 'N', 0, 18), -('Mn', 'NSM', 'N', 0, 19), -('Mn', 'NSM', 'N', 0, 16), -('Mn', 'NSM', 'N', 0, 17), -('Lo', 'R', 'N', 2, 0), -('Mn', 'NSM', 'N', 0, 31), -('Mn', 'NSM', 'N', 0, 28), -('Mn', 'NSM', 'N', 0, 29), -('Mn', 'NSM', 'N', 0, 26), ('Mn', 'NSM', 'N', 0, 27), -('Mn', 'NSM', 'N', 0, 24), -('Mn', 'NSM', 'N', 0, 25), -('So', 'L', 'W', 0, 0), -('Pc', 'ON', 'F', 0, 0), -('Ll', 'L', 'N', 34, 0), -('So', 'ON', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 34), -('Mn', 'NSM', 'N', 0, 35), -('Mn', 'NSM', 'N', 0, 32), -('Mn', 'NSM', 'N', 0, 33), -('Mn', 'NSM', 'W', 0, 224), -('Pi', 'ON', 'A', 0, 0), -('Mn', 'NSM', 'W', 0, 232), -('Zs', 'BN', 'N', 1, 0), -('Sk', 'ON', 'N', 0, 0), -('Po', 'CS', 'Na', 0, 0), -('Sm', 'L', 'N', 0, 0), -('So', 'L', 'N', 0, 0), -('Po', 'L', 'N', 0, 0), -('Co', 'L', 'A', 0, 0), +('Mn', 'NSM', 'N', 0, 20), +('Mn', 'NSM', 'A', 0, 230), +('Pe', 'ON', 'F', 512, 0), +('Pf', 'ON', 'A', 0, 0), +('No', 'EN', 'N', 448, 0), +('Ps', 'ON', 'W', 0, 0), +('Po', 'ET', 'W', 0, 0), +('So', 'ON', 'N', 0, 0), +('Pd', 'ON', 'N', 0, 0), +('Nd', 'EN', 'N', 448, 0), +('Sm', 'ON', 'A', 512, 0), +('Lm', 'AL', 'N', 2, 0), +('Lo', 'L', 'N', 2, 0), +('Nd', 'AN', 'N', 448, 0), +('Sk', 'ON', 'Na', 0, 0), +('Cs', 'L', 'N', 0, 0), ('Po', 'R', 'N', 0, 0), -('No', 'EN', 'N', 192, 0), -('Zl', 'WS', 'N', 5, 0), -('Sm', 'ON', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 132), ('Mn', 'NSM', 'W', 0, 8), -('Zs', 'WS', 'F', 1, 0), -('No', 'ON', 'A', 192, 0), -('Cf', 'L', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 222), -('Mn', 'NSM', 'N', 0, 220), -('Sc', 'ET', 'N', 0, 0), -('Zs', 'CS', 'N', 1, 0), -('Mn', 'NSM', 'N', 0, 230), -('Cf', 'PDF', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 228), -('No', 'ON', 'N', 192, 0), -('Nl', 'L', 'N', 64, 0), -('Pc', 'ON', 'N', 0, 0), -('Lo', 'L', 'W', 2, 0), -('Mn', 'NSM', 'W', 0, 228), -('Lu', 'L', 'N', 10, 0), -('Sk', 'ON', 'A', 0, 0), -('Cf', 'LRO', 'N', 0, 0), -('Sk', 'ON', 'F', 0, 0), -('Cc', 'S', 'N', 1, 0), -('No', 'EN', 'A', 64, 0), -('No', 'L', 'N', 64, 0), -('Mn', 'NSM', 'N', 0, 130), +('So', 'L', 'W', 0, 0), ('Mn', 'NSM', 'N', 0, 129), -('Mn', 'NSM', 'A', 0, 202), -('Cf', 'RLO', 'N', 0, 0), -('Mc', 'L', 'N', 0, 226), -('Mn', 'NSM', 'A', 0, 216), -('Zs', 'WS', 'N', 1, 0), -('Me', 'NSM', 'N', 0, 0), -('Po', 'CS', 'W', 0, 0), -('Po', 'ES', 'F', 0, 0), -('Pc', 'ON', 'H', 0, 0), -('Lt', 'L', 'N', 18, 0), -('Mn', 'NSM', 'A', 0, 230), -('Mn', 'NSM', 'A', 0, 233), -('Mn', 'NSM', 'A', 0, 232), -('Mn', 'NSM', 'A', 0, 234), -('Pe', 'ON', 'F', 512, 0), -('Mn', 'NSM', 'A', 0, 240), -('Lu', 'L', 'Na', 10, 0), -('So', 'ET', 'A', 0, 0), -('Lm', 'L', 'W', 2, 0), -('Po', 'AL', 'N', 0, 0), -('No', 'ON', 'N', 64, 0), -('Sc', 'ET', 'W', 0, 0), +('Sk', 'ON', 'F', 0, 0), ('So', 'ET', 'N', 0, 0), -('Po', 'ON', 'Na', 0, 0), +('Co', 'L', 'A', 0, 0), +('Lo', 'L', 'H', 2, 0), +('Mn', 'NSM', 'N', 0, 91), +('So', 'ET', 'A', 0, 0), ('Po', 'ON', 'A', 0, 0), -('Cf', 'AL', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 10), +('Mn', 'NSM', 'N', 0, 1), +('Mn', 'NSM', 'N', 0, 28), +('Mn', 'NSM', 'N', 0, 21), +('Lo', 'L', 'W', 2, 0), +('Pf', 'ON', 'N', 512, 0), +('Pi', 'ON', 'N', 0, 0), +('Lm', 'L', 'W', 2, 0), +('Pc', 'ON', 'W', 0, 0), +('Sk', 'ON', 'N', 0, 0), +('Pi', 'ON', 'N', 512, 0), ('Mc', 'L', 'N', 0, 0), -('Sk', 'ON', 'W', 0, 0), -('Sk', 'ON', 'Na', 0, 0), +('Po', 'ET', 'A', 0, 0), ('Cc', 'BN', 'N', 0, 0), -('Ll', 'L', 'Na', 34, 0), -('Mn', 'NSM', 'A', 0, 220), -('So', 'ON', 'W', 0, 0), -('Pf', 'ON', 'N', 512, 0), -('Po', 'ET', 'Na', 0, 0), -('Po', 'ON', 'W', 0, 0), -('Sc', 'ET', 'F', 0, 0), -('Sm', 'ON', 'Na', 512, 0), -('Nd', 'EN', 'F', 448, 0), -('No', 'EN', 'A', 192, 0), -('Pe', 'ON', 'H', 512, 0), -('Sc', 'AL', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 228), +('No', 'EN', 'A', 64, 0), +('Zl', 'WS', 'N', 5, 0), +('No', 'L', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 130), +('Nl', 'L', 'N', 0, 0), +('Pd', 'ON', 'W', 0, 0), +('Cn', '', 'N', 0, 0), ('Sm', 'ON', 'N', 512, 0), -('Lm', 'L', 'N', 2, 0), -('Pe', 'ON', 'N', 0, 0), +('Pd', 'ET', 'W', 0, 0), +('Mn', 'NSM', 'W', 0, 224), +('Mn', 'NSM', 'N', 0, 32), +('Mn', 'NSM', 'N', 0, 122), +('Mn', 'NSM', 'N', 0, 11), +('Lu', 'L', 'Na', 10, 0), +('Mn', 'NSM', 'N', 0, 29), +('Mn', 'NSM', 'N', 0, 22), +('Mn', 'NSM', 'A', 0, 234), +('Cf', 'AL', 'N', 0, 0), +('Sm', 'ON', 'N', 0, 0), +('Mn', 'NSM', 'A', 0, 220), +('Lt', 'L', 'N', 18, 0), +('Po', 'CS', 'N', 0, 0), +('Cf', 'BN', 'N', 0, 0), +('Pe', 'ON', 'W', 0, 0), +('Zp', 'B', 'N', 5, 0), +('Ps', 'ON', 'W', 512, 0), ('Lu', 'L', 'A', 10, 0), -('Ps', 'ON', 'N', 512, 0), -('Pd', 'ON', 'N', 0, 0), -('Ll', 'L', 'F', 34, 0), +('No', 'ON', 'A', 192, 0), +('No', 'L', 'W', 64, 0), ('Pe', 'ON', 'W', 512, 0), -('Lo', 'L', 'H', 2, 0), -('Pi', 'ON', 'N', 512, 0), -('Pd', 'ET', 'F', 0, 0), -('Pf', 'ON', 'A', 0, 0), -('No', 'ON', 'A', 64, 0), -('Lo', 'AL', 'N', 2, 0), -('Sm', 'ET', 'Na', 0, 0), +('Cf', 'L', 'N', 0, 0), ('Po', 'CS', 'F', 0, 0), +('Nl', 'L', 'W', 64, 0), +('Sm', 'L', 'N', 0, 0), ('Lu', 'L', 'F', 10, 0), +('Ll', 'L', 'N', 34, 0), +('So', 'ON', 'A', 0, 0), +('Sc', 'ET', 'Na', 0, 0), +('Sm', 'ON', 'Na', 512, 0), +('Mc', 'L', 'N', 0, 216), +('Mn', 'NSM', 'W', 0, 232), +('Mn', 'NSM', 'N', 0, 33), +('Po', 'CS', 'Na', 0, 0), +('Mn', 'NSM', 'N', 0, 12), +('Mn', 'NSM', 'N', 0, 30), +('Mn', 'NSM', 'N', 0, 23), +('Mn', 'NSM', 'N', 0, 16), +('Mn', 'NSM', 'A', 0, 233), +('Mn', 'NSM', 'A', 0, 240), +('Mn', 'NSM', 'N', 0, 24), +('Sk', 'ON', 'W', 0, 0), +('Sm', 'ET', 'N', 0, 0), +('Me', 'NSM', 'N', 0, 0), +('Pd', 'ON', 'A', 0, 0), +('Ll', 'L', 'F', 34, 0), +('No', 'EN', 'A', 448, 0), +('Ll', 'L', 'A', 34, 0), +('Zs', 'WS', 'Na', 1, 0), +('Ps', 'ON', 'N', 512, 0), +('Nd', 'EN', 'F', 448, 0), +('Sc', 'ET', 'N', 0, 0), +('Cf', 'RLE', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 230), +('Sm', 'ET', 'Na', 0, 0), +('Po', 'L', 'N', 0, 0), +('Cf', 'LRO', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 220), ('Sc', 'ET', 'H', 0, 0), +('No', 'EN', 'N', 192, 0), +('No', 'ON', 'N', 64, 0), +('So', 'L', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 132), +('Ll', 'L', 'Na', 34, 0), +('Mn', 'NSM', 'W', 0, 218), +('Zs', 'BN', 'N', 1, 0), ('Sm', 'ET', 'A', 0, 0), -('So', 'ON', 'N', 0, 0), -('Cf', 'R', 'N', 0, 0), -('Cs', 'L', 'N', 0, 0), -('Pd', 'ON', 'W', 0, 0), -('Sm', 'ON', 'A', 512, 0), -('No', 'L', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 36), -('No', 'EN', 'N', 448, 0), -('Pc', 'ON', 'Na', 0, 0), -('Nd', 'EN', 'N', 448, 0), -('Ps', 'ON', 'N', 0, 0), -('Cn', '', 'N', 0, 0), -('Sm', 'ON', 'F', 0, 0), -('Lm', 'L', 'A', 2, 0), -('Sm', 'ON', 'Na', 0, 0), -('Ps', 'ON', 'H', 512, 0), -('Sm', 'ET', 'F', 0, 0), -('Pd', 'ET', 'Na', 0, 0), -('Sc', 'ET', 'Na', 0, 0), -('Pd', 'ET', 'W', 0, 0), -('Sm', 'ON', 'H', 0, 0), -('Po', 'CS', 'N', 0, 0), -('Nl', 'L', 'W', 64, 0), -('Nl', 'L', 'N', 0, 0), -('Po', 'AN', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 216), ('Nl', 'L', 'A', 64, 0), -('Po', 'ET', 'F', 0, 0), +('Mn', 'NSM', 'N', 0, 34), +('Mn', 'NSM', 'N', 0, 13), +('Mn', 'NSM', 'N', 0, 31), +('Po', 'ON', 'Na', 0, 0), +('Mn', 'NSM', 'N', 0, 17), +('Mn', 'NSM', 'A', 0, 232), +('Po', 'AN', 'N', 0, 0), +('Sc', 'ET', 'F', 0, 0), +('No', 'ON', 'A', 64, 0), +('Pe', 'ON', 'N', 0, 0), +('Po', 'ET', 'N', 0, 0), +('Zs', 'WS', 'N', 1, 0), +('No', 'L', 'N', 64, 0), +('No', 'ON', 'W', 64, 0), +('Sk', 'ON', 'A', 0, 0), +('Pd', 'ET', 'F', 0, 0), +('Nl', 'L', 'N', 64, 0), ('Sm', 'ON', 'W', 0, 0), -('Zp', 'B', 'N', 5, 0), -('Pe', 'ON', 'N', 512, 0), -('Lm', 'AL', 'N', 2, 0), -('So', 'L', 'A', 0, 0), -('Nd', 'L', 'N', 448, 0), -('Pi', 'ON', 'N', 0, 0), -('Pc', 'ON', 'W', 0, 0), -('Po', 'ON', 'H', 0, 0), -('Mn', 'NSM', 'N', 0, 11), -('So', 'ON', 'H', 0, 0), +('Mn', 'NSM', 'A', 0, 1), +('Sm', 'ON', 'H', 0, 0), +('Sm', 'ET', 'W', 0, 0), +('Cc', 'S', 'N', 1, 0), +('Po', 'ES', 'F', 0, 0), +('Lo', 'R', 'N', 2, 0), ('Ps', 'ON', 'F', 512, 0), ('Po', 'ON', 'N', 0, 0), -('Cf', 'RLE', 'N', 0, 0), -('Pd', 'ON', 'A', 0, 0), -('Ps', 'ON', 'Na', 512, 0), +('Pi', 'ON', 'A', 0, 0), +('Lm', 'L', 'A', 2, 0), +('Ps', 'ON', 'H', 512, 0), +('So', 'AL', 'N', 0, 0), +('Po', 'ON', 'H', 0, 0), +('Mn', 'NSM', 'W', 0, 228), +('Mn', 'NSM', 'N', 0, 35), +('Cc', 'WS', 'N', 1, 0), +('Mn', 'NSM', 'N', 0, 14), +('Mn', 'NSM', 'N', 0, 7), +('Mn', 'NSM', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 25), +('Mn', 'NSM', 'N', 0, 18), ('Po', 'ES', 'Na', 0, 0), -('Nd', 'EN', 'Na', 448, 0), -('Lo', 'L', 'N', 2, 0), -('Po', 'ET', 'W', 0, 0), -('No', 'ON', 'W', 64, 0), -('Po', 'ET', 'A', 0, 0), -('So', 'ON', 'A', 0, 0), -('Sm', 'ET', 'N', 0, 0), -('Mc', 'L', 'N', 0, 216), -('Cf', 'LRE', 'N', 0, 0), -('Mn', 'NSM', 'W', 0, 218), -) +('Po', 'CS', 'W', 0, 0), +('Mn', 'NSM', 'A', 0, 202), +('Mn', 'NSM', 'A', 0, 216), +('Cf', 'RLO', 'N', 0, 0), +('Ps', 'ON', 'N', 0, 0), +('Lm', 'L', 'H', 2, 0), +('Sc', 'ET', 'W', 0, 0), +('Po', 'AL', 'N', 0, 0), +('Sm', 'ON', 'F', 0, 0), +('Mn', 'NSM', 'N', 0, 84), +('Sc', 'AL', 'N', 0, 0), +('No', 'ON', 'N', 192, 0), +('So', 'ON', 'W', 0, 0), +('Mn', 'NSM', 'A', 0, 0), +('Pe', 'ON', 'Na', 512, 0), +('Sm', 'ON', 'F', 512, 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&\'()*+,,,,,,,,,,,,' ',,,,,,,,,,,,,-,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,' @@ -14177,355 +14168,286 @@ '222222222222222222222222222222222222222222222222222222222222222D' ) _db_pages = ( -'\x85\x85\x85\x85\x85\x85\x85\x85\x85c\x1ac&\x1a\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x1a\x1a\x1ac\x05\x7f\x7f\x8a\xb7\x8a\x7f\x7f\xd0\x00\x7f\xa0E\xb6E\xd1\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2E\x7f\x8d\xb3\x8d\x7f' -'\x7fxxxxxxxxxxxxxxxxxxxxxxxxxx\xd0\x7f\x00\x84\xad\x84\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\xd0\xb3\x00\xb3\x85' -'\x85\x85\x85\x85\x85\x1a\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85V\x80\xb7\xb7\x17\xb7;\xd7`\xa5\x10\x9b\xb3\xcf\xd7\x84y\xa4\x19\x19`:\xd7\x80`\x19\x10\x89\x9e\x9e\x9e\x80' -'______\x95_________\x95______\x0c\x95_____\x95\x10\x10\x10::::\x10:\x10\x10\x10:\x10\x10::\x10:\x10\x10:::\x0c\x10\x10\x10:\x10:\x10:' -, -'_\x10_:_:_:_:_:_:_:_\x10_\x10_:_:_:_\x10_:_:_:_:_:\x95\x10_:_\x10_:_:_\x10\x95\x10_:_:\x10_:_:_:\x95' -'\x10\x95\x10_\x10_:_\x10\x10\x95\x10_\x10_:_:\x95\x10_:_:_:_:_:_:_:_:_:\x95\x10_:_\x10_:_:_:_:_:_:__:_:_::' -':__:_:__:___::____:__:___:::__:__:_:_:__:_::_:__:___:_:__::\xd3_:::' -'\xd3\xd3\xd3\xd3_q:_q:_q:_\x10_\x10_\x10_\x10_\x10_\x10_\x10_\x10:_:_:_:_:_:_:_:_:_::_q:_:___:_:_:_:' -, -'_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_\xb0_:_:_:_:_:_:_:_:_:\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0:\x10:::::::::::::::\x10::::::::::::::::::::::::::::::' -'::::::::::::::::::::::::::::::::::::::::::::::\xb0\xb0\x93\x93\x93\x93\x93\x93\x93\x93\x93DD\x93\x93\x93\x93\x93' -'\x93\x93DD`DD`D```D`DD\xb2\x93DDDDDD````D`D`\x93\x93\x93\x93\x93DDDDDDDDD\x93\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'rrrrrrrrrrrrrrrrrrrrrt\x87\x87\x87\x87tk\x87\x87\x87\x87\x87hh\x87\x87\x87\x87hh\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x15\x15\x15\x15\x15\x87\x87\x87\x87rrr' -'rrrrrwr\x87\x87\x87rrr\x87\x87\x01\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0uusrrrrrrrrrrrrr\xb0\xb0\xb0\xb0DD\xb0\xb0\xb0\xb0\x93\xb0\xb0\xb0\xcd\xb0' -'\xb0\xb0\xb0\xb0DD_\xcd___\xb0_\xb0__:\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\xb0\x95\x95\x95\x95\x95\x95\x95__:::::\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' -'\x10\x10:\x10\x10\x10\x10\x10\x10\x10:::::\xb0::___:::_:_:_:_:_:_:_:_:_:_:_:_:::::_:M\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'_\x95______________\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' -'\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10:\x10::::::::::::::_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:' -'_:GWWWW\xb0mm_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:' -'__:_:_:_:_:_:_:\xb0_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:\xb0\xb0_:\xb0\xb0\xb0\xb0\xb0\xb0' -, -'_:_:_:_:_:_:_:_:\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0_______________' -'_______________________\xb0\xb0\x93HHHHHH\xb0:::::::::::::::::::::::::::::::' -'::::::::\xb0H\x97\xb0\xb0\xb0\xb0\xb0\xb0TWWWWTWWWSTWWWWWW\xb0TTTTTWWTWWSYW%\xca#$!"./,-\xb0*+(J)' -'J67JW\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0000000000000000000000000000\xb0\xb0\xb0\xb0\xb0000JJ\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xba\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0{\xb0\xb0\xb0{\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\xb0\xb0\xb0' -'\xc4\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f523\x071>?>\x89\x89OOL\\LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLPOOOL' +']]]]]LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]LLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLL]??ssss??????????LLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]' +']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]LLLLLLLLLLLLLLLL' +'?????????????????????????????]]]ssssssssss??????????????????????' +'????]]]]]]]]]]]]]\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1????????????????????????????]]]?' +'ssssssssss???????????????????????????????????????\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1' +'????????????]]]]???????????????????????????????????????????????]' +'????????????????????????????????????????????????????????????????' +'???????????????????????????????????????????????????????]]]]?????' +'????????????????????????????????????????????????????????????????' +'??????????????????????????????]]???????????????????????????????]' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLL]]]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' +'\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -, +'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' +'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' +'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' +'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]LLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, +'zzzzzzz]]]]]]]]]]]]zzzzz]]]]]\xbb\x0e\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\x8a\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb]\xbb\xbb\xbb\xbb\xbb]\xbb]' +'\xbb\xbb]\xbb\xbb]\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xd0\xad' +']]]]]]]]]]]]]]]]\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\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\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\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\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\xd6]]]' +'\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9]]]]]]]]]]]]]]]]\x95\x95\x95\x95]]]]]]]]]]]]\x1f\\\\PP2n2n2n2n2n2' +'n2n2n\x1f\x1f]]\x1f\x1f\x1f\x1fPPP\xcc\x1f\xcc]\x1f\xcc\x1f\x1f\\2n2n2n3\x1f\x1f\xb8_\xb5\xb5\xb5]\x1f\xd23\x1f]]]]\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16]]m' +']\x14\x14\x11\xab\x11\x14\x14\xbc/\x14(v\xb3v\xba\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92v\x14\xdb\xd4\xdb\x14\x14yyyyyyyyyyyyyyyyyyyyyyyyyy\xbc\x14/A\x08' +'A\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\xbc\xd4/\xd4\xbc/\xc2\xc0\x1a\xc2\x10DDDDDDDDDD\xd1DDDDDDDDDDDDDDD' +'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\xd1\xd1DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD]' +"]]DDDDDD]]DDDDDD]]DDDDDD]]DDD]]]\xab\xab\xd4A \xab\xab]'\xb7\xb7\xb7\xb7'']]]]]]]]]]mmm4{]]" +'9999999999999999999999999999999]\xb0\xb0\xb0\xb0]]]]]]]]]]]]9999999999999999' +'9999999999[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, +'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02]]zzzzzzzzzzzzzzzzzzzzzzzz' +'zzzzzzzzzzzzzz]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]\xb0\xb0\xb0\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88\x88' -'\x88\x88\x88\x88\x88\x88\x88\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d~~III\x9d\x9d\x9d*~~~~~mmmmmmmm\x99\x99\x99\x99\x99' +'\x99\x99\x99\x9d\x9d\x95\x95\x95\x95\x95\x99\x99\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x95\x95\x95\x95\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' +'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' +'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzz]zzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' +'\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02]\x02\x02]]\x02]]\x02\x02]]\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02\x02zzzz]z]zzz' +'z]zz]zzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzz' +'zzzz\x02\x02]\x02\x02\x02\x02]]\x02\x02\x02\x02\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02]\x02\x02\x02\x02]' +'\x02\x02\x02\x02\x02]\x02]]]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' +'\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzz' +'zzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzz' +'zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02' +'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' +'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' +'\x02xzzzzzzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzz' +'zzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzz' +'zzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzz' +'zzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzzzzzzzz' +'zzzxzzzzzz]]]]66666666666666666666666666666666666666666666666666' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' +'LLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7' -'\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7' -'\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7' -'\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7' -, -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -, -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -':::::::\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0:::::\xb0\xb0\xb0\xb0\xb0040000000000\xd80000000000000\xb000000\xb00\xb0' -'00\xb000\xb00000000000\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -, -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -, -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xaf\x94' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x91\xb0\xb0\xb0' -, -'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0WWWW\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x8b\xa8\xa8\xc8\xc8\x12\x06\x12\x06\x12\x06\x12\x06\x12\x06\x12' -'\x06\x12\x06\x12\x06\x8b\x8b\xb0\xb0\x8b\x8b\x8b\x8b\xc8\xc8\xc8n\x8bn\xb0\x8bn\x8b\x8b\xa8\x12\x06\x12\x06\x12\x06\xd4\x8b\x8b\x16\xb8\xc1\xc1\xc1\xb0\x8b}\xd4\x8b\xb0\xb0\xb0\xb0\x9f\x9f\x9f\x9f\x9f\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f' -'\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\x1e' -, -'\xb0\x0e\x0e\xc0\x8c\xc0\x0e\x0e\xccv\x0e\xb5\xa1\x9c\xa1o\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\xa1\x0e\x1d\xb1\x1d\x0e\x0e\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xcc\x0evb9' -'b\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\xcc\xb1v\xb1\xccv\xc9\xb4\x90\xc9p\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x1c\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a' -'\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x1c\x1c\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\xb0' -'\xb0\xb0\x9a\x9a\x9a\x9a\x9a\x9a\xb0\xb0\x9a\x9a\x9a\x9a\x9a\x9a\xb0\xb0\x9a\x9a\x9a\x9a\x9a\x9a\xb0\xb0\x9a\x9a\x9a\xb0\xb0\xb0\x8c\x8c\xb1b\x03\x8c\x8c\xb0\xcb\xb9\xb9\xb9\xb9\xcb\xcb\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x1e\x1e\x1e\xa5\xd7\xb0\xb0' -, -'\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xb0eeee\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3' -'\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xbc\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'______________________________________\xb0\xb0::::::::::::::::::::::::' -'::::::::::::::\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG' -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG' -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG' -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\xb0\xb0\xb0GGGGGGGGGGGGGGGGGGGGGG' -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\xd9\xd9 GGGj\xd9\xd9\xd9\xd9\xd9\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1eTTTTT' -'TTTGGWWWWWTTGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGWWWWGGGGGGGGGGGGGGGGGG' -'GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'__________________________::::::::::::::::::::::::::____________' -'______________:::::::\xb0::::::::::::::::::________________________' -'__::::::::::::::::::::::::::_\xb0__\xb0\xb0_\xb0\xb0__\xb0\xb0____\xb0________::::\xb0:\xb0:::' -':\xb0::\xb0:::::::::::__________________________::::::::::::::::::::::' -, -'::::__\xb0____\xb0\xb0________\xb0_______\xb0::::::::::::::::::::::::::__\xb0____\xb0' -'_____\xb0_\xb0\xb0\xb0_______\xb0::::::::::::::::::::::::::____________________' -'______::::::::::::::::::::::::::__________________________::::::' -'::::::::::::::::::::__________________________::::::::::::::::::' -, -'::::::::__________________________::::::::::::::::::::::::::____' -'______________________::::::::::::::::::::::::::________________' -'__________::::::::::::::::::::::::::\xb0\xb0\xb0\xb0________________________' -'_F:::::::::::::::::::::::::F::::::_________________________F::::' -, -':::::::::::::::::::::F::::::_________________________F::::::::::' -':::::::::::::::F::::::_________________________F::::::::::::::::' -':::::::::F::::::_________________________F::::::::::::::::::::::' -':::F::::::\xb0\xb0\xb0\xb0\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae' -, ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' +']m]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' +'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' ']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'\xb0\x1e\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' -'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -'\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -, -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII' -'IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII\xb0\xb0' -, +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' +'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]]' ) def _get_record(code): - return _db_records[ord(_db_pages[ord(_db_pgtbl[code >> 8])][code & 255])] + return _db_records[ord(_db_pages[(ord(_db_pgtbl[code >> 8]) << 8) + (code & 255)])] def category(code): return _get_record(code)[0] def bidirectional(code): return _get_record(code)[1] @@ -24051,7077 +23973,7077 @@ } _canon_decomposition = { -192: (65, 768), -193: (65, 769), -194: (65, 770), -195: (65, 771), -196: (65, 776), -197: (65, 778), -199: (67, 807), -200: (69, 768), -201: (69, 769), -202: (69, 770), -203: (69, 776), -204: (73, 768), -205: (73, 769), -206: (73, 770), -207: (73, 776), -209: (78, 771), -210: (79, 768), -211: (79, 769), -212: (79, 770), -213: (79, 771), -214: (79, 776), -217: (85, 768), -218: (85, 769), -219: (85, 770), -220: (85, 776), -221: (89, 769), -224: (97, 768), -225: (97, 769), -226: (97, 770), -227: (97, 771), -228: (97, 776), -229: (97, 778), -231: (99, 807), -232: (101, 768), -233: (101, 769), -234: (101, 770), -235: (101, 776), -236: (105, 768), -237: (105, 769), -238: (105, 770), -239: (105, 776), -241: (110, 771), -242: (111, 768), -243: (111, 769), -244: (111, 770), -245: (111, 771), -246: (111, 776), -249: (117, 768), -250: (117, 769), -251: (117, 770), -252: (117, 776), -253: (121, 769), -255: (121, 776), -256: (65, 772), -257: (97, 772), -258: (65, 774), -259: (97, 774), -260: (65, 808), -261: (97, 808), -262: (67, 769), -263: (99, 769), -264: (67, 770), -265: (99, 770), -266: (67, 775), -267: (99, 775), -268: (67, 780), -269: (99, 780), -270: (68, 780), -271: (100, 780), -274: (69, 772), -275: (101, 772), -276: (69, 774), -277: (101, 774), -278: (69, 775), -279: (101, 775), -280: (69, 808), -281: (101, 808), -282: (69, 780), -283: (101, 780), -284: (71, 770), -285: (103, 770), -286: (71, 774), -287: (103, 774), -288: (71, 775), -289: (103, 775), -290: (71, 807), -291: (103, 807), -292: (72, 770), -293: (104, 770), -296: (73, 771), -297: (105, 771), -298: (73, 772), -299: (105, 772), -300: (73, 774), -301: (105, 774), -302: (73, 808), -303: (105, 808), -304: (73, 775), -308: (74, 770), -309: (106, 770), -310: (75, 807), -311: (107, 807), -313: (76, 769), -314: (108, 769), -315: (76, 807), -316: (108, 807), -317: (76, 780), -318: (108, 780), -323: (78, 769), -324: (110, 769), -325: (78, 807), -326: (110, 807), -327: (78, 780), -328: (110, 780), -332: (79, 772), -333: (111, 772), -334: (79, 774), -335: (111, 774), -336: (79, 779), -337: (111, 779), -340: (82, 769), -341: (114, 769), -342: (82, 807), -343: (114, 807), -344: (82, 780), -345: (114, 780), -346: (83, 769), -347: (115, 769), -348: (83, 770), -349: (115, 770), -350: (83, 807), -351: (115, 807), -352: (83, 780), -353: (115, 780), -354: (84, 807), -355: (116, 807), -356: (84, 780), -357: (116, 780), -360: (85, 771), -361: (117, 771), -362: (85, 772), -363: (117, 772), -364: (85, 774), -365: (117, 774), -366: (85, 778), -367: (117, 778), -368: (85, 779), -369: (117, 779), -370: (85, 808), -371: (117, 808), -372: (87, 770), -373: (119, 770), -374: (89, 770), -375: (121, 770), -376: (89, 776), -377: (90, 769), -378: (122, 769), -379: (90, 775), -380: (122, 775), -381: (90, 780), -382: (122, 780), -416: (79, 795), -417: (111, 795), -431: (85, 795), -432: (117, 795), -461: (65, 780), -462: (97, 780), -463: (73, 780), -464: (105, 780), -465: (79, 780), -466: (111, 780), -467: (85, 780), -468: (117, 780), -469: (85, 776, 772), -470: (117, 776, 772), -471: (85, 776, 769), -472: (117, 776, 769), -473: (85, 776, 780), -474: (117, 776, 780), -475: (85, 776, 768), -476: (117, 776, 768), -478: (65, 776, 772), -479: (97, 776, 772), -480: (65, 775, 772), -481: (97, 775, 772), -482: (198, 772), -483: (230, 772), -486: (71, 780), -487: (103, 780), -488: (75, 780), -489: (107, 780), -490: (79, 808), -491: (111, 808), -492: (79, 808, 772), -493: (111, 808, 772), -494: (439, 780), -495: (658, 780), -496: (106, 780), -500: (71, 769), -501: (103, 769), -504: (78, 768), -505: (110, 768), -506: (65, 778, 769), -507: (97, 778, 769), -508: (198, 769), -509: (230, 769), -510: (216, 769), -511: (248, 769), -512: (65, 783), -513: (97, 783), -514: (65, 785), -515: (97, 785), -516: (69, 783), -517: (101, 783), -518: (69, 785), -519: (101, 785), -520: (73, 783), -521: (105, 783), -522: (73, 785), -523: (105, 785), -524: (79, 783), -525: (111, 783), -526: (79, 785), -527: (111, 785), -528: (82, 783), -529: (114, 783), -530: (82, 785), -531: (114, 785), -532: (85, 783), -533: (117, 783), -534: (85, 785), -535: (117, 785), -536: (83, 806), -537: (115, 806), -538: (84, 806), -539: (116, 806), -542: (72, 780), -543: (104, 780), -550: (65, 775), -551: (97, 775), -552: (69, 807), -553: (101, 807), -554: (79, 776, 772), -555: (111, 776, 772), -556: (79, 771, 772), -557: (111, 771, 772), -558: (79, 775), -559: (111, 775), -560: (79, 775, 772), -561: (111, 775, 772), -562: (89, 772), -563: (121, 772), -832: (768,), -833: (769,), -835: (787,), -836: (776, 769), -884: (697,), -894: (59,), -901: (168, 769), -902: (913, 769), -903: (183,), -904: (917, 769), -905: (919, 769), -906: (921, 769), -908: (927, 769), -910: (933, 769), -911: (937, 769), -912: (953, 776, 769), -938: (921, 776), -939: (933, 776), -940: (945, 769), -941: (949, 769), -942: (951, 769), -943: (953, 769), -944: (965, 776, 769), -970: (953, 776), -971: (965, 776), -972: (959, 769), -973: (965, 769), -974: (969, 769), -979: (978, 769), -980: (978, 776), -1024: (1045, 768), -1025: (1045, 776), -1027: (1043, 769), -1031: (1030, 776), -1036: (1050, 769), -1037: (1048, 768), -1038: (1059, 774), -1049: (1048, 774), -1081: (1080, 774), -1104: (1077, 768), -1105: (1077, 776), -1107: (1075, 769), -1111: (1110, 776), -1116: (1082, 769), -1117: (1080, 768), -1118: (1091, 774), -1142: (1140, 783), -1143: (1141, 783), -1217: (1046, 774), -1218: (1078, 774), -1232: (1040, 774), -1233: (1072, 774), -1234: (1040, 776), -1235: (1072, 776), -1238: (1045, 774), -1239: (1077, 774), -1242: (1240, 776), -1243: (1241, 776), -1244: (1046, 776), -1245: (1078, 776), -1246: (1047, 776), -1247: (1079, 776), -1250: (1048, 772), -1251: (1080, 772), -1252: (1048, 776), -1253: (1080, 776), -1254: (1054, 776), -1255: (1086, 776), -1258: (1256, 776), -1259: (1257, 776), -1260: (1069, 776), -1261: (1101, 776), -1262: (1059, 772), -1263: (1091, 772), -1264: (1059, 776), -1265: (1091, 776), -1266: (1059, 779), -1267: (1091, 779), -1268: (1063, 776), -1269: (1095, 776), -1272: (1067, 776), -1273: (1099, 776), -1570: (1575, 1619), -1571: (1575, 1620), -1572: (1608, 1620), -1573: (1575, 1621), -1574: (1610, 1620), -1728: (1749, 1620), -1730: (1729, 1620), -1747: (1746, 1620), -2345: (2344, 2364), -2353: (2352, 2364), -2356: (2355, 2364), -2392: (2325, 2364), -2393: (2326, 2364), -2394: (2327, 2364), -2395: (2332, 2364), -2396: (2337, 2364), -2397: (2338, 2364), -2398: (2347, 2364), -2399: (2351, 2364), -2507: (2503, 2494), -2508: (2503, 2519), -2524: (2465, 2492), -2525: (2466, 2492), -2527: (2479, 2492), -2611: (2610, 2620), -2614: (2616, 2620), -2649: (2582, 2620), -2650: (2583, 2620), -2651: (2588, 2620), -2654: (2603, 2620), -2888: (2887, 2902), -2891: (2887, 2878), -2892: (2887, 2903), -2908: (2849, 2876), -2909: (2850, 2876), -2964: (2962, 3031), -3018: (3014, 3006), -3019: (3015, 3006), -3020: (3014, 3031), -3144: (3142, 3158), -3264: (3263, 3285), -3271: (3270, 3285), -3272: (3270, 3286), -3274: (3270, 3266), -3275: (3270, 3266, 3285), -3402: (3398, 3390), -3403: (3399, 3390), -3404: (3398, 3415), -3546: (3545, 3530), -3548: (3545, 3535), -3549: (3545, 3535, 3530), -3550: (3545, 3551), -3907: (3906, 4023), -3917: (3916, 4023), -3922: (3921, 4023), -3927: (3926, 4023), -3932: (3931, 4023), -3945: (3904, 4021), -3955: (3953, 3954), -3957: (3953, 3956), -3958: (4018, 3968), -3960: (4019, 3968), -3969: (3953, 3968), -3987: (3986, 4023), -3997: (3996, 4023), -4002: (4001, 4023), -4007: (4006, 4023), -4012: (4011, 4023), -4025: (3984, 4021), -4134: (4133, 4142), -7680: (65, 805), -7681: (97, 805), -7682: (66, 775), -7683: (98, 775), -7684: (66, 803), -7685: (98, 803), -7686: (66, 817), -7687: (98, 817), -7688: (67, 807, 769), -7689: (99, 807, 769), -7690: (68, 775), -7691: (100, 775), -7692: (68, 803), -7693: (100, 803), -7694: (68, 817), -7695: (100, 817), -7696: (68, 807), -7697: (100, 807), -7698: (68, 813), -7699: (100, 813), -7700: (69, 772, 768), -7701: (101, 772, 768), -7702: (69, 772, 769), -7703: (101, 772, 769), -7704: (69, 813), -7705: (101, 813), -7706: (69, 816), -7707: (101, 816), -7708: (69, 807, 774), -7709: (101, 807, 774), -7710: (70, 775), -7711: (102, 775), -7712: (71, 772), -7713: (103, 772), -7714: (72, 775), -7715: (104, 775), -7716: (72, 803), -7717: (104, 803), -7718: (72, 776), -7719: (104, 776), -7720: (72, 807), -7721: (104, 807), -7722: (72, 814), -7723: (104, 814), -7724: (73, 816), -7725: (105, 816), -7726: (73, 776, 769), -7727: (105, 776, 769), -7728: (75, 769), -7729: (107, 769), -7730: (75, 803), -7731: (107, 803), -7732: (75, 817), -7733: (107, 817), -7734: (76, 803), -7735: (108, 803), -7736: (76, 803, 772), -7737: (108, 803, 772), -7738: (76, 817), -7739: (108, 817), -7740: (76, 813), -7741: (108, 813), -7742: (77, 769), -7743: (109, 769), -7744: (77, 775), -7745: (109, 775), -7746: (77, 803), -7747: (109, 803), -7748: (78, 775), -7749: (110, 775), -7750: (78, 803), -7751: (110, 803), -7752: (78, 817), -7753: (110, 817), -7754: (78, 813), -7755: (110, 813), -7756: (79, 771, 769), -7757: (111, 771, 769), -7758: (79, 771, 776), -7759: (111, 771, 776), -7760: (79, 772, 768), -7761: (111, 772, 768), -7762: (79, 772, 769), -7763: (111, 772, 769), -7764: (80, 769), -7765: (112, 769), -7766: (80, 775), -7767: (112, 775), -7768: (82, 775), -7769: (114, 775), -7770: (82, 803), -7771: (114, 803), -7772: (82, 803, 772), -7773: (114, 803, 772), -7774: (82, 817), -7775: (114, 817), -7776: (83, 775), -7777: (115, 775), -7778: (83, 803), -7779: (115, 803), -7780: (83, 769, 775), -7781: (115, 769, 775), -7782: (83, 780, 775), -7783: (115, 780, 775), -7784: (83, 803, 775), -7785: (115, 803, 775), -7786: (84, 775), -7787: (116, 775), -7788: (84, 803), -7789: (116, 803), -7790: (84, 817), -7791: (116, 817), -7792: (84, 813), -7793: (116, 813), -7794: (85, 804), -7795: (117, 804), -7796: (85, 816), -7797: (117, 816), -7798: (85, 813), -7799: (117, 813), -7800: (85, 771, 769), -7801: (117, 771, 769), -7802: (85, 772, 776), -7803: (117, 772, 776), -7804: (86, 771), -7805: (118, 771), -7806: (86, 803), -7807: (118, 803), -7808: (87, 768), -7809: (119, 768), -7810: (87, 769), -7811: (119, 769), -7812: (87, 776), -7813: (119, 776), -7814: (87, 775), -7815: (119, 775), -7816: (87, 803), -7817: (119, 803), -7818: (88, 775), -7819: (120, 775), -7820: (88, 776), -7821: (120, 776), -7822: (89, 775), -7823: (121, 775), -7824: (90, 770), -7825: (122, 770), -7826: (90, 803), -7827: (122, 803), -7828: (90, 817), -7829: (122, 817), -7830: (104, 817), -7831: (116, 776), -7832: (119, 778), -7833: (121, 778), -7835: (383, 775), -7840: (65, 803), -7841: (97, 803), -7842: (65, 777), -7843: (97, 777), -7844: (65, 770, 769), -7845: (97, 770, 769), -7846: (65, 770, 768), -7847: (97, 770, 768), -7848: (65, 770, 777), -7849: (97, 770, 777), -7850: (65, 770, 771), -7851: (97, 770, 771), -7852: (65, 803, 770), -7853: (97, 803, 770), -7854: (65, 774, 769), -7855: (97, 774, 769), -7856: (65, 774, 768), -7857: (97, 774, 768), -7858: (65, 774, 777), -7859: (97, 774, 777), -7860: (65, 774, 771), -7861: (97, 774, 771), -7862: (65, 803, 774), -7863: (97, 803, 774), -7864: (69, 803), -7865: (101, 803), -7866: (69, 777), -7867: (101, 777), -7868: (69, 771), -7869: (101, 771), -7870: (69, 770, 769), -7871: (101, 770, 769), -7872: (69, 770, 768), -7873: (101, 770, 768), -7874: (69, 770, 777), -7875: (101, 770, 777), -7876: (69, 770, 771), -7877: (101, 770, 771), -7878: (69, 803, 770), -7879: (101, 803, 770), -7880: (73, 777), -7881: (105, 777), -7882: (73, 803), -7883: (105, 803), -7884: (79, 803), -7885: (111, 803), -7886: (79, 777), -7887: (111, 777), -7888: (79, 770, 769), -7889: (111, 770, 769), -7890: (79, 770, 768), -7891: (111, 770, 768), -7892: (79, 770, 777), -7893: (111, 770, 777), -7894: (79, 770, 771), -7895: (111, 770, 771), -7896: (79, 803, 770), -7897: (111, 803, 770), -7898: (79, 795, 769), -7899: (111, 795, 769), -7900: (79, 795, 768), -7901: (111, 795, 768), -7902: (79, 795, 777), -7903: (111, 795, 777), -7904: (79, 795, 771), -7905: (111, 795, 771), -7906: (79, 795, 803), -7907: (111, 795, 803), -7908: (85, 803), -7909: (117, 803), -7910: (85, 777), -7911: (117, 777), -7912: (85, 795, 769), -7913: (117, 795, 769), -7914: (85, 795, 768), -7915: (117, 795, 768), -7916: (85, 795, 777), -7917: (117, 795, 777), -7918: (85, 795, 771), -7919: (117, 795, 771), -7920: (85, 795, 803), -7921: (117, 795, 803), -7922: (89, 768), -7923: (121, 768), -7924: (89, 803), -7925: (121, 803), -7926: (89, 777), -7927: (121, 777), -7928: (89, 771), -7929: (121, 771), -7936: (945, 787), -7937: (945, 788), -7938: (945, 787, 768), -7939: (945, 788, 768), -7940: (945, 787, 769), -7941: (945, 788, 769), -7942: (945, 787, 834), -7943: (945, 788, 834), -7944: (913, 787), -7945: (913, 788), -7946: (913, 787, 768), -7947: (913, 788, 768), -7948: (913, 787, 769), -7949: (913, 788, 769), -7950: (913, 787, 834), -7951: (913, 788, 834), -7952: (949, 787), -7953: (949, 788), -7954: (949, 787, 768), -7955: (949, 788, 768), -7956: (949, 787, 769), -7957: (949, 788, 769), -7960: (917, 787), -7961: (917, 788), -7962: (917, 787, 768), -7963: (917, 788, 768), -7964: (917, 787, 769), -7965: (917, 788, 769), -7968: (951, 787), -7969: (951, 788), -7970: (951, 787, 768), -7971: (951, 788, 768), -7972: (951, 787, 769), -7973: (951, 788, 769), -7974: (951, 787, 834), -7975: (951, 788, 834), -7976: (919, 787), -7977: (919, 788), -7978: (919, 787, 768), -7979: (919, 788, 768), -7980: (919, 787, 769), -7981: (919, 788, 769), -7982: (919, 787, 834), -7983: (919, 788, 834), -7984: (953, 787), -7985: (953, 788), -7986: (953, 787, 768), -7987: (953, 788, 768), -7988: (953, 787, 769), -7989: (953, 788, 769), -7990: (953, 787, 834), -7991: (953, 788, 834), -7992: (921, 787), -7993: (921, 788), -7994: (921, 787, 768), -7995: (921, 788, 768), -7996: (921, 787, 769), -7997: (921, 788, 769), -7998: (921, 787, 834), -7999: (921, 788, 834), -8000: (959, 787), -8001: (959, 788), -8002: (959, 787, 768), -8003: (959, 788, 768), -8004: (959, 787, 769), -8005: (959, 788, 769), -8008: (927, 787), -8009: (927, 788), -8010: (927, 787, 768), -8011: (927, 788, 768), -8012: (927, 787, 769), -8013: (927, 788, 769), -8016: (965, 787), -8017: (965, 788), -8018: (965, 787, 768), -8019: (965, 788, 768), -8020: (965, 787, 769), -8021: (965, 788, 769), -8022: (965, 787, 834), -8023: (965, 788, 834), -8025: (933, 788), -8027: (933, 788, 768), -8029: (933, 788, 769), -8031: (933, 788, 834), -8032: (969, 787), -8033: (969, 788), -8034: (969, 787, 768), -8035: (969, 788, 768), -8036: (969, 787, 769), -8037: (969, 788, 769), -8038: (969, 787, 834), -8039: (969, 788, 834), -8040: (937, 787), -8041: (937, 788), -8042: (937, 787, 768), -8043: (937, 788, 768), -8044: (937, 787, 769), -8045: (937, 788, 769), -8046: (937, 787, 834), -8047: (937, 788, 834), -8048: (945, 768), -8049: (945, 769), -8050: (949, 768), -8051: (949, 769), -8052: (951, 768), -8053: (951, 769), -8054: (953, 768), -8055: (953, 769), -8056: (959, 768), -8057: (959, 769), -8058: (965, 768), -8059: (965, 769), -8060: (969, 768), -8061: (969, 769), -8064: (945, 787, 837), -8065: (945, 788, 837), -8066: (945, 787, 768, 837), -8067: (945, 788, 768, 837), -8068: (945, 787, 769, 837), -8069: (945, 788, 769, 837), -8070: (945, 787, 834, 837), -8071: (945, 788, 834, 837), -8072: (913, 787, 837), -8073: (913, 788, 837), -8074: (913, 787, 768, 837), -8075: (913, 788, 768, 837), -8076: (913, 787, 769, 837), -8077: (913, 788, 769, 837), -8078: (913, 787, 834, 837), -8079: (913, 788, 834, 837), -8080: (951, 787, 837), -8081: (951, 788, 837), -8082: (951, 787, 768, 837), -8083: (951, 788, 768, 837), -8084: (951, 787, 769, 837), -8085: (951, 788, 769, 837), -8086: (951, 787, 834, 837), -8087: (951, 788, 834, 837), -8088: (919, 787, 837), -8089: (919, 788, 837), -8090: (919, 787, 768, 837), -8091: (919, 788, 768, 837), -8092: (919, 787, 769, 837), -8093: (919, 788, 769, 837), -8094: (919, 787, 834, 837), -8095: (919, 788, 834, 837), -8096: (969, 787, 837), -8097: (969, 788, 837), -8098: (969, 787, 768, 837), -8099: (969, 788, 768, 837), -8100: (969, 787, 769, 837), -8101: (969, 788, 769, 837), -8102: (969, 787, 834, 837), -8103: (969, 788, 834, 837), -8104: (937, 787, 837), -8105: (937, 788, 837), -8106: (937, 787, 768, 837), -8107: (937, 788, 768, 837), -8108: (937, 787, 769, 837), -8109: (937, 788, 769, 837), -8110: (937, 787, 834, 837), -8111: (937, 788, 834, 837), -8112: (945, 774), -8113: (945, 772), -8114: (945, 768, 837), -8115: (945, 837), -8116: (945, 769, 837), -8118: (945, 834), -8119: (945, 834, 837), -8120: (913, 774), -8121: (913, 772), -8122: (913, 768), -8123: (913, 769), -8124: (913, 837), -8126: (953,), -8129: (168, 834), -8130: (951, 768, 837), -8131: (951, 837), -8132: (951, 769, 837), -8134: (951, 834), -8135: (951, 834, 837), -8136: (917, 768), -8137: (917, 769), -8138: (919, 768), -8139: (919, 769), -8140: (919, 837), -8141: (8127, 768), -8142: (8127, 769), -8143: (8127, 834), -8144: (953, 774), -8145: (953, 772), -8146: (953, 776, 768), -8147: (953, 776, 769), -8150: (953, 834), -8151: (953, 776, 834), -8152: (921, 774), -8153: (921, 772), -8154: (921, 768), -8155: (921, 769), -8157: (8190, 768), -8158: (8190, 769), -8159: (8190, 834), -8160: (965, 774), -8161: (965, 772), -8162: (965, 776, 768), -8163: (965, 776, 769), -8164: (961, 787), -8165: (961, 788), -8166: (965, 834), -8167: (965, 776, 834), -8168: (933, 774), -8169: (933, 772), -8170: (933, 768), -8171: (933, 769), -8172: (929, 788), -8173: (168, 768), -8174: (168, 769), -8175: (96,), -8178: (969, 768, 837), -8179: (969, 837), -8180: (969, 769, 837), -8182: (969, 834), -8183: (969, 834, 837), -8184: (927, 768), -8185: (927, 769), -8186: (937, 768), -8187: (937, 769), -8188: (937, 837), -8189: (180,), -8192: (8194,), -8193: (8195,), -8486: (937,), -8490: (75,), -8491: (65, 778), -8602: (8592, 824), -8603: (8594, 824), -8622: (8596, 824), -8653: (8656, 824), -8654: (8660, 824), -8655: (8658, 824), -8708: (8707, 824), -8713: (8712, 824), -8716: (8715, 824), -8740: (8739, 824), -8742: (8741, 824), -8769: (8764, 824), -8772: (8771, 824), -8775: (8773, 824), -8777: (8776, 824), -8800: (61, 824), -8802: (8801, 824), -8813: (8781, 824), -8814: (60, 824), -8815: (62, 824), -8816: (8804, 824), -8817: (8805, 824), -8820: (8818, 824), -8821: (8819, 824), -8824: (8822, 824), -8825: (8823, 824), -8832: (8826, 824), -8833: (8827, 824), -8836: (8834, 824), -8837: (8835, 824), -8840: (8838, 824), -8841: (8839, 824), -8876: (8866, 824), -8877: (8872, 824), -8878: (8873, 824), -8879: (8875, 824), -8928: (8828, 824), -8929: (8829, 824), -8930: (8849, 824), -8931: (8850, 824), -8938: (8882, 824), -8939: (8883, 824), -8940: (8884, 824), -8941: (8885, 824), -9001: (12296,), -9002: (12297,), -10972: (10973, 824), -12364: (12363, 12441), -12366: (12365, 12441), -12368: (12367, 12441), -12370: (12369, 12441), -12372: (12371, 12441), -12374: (12373, 12441), -12376: (12375, 12441), -12378: (12377, 12441), -12380: (12379, 12441), -12382: (12381, 12441), -12384: (12383, 12441), -12386: (12385, 12441), -12389: (12388, 12441), -12391: (12390, 12441), -12393: (12392, 12441), -12400: (12399, 12441), -12401: (12399, 12442), -12403: (12402, 12441), -12404: (12402, 12442), -12406: (12405, 12441), -12407: (12405, 12442), -12409: (12408, 12441), -12410: (12408, 12442), -12412: (12411, 12441), -12413: (12411, 12442), -12436: (12358, 12441), -12446: (12445, 12441), -12460: (12459, 12441), -12462: (12461, 12441), -12464: (12463, 12441), -12466: (12465, 12441), -12468: (12467, 12441), -12470: (12469, 12441), -12472: (12471, 12441), -12474: (12473, 12441), -12476: (12475, 12441), -12478: (12477, 12441), -12480: (12479, 12441), -12482: (12481, 12441), -12485: (12484, 12441), -12487: (12486, 12441), -12489: (12488, 12441), -12496: (12495, 12441), -12497: (12495, 12442), -12499: (12498, 12441), -12500: (12498, 12442), -12502: (12501, 12441), -12503: (12501, 12442), -12505: (12504, 12441), -12506: (12504, 12442), -12508: (12507, 12441), -12509: (12507, 12442), -12532: (12454, 12441), -12535: (12527, 12441), -12536: (12528, 12441), -12537: (12529, 12441), -12538: (12530, 12441), -12542: (12541, 12441), -63744: (35912,), -63745: (26356,), -63746: (36554,), -63747: (36040,), -63748: (28369,), -63749: (20018,), -63750: (21477,), -63751: (40860,), -63752: (40860,), -63753: (22865,), -63754: (37329,), -63755: (21895,), -63756: (22856,), -63757: (25078,), -63758: (30313,), -63759: (32645,), -63760: (34367,), -63761: (34746,), -63762: (35064,), -63763: (37007,), -63764: (27138,), -63765: (27931,), -63766: (28889,), -63767: (29662,), -63768: (33853,), -63769: (37226,), -63770: (39409,), -63771: (20098,), -63772: (21365,), -63773: (27396,), -63774: (29211,), -63775: (34349,), -63776: (40478,), -63777: (23888,), -63778: (28651,), -63779: (34253,), -63780: (35172,), -63781: (25289,), -63782: (33240,), -63783: (34847,), -63784: (24266,), -63785: (26391,), -63786: (28010,), -63787: (29436,), -63788: (37070,), -63789: (20358,), -63790: (20919,), -63791: (21214,), -63792: (25796,), -63793: (27347,), -63794: (29200,), -63795: (30439,), -63796: (32769,), -63797: (34310,), -63798: (34396,), -63799: (36335,), -63800: (38706,), -63801: (39791,), -63802: (40442,), -63803: (30860,), -63804: (31103,), -63805: (32160,), -63806: (33737,), -63807: (37636,), -63808: (40575,), -63809: (35542,), -63810: (22751,), -63811: (24324,), -63812: (31840,), -63813: (32894,), -63814: (29282,), -63815: (30922,), -63816: (36034,), -63817: (38647,), -63818: (22744,), -63819: (23650,), -63820: (27155,), -63821: (28122,), -63822: (28431,), -63823: (32047,), -63824: (32311,), -63825: (38475,), -63826: (21202,), -63827: (32907,), -63828: (20956,), -63829: (20940,), -63830: (31260,), -63831: (32190,), -63832: (33777,), -63833: (38517,), -63834: (35712,), -63835: (25295,), -63836: (27138,), -63837: (35582,), -63838: (20025,), -63839: (23527,), -63840: (24594,), -63841: (29575,), -63842: (30064,), -63843: (21271,), -63844: (30971,), -63845: (20415,), -63846: (24489,), -63847: (19981,), -63848: (27852,), -63849: (25976,), -63850: (32034,), -63851: (21443,), -63852: (22622,), -63853: (30465,), -63854: (33865,), -63855: (35498,), -63856: (27578,), -63857: (36784,), -63858: (27784,), -63859: (25342,), -63860: (33509,), -63861: (25504,), -63862: (30053,), -63863: (20142,), -63864: (20841,), -63865: (20937,), -63866: (26753,), -63867: (31975,), -63868: (33391,), -63869: (35538,), -63870: (37327,), -63871: (21237,), -63872: (21570,), -63873: (22899,), -63874: (24300,), -63875: (26053,), -63876: (28670,), -63877: (31018,), -63878: (38317,), -63879: (39530,), -63880: (40599,), -63881: (40654,), -63882: (21147,), -63883: (26310,), -63884: (27511,), -63885: (36706,), -63886: (24180,), -63887: (24976,), -63888: (25088,), -63889: (25754,), -63890: (28451,), -63891: (29001,), -63892: (29833,), -63893: (31178,), -63894: (32244,), -63895: (32879,), -63896: (36646,), -63897: (34030,), -63898: (36899,), -63899: (37706,), -63900: (21015,), -63901: (21155,), -63902: (21693,), -63903: (28872,), -63904: (35010,), -63905: (35498,), -63906: (24265,), -63907: (24565,), -63908: (25467,), -63909: (27566,), -63910: (31806,), -63911: (29557,), -63912: (20196,), -63913: (22265,), -63914: (23527,), -63915: (23994,), -63916: (24604,), -63917: (29618,), -63918: (29801,), -63919: (32666,), -63920: (32838,), -63921: (37428,), -63922: (38646,), -63923: (38728,), -63924: (38936,), -63925: (20363,), -63926: (31150,), -63927: (37300,), -63928: (38584,), -63929: (24801,), -63930: (20102,), -63931: (20698,), -63932: (23534,), -63933: (23615,), -63934: (26009,), -63935: (27138,), -63936: (29134,), -63937: (30274,), -63938: (34044,), -63939: (36988,), -63940: (40845,), -63941: (26248,), -63942: (38446,), -63943: (21129,), -63944: (26491,), -63945: (26611,), -63946: (27969,), -63947: (28316,), -63948: (29705,), -63949: (30041,), -63950: (30827,), -63951: (32016,), -63952: (39006,), -63953: (20845,), -63954: (25134,), -63955: (38520,), -63956: (20523,), -63957: (23833,), -63958: (28138,), -63959: (36650,), -63960: (24459,), -63961: (24900,), -63962: (26647,), -63963: (29575,), -63964: (38534,), -63965: (21033,), -63966: (21519,), -63967: (23653,), -63968: (26131,), -63969: (26446,), -63970: (26792,), -63971: (27877,), -63972: (29702,), -63973: (30178,), -63974: (32633,), -63975: (35023,), -63976: (35041,), -63977: (37324,), -63978: (38626,), -63979: (21311,), -63980: (28346,), -63981: (21533,), -63982: (29136,), -63983: (29848,), -63984: (34298,), -63985: (38563,), -63986: (40023,), -63987: (40607,), -63988: (26519,), -63989: (28107,), -63990: (33256,), -63991: (31435,), -63992: (31520,), -63993: (31890,), -63994: (29376,), -63995: (28825,), -63996: (35672,), -63997: (20160,), -63998: (33590,), -63999: (21050,), -64000: (20999,), -64001: (24230,), -64002: (25299,), -64003: (31958,), -64004: (23429,), -64005: (27934,), -64006: (26292,), -64007: (36667,), -64008: (34892,), -64009: (38477,), -64010: (35211,), -64011: (24275,), -64012: (20800,), -64013: (21952,), -64016: (22618,), -64018: (26228,), -64021: (20958,), -64022: (29482,), -64023: (30410,), -64024: (31036,), -64025: (31070,), -64026: (31077,), -64027: (31119,), -64028: (38742,), -64029: (31934,), -64030: (32701,), -64032: (34322,), -64034: (35576,), -64037: (36920,), -64038: (37117,), -64042: (39151,), -64043: (39164,), -64044: (39208,), -64045: (40372,), -64048: (20398,), -64049: (20711,), -64050: (20813,), -64051: (21193,), -64052: (21220,), -64053: (21329,), -64054: (21917,), -64055: (22022,), -64056: (22120,), -64057: (22592,), -64058: (22696,), -64059: (23652,), -64060: (23662,), -64061: (24724,), -64062: (24936,), -64063: (24974,), -64064: (25074,), -64065: (25935,), -64066: (26082,), -64067: (26257,), -64068: (26757,), -64069: (28023,), -64070: (28186,), -64071: (28450,), -64072: (29038,), -64073: (29227,), -64074: (29730,), -64075: (30865,), -64076: (31038,), -64077: (31049,), -64078: (31048,), -64079: (31056,), -64080: (31062,), -64081: (31069,), -64082: (31117,), -64083: (31118,), -64084: (31296,), -64085: (31361,), -64086: (31680,), -64087: (32244,), -64088: (32265,), -64089: (32321,), -64090: (32626,), -64091: (32773,), -64092: (33261,), -64093: (33401,), -64094: (33401,), -64095: (33879,), -64096: (35088,), -64097: (35222,), -64098: (35585,), -64099: (35641,), -64100: (36051,), -64101: (36104,), -64102: (36790,), -64103: (36920,), -64104: (38627,), -64105: (38911,), -64106: (38971,), -64285: (1497, 1460), -64287: (1522, 1463), -64298: (1513, 1473), -64299: (1513, 1474), -64300: (1513, 1468, 1473), -64301: (1513, 1468, 1474), -64302: (1488, 1463), -64303: (1488, 1464), -64304: (1488, 1468), -64305: (1489, 1468), -64306: (1490, 1468), -64307: (1491, 1468), -64308: (1492, 1468), -64309: (1493, 1468), -64310: (1494, 1468), -64312: (1496, 1468), -64313: (1497, 1468), -64314: (1498, 1468), -64315: (1499, 1468), -64316: (1500, 1468), -64318: (1502, 1468), -64320: (1504, 1468), -64321: (1505, 1468), -64323: (1507, 1468), -64324: (1508, 1468), -64326: (1510, 1468), -64327: (1511, 1468), -64328: (1512, 1468), -64329: (1513, 1468), -64330: (1514, 1468), -64331: (1493, 1465), -64332: (1489, 1471), -64333: (1499, 1471), -64334: (1508, 1471), -119134: (119127, 119141), -119135: (119128, 119141), -119136: (119128, 119141, 119150), -119137: (119128, 119141, 119151), -119138: (119128, 119141, 119152), -119139: (119128, 119141, 119153), -119140: (119128, 119141, 119154), -119227: (119225, 119141), -119228: (119226, 119141), -119229: (119225, 119141, 119150), -119230: (119226, 119141, 119150), -119231: (119225, 119141, 119151), -119232: (119226, 119141, 119151), -194560: (20029,), -194561: (20024,), -194562: (20033,), -194563: (131362,), -194564: (20320,), -194565: (20398,), -194566: (20411,), -194567: (20482,), -194568: (20602,), -194569: (20633,), -194570: (20711,), -194571: (20687,), -194572: (13470,), -194573: (132666,), -194574: (20813,), -194575: (20820,), -194576: (20836,), -194577: (20855,), -194578: (132380,), -194579: (13497,), -194580: (20839,), -194581: (20877,), -194582: (132427,), -194583: (20887,), -194584: (20900,), -194585: (20172,), -194586: (20908,), -194587: (20917,), -194588: (168415,), -194589: (20981,), -194590: (20995,), -194591: (13535,), -194592: (21051,), -194593: (21062,), -194594: (21106,), -194595: (21111,), -194596: (13589,), -194597: (21191,), -194598: (21193,), -194599: (21220,), -194600: (21242,), -194601: (21253,), -194602: (21254,), -194603: (21271,), -194604: (21321,), -194605: (21329,), -194606: (21338,), -194607: (21363,), -194608: (21373,), -194609: (21375,), -194610: (21375,), -194611: (21375,), -194612: (133676,), -194613: (28784,), -194614: (21450,), -194615: (21471,), -194616: (133987,), -194617: (21483,), -194618: (21489,), -194619: (21510,), -194620: (21662,), -194621: (21560,), -194622: (21576,), -194623: (21608,), -194624: (21666,), -194625: (21750,), -194626: (21776,), -194627: (21843,), -194628: (21859,), -194629: (21892,), -194630: (21892,), -194631: (21913,), -194632: (21931,), -194633: (21939,), -194634: (21954,), -194635: (22294,), -194636: (22022,), -194637: (22295,), -194638: (22097,), -194639: (22132,), -194640: (20999,), -194641: (22766,), -194642: (22478,), -194643: (22516,), -194644: (22541,), -194645: (22411,), -194646: (22578,), -194647: (22577,), -194648: (22700,), -194649: (136420,), -194650: (22770,), -194651: (22775,), -194652: (22790,), -194653: (22810,), -194654: (22818,), -194655: (22882,), -194656: (136872,), -194657: (136938,), -194658: (23020,), -194659: (23067,), -194660: (23079,), -194661: (23000,), -194662: (23142,), -194663: (14062,), -194664: (136042,), -194665: (23304,), -194666: (23358,), -194667: (23358,), -194668: (137672,), -194669: (23491,), -194670: (23512,), -194671: (23527,), -194672: (23539,), -194673: (138008,), -194674: (23551,), -194675: (23558,), -194676: (24371,), -194677: (23586,), -194678: (14209,), -194679: (23648,), -194680: (23662,), -194681: (23744,), -194682: (23693,), -194683: (138724,), -194684: (23875,), -194685: (138726,), -194686: (23918,), -194687: (23915,), -194688: (23932,), -194689: (24033,), -194690: (24034,), -194691: (14383,), -194692: (24061,), -194693: (24104,), -194694: (24125,), -194695: (24169,), -194696: (14434,), -194697: (139651,), -194698: (14460,), -194699: (24240,), -194700: (24243,), -194701: (24246,), -194702: (24266,), -194703: (172946,), -194704: (24318,), -194705: (140081,), -194706: (140081,), -194707: (33281,), -194708: (24354,), -194709: (24354,), -194710: (14535,), -194711: (144056,), -194712: (156122,), -194713: (24418,), -194714: (24427,), -194715: (14563,), -194716: (24474,), -194717: (24525,), -194718: (24535,), -194719: (24569,), -194720: (24705,), -194721: (14650,), -194722: (14620,), -194723: (24724,), -194724: (141012,), -194725: (24775,), -194726: (24904,), -194727: (24908,), -194728: (24910,), -194729: (24908,), -194730: (24954,), -194731: (24974,), -194732: (25010,), -194733: (24996,), -194734: (25007,), -194735: (25054,), -194736: (25074,), -194737: (25078,), -194738: (25104,), -194739: (25115,), -194740: (25181,), -194741: (25265,), -194742: (25300,), -194743: (25424,), -194744: (142092,), -194745: (25405,), -194746: (25340,), -194747: (25448,), -194748: (25475,), -194749: (25572,), -194750: (142321,), -194751: (25634,), -194752: (25541,), -194753: (25513,), -194754: (14894,), -194755: (25705,), -194756: (25726,), -194757: (25757,), -194758: (25719,), -194759: (14956,), -194760: (25935,), -194761: (25964,), -194762: (143370,), -194763: (26083,), -194764: (26360,), -194765: (26185,), -194766: (15129,), -194767: (26257,), -194768: (15112,), -194769: (15076,), -194770: (20882,), -194771: (20885,), -194772: (26368,), -194773: (26268,), -194774: (32941,), -194775: (17369,), -194776: (26391,), -194777: (26395,), -194778: (26401,), -194779: (26462,), -194780: (26451,), -194781: (144323,), -194782: (15177,), -194783: (26618,), -194784: (26501,), -194785: (26706,), -194786: (26757,), -194787: (144493,), -194788: (26766,), -194789: (26655,), -194790: (26900,), -194791: (15261,), -194792: (26946,), -194793: (27043,), -194794: (27114,), -194795: (27304,), -194796: (145059,), -194797: (27355,), -194798: (15384,), -194799: (27425,), -194800: (145575,), -194801: (27476,), -194802: (15438,), -194803: (27506,), -194804: (27551,), -194805: (27578,), -194806: (27579,), -194807: (146061,), -194808: (138507,), -194809: (146170,), -194810: (27726,), -194811: (146620,), -194812: (27839,), -194813: (27853,), -194814: (27751,), -194815: (27926,), -194816: (27966,), -194817: (28023,), -194818: (27969,), -194819: (28009,), -194820: (28024,), -194821: (28037,), -194822: (146718,), -194823: (27956,), -194824: (28207,), -194825: (28270,), -194826: (15667,), -194827: (28363,), -194828: (28359,), -194829: (147153,), -194830: (28153,), -194831: (28526,), -194832: (147294,), -194833: (147342,), -194834: (28614,), -194835: (28729,), -194836: (28702,), -194837: (28699,), -194838: (15766,), -194839: (28746,), -194840: (28797,), -194841: (28791,), -194842: (28845,), -194843: (132389,), -194844: (28997,), -194845: (148067,), -194846: (29084,), -194847: (17323,), -194848: (29224,), -194849: (29237,), -194850: (29264,), -194851: (149000,), -194852: (29312,), -194853: (29333,), -194854: (149301,), -194855: (149524,), -194856: (29562,), -194857: (29579,), -194858: (16044,), -194859: (29605,), -194860: (16056,), -194861: (16056,), -194862: (29767,), -194863: (29788,), -194864: (29809,), -194865: (29829,), -194866: (29898,), -194867: (16155,), -194868: (29988,), -194869: (150582,), -194870: (30014,), -194871: (150674,), -194872: (30064,), -194873: (139679,), -194874: (30224,), -194875: (151457,), -194876: (151480,), -194877: (151620,), -194878: (16380,), -194879: (16392,), -194880: (30452,), -194881: (151795,), -194882: (151794,), -194883: (151833,), -194884: (151859,), -194885: (30494,), -194886: (30495,), -194887: (30495,), -194888: (30538,), -194889: (16441,), -194890: (30603,), -194891: (16454,), -194892: (16534,), -194893: (152605,), -194894: (30798,), -194895: (30860,), -194896: (30924,), -194897: (16611,), -194898: (153126,), -194899: (31062,), -194900: (153242,), -194901: (153285,), -194902: (31119,), -194903: (31211,), -194904: (16687,), -194905: (31296,), -194906: (31306,), -194907: (31311,), -194908: (153980,), -194909: (154279,), -194910: (154279,), -194911: (31406,), -194912: (16898,), -194913: (154539,), -194914: (31686,), -194915: (31689,), -194916: (16935,), -194917: (154752,), -194918: (31954,), -194919: (17056,), -194920: (31976,), -194921: (31971,), -194922: (32000,), -194923: (155526,), -194924: (32099,), -194925: (17153,), -194926: (32199,), -194927: (32258,), -194928: (32325,), -194929: (17204,), -194930: (156200,), -194931: (156231,), -194932: (17241,), -194933: (156377,), -194934: (32634,), -194935: (156478,), -194936: (32661,), -194937: (32762,), -194938: (32773,), -194939: (156890,), -194940: (156963,), -194941: (32864,), -194942: (157096,), -194943: (32880,), -194944: (144223,), -194945: (17365,), -194946: (32946,), -194947: (33027,), -194948: (17419,), -194949: (33086,), -194950: (23221,), -194951: (157607,), -194952: (157621,), -194953: (144275,), -194954: (144284,), -194955: (33281,), -194956: (33284,), -194957: (36766,), -194958: (17515,), -194959: (33425,), -194960: (33419,), -194961: (33437,), -194962: (21171,), -194963: (33457,), -194964: (33459,), -194965: (33469,), -194966: (33510,), -194967: (158524,), -194968: (33509,), -194969: (33565,), -194970: (33635,), -194971: (33709,), -194972: (33571,), -194973: (33725,), -194974: (33767,), -194975: (33879,), -194976: (33619,), -194977: (33738,), -194978: (33740,), -194979: (33756,), -194980: (158774,), -194981: (159083,), -194982: (158933,), -194983: (17707,), -194984: (34033,), -194985: (34035,), -194986: (34070,), -194987: (160714,), -194988: (34148,), -194989: (159532,), -194990: (17757,), -194991: (17761,), -194992: (159665,), -194993: (159954,), -194994: (17771,), -194995: (34384,), -194996: (34396,), -194997: (34407,), -194998: (34409,), -194999: (34473,), -195000: (34440,), -195001: (34574,), -195002: (34530,), -195003: (34681,), -195004: (34600,), -195005: (34667,), -195006: (34694,), -195007: (19799,), -195008: (34785,), -195009: (34817,), -195010: (17913,), -195011: (34912,), -195012: (34915,), -195013: (161383,), -195014: (35031,), -195015: (35038,), -195016: (17973,), -195017: (35066,), -195018: (13499,), -195019: (161966,), -195020: (162150,), -195021: (18110,), -195022: (18119,), -195023: (35488,), -195024: (35565,), -195025: (35722,), -195026: (35925,), -195027: (162984,), -195028: (36011,), -195029: (36033,), -195030: (36123,), -195031: (36215,), -195032: (163631,), -195033: (133124,), -195034: (36299,), -195035: (36284,), -195036: (36336,), -195037: (133342,), -195038: (36564,), -195039: (36664,), -195040: (165330,), -195041: (165357,), -195042: (37012,), -195043: (37105,), -195044: (37137,), -195045: (165678,), -195046: (37147,), -195047: (37432,), -195048: (37591,), -195049: (37592,), -195050: (37500,), -195051: (37881,), -195052: (37909,), -195053: (166906,), -195054: (38283,), -195055: (18837,), -195056: (38327,), -195057: (167287,), -195058: (18918,), -195059: (38595,), -195060: (23986,), -195061: (38691,), -195062: (168261,), -195063: (168474,), -195064: (19054,), -195065: (19062,), -195066: (38880,), -195067: (168970,), -195068: (19122,), -195069: (169110,), -195070: (38923,), -195071: (38923,), -195072: (38953,), -195073: (169398,), -195074: (39138,), -195075: (19251,), -195076: (39209,), -195077: (39335,), -195078: (39362,), -195079: (39422,), -195080: (19406,), -195081: (170800,), -195082: (39698,), -195083: (40000,), -195084: (40189,), -195085: (19662,), -195086: (19693,), -195087: (40295,), -195088: (172238,), -195089: (19704,), -195090: (172293,), -195091: (172558,), -195092: (172689,), -195093: (40635,), -195094: (19798,), -195095: (40697,), -195096: (40702,), -195097: (40709,), -195098: (40719,), -195099: (40726,), -195100: (40763,), -195101: (173568,), +192: [65, 768], +193: [65, 769], +194: [65, 770], +195: [65, 771], +196: [65, 776], +197: [65, 778], +199: [67, 807], +200: [69, 768], +201: [69, 769], +202: [69, 770], +203: [69, 776], +204: [73, 768], +205: [73, 769], +206: [73, 770], +207: [73, 776], +209: [78, 771], +210: [79, 768], +211: [79, 769], +212: [79, 770], +213: [79, 771], +214: [79, 776], +217: [85, 768], +218: [85, 769], +219: [85, 770], +220: [85, 776], +221: [89, 769], +224: [97, 768], +225: [97, 769], +226: [97, 770], +227: [97, 771], +228: [97, 776], +229: [97, 778], +231: [99, 807], +232: [101, 768], +233: [101, 769], +234: [101, 770], +235: [101, 776], +236: [105, 768], +237: [105, 769], +238: [105, 770], +239: [105, 776], +241: [110, 771], +242: [111, 768], +243: [111, 769], +244: [111, 770], +245: [111, 771], +246: [111, 776], +249: [117, 768], +250: [117, 769], +251: [117, 770], +252: [117, 776], +253: [121, 769], +255: [121, 776], +256: [65, 772], +257: [97, 772], +258: [65, 774], +259: [97, 774], +260: [65, 808], +261: [97, 808], +262: [67, 769], +263: [99, 769], +264: [67, 770], +265: [99, 770], +266: [67, 775], +267: [99, 775], +268: [67, 780], +269: [99, 780], +270: [68, 780], +271: [100, 780], +274: [69, 772], +275: [101, 772], +276: [69, 774], +277: [101, 774], +278: [69, 775], +279: [101, 775], +280: [69, 808], +281: [101, 808], +282: [69, 780], +283: [101, 780], +284: [71, 770], +285: [103, 770], +286: [71, 774], +287: [103, 774], +288: [71, 775], +289: [103, 775], +290: [71, 807], +291: [103, 807], +292: [72, 770], +293: [104, 770], +296: [73, 771], +297: [105, 771], +298: [73, 772], +299: [105, 772], +300: [73, 774], +301: [105, 774], +302: [73, 808], +303: [105, 808], +304: [73, 775], +308: [74, 770], +309: [106, 770], +310: [75, 807], +311: [107, 807], +313: [76, 769], +314: [108, 769], +315: [76, 807], +316: [108, 807], +317: [76, 780], +318: [108, 780], +323: [78, 769], +324: [110, 769], +325: [78, 807], +326: [110, 807], +327: [78, 780], +328: [110, 780], +332: [79, 772], +333: [111, 772], +334: [79, 774], +335: [111, 774], +336: [79, 779], +337: [111, 779], +340: [82, 769], +341: [114, 769], +342: [82, 807], +343: [114, 807], +344: [82, 780], +345: [114, 780], +346: [83, 769], +347: [115, 769], +348: [83, 770], +349: [115, 770], +350: [83, 807], +351: [115, 807], +352: [83, 780], +353: [115, 780], +354: [84, 807], +355: [116, 807], +356: [84, 780], +357: [116, 780], +360: [85, 771], +361: [117, 771], +362: [85, 772], +363: [117, 772], +364: [85, 774], +365: [117, 774], +366: [85, 778], +367: [117, 778], +368: [85, 779], +369: [117, 779], +370: [85, 808], +371: [117, 808], +372: [87, 770], +373: [119, 770], +374: [89, 770], +375: [121, 770], +376: [89, 776], +377: [90, 769], +378: [122, 769], +379: [90, 775], +380: [122, 775], +381: [90, 780], +382: [122, 780], +416: [79, 795], +417: [111, 795], +431: [85, 795], +432: [117, 795], +461: [65, 780], +462: [97, 780], +463: [73, 780], +464: [105, 780], +465: [79, 780], +466: [111, 780], +467: [85, 780], +468: [117, 780], +469: [85, 776, 772], +470: [117, 776, 772], +471: [85, 776, 769], +472: [117, 776, 769], +473: [85, 776, 780], +474: [117, 776, 780], +475: [85, 776, 768], +476: [117, 776, 768], +478: [65, 776, 772], +479: [97, 776, 772], +480: [65, 775, 772], +481: [97, 775, 772], +482: [198, 772], +483: [230, 772], +486: [71, 780], +487: [103, 780], +488: [75, 780], +489: [107, 780], +490: [79, 808], +491: [111, 808], +492: [79, 808, 772], +493: [111, 808, 772], +494: [439, 780], +495: [658, 780], +496: [106, 780], +500: [71, 769], +501: [103, 769], +504: [78, 768], +505: [110, 768], +506: [65, 778, 769], +507: [97, 778, 769], +508: [198, 769], +509: [230, 769], +510: [216, 769], +511: [248, 769], +512: [65, 783], +513: [97, 783], +514: [65, 785], +515: [97, 785], +516: [69, 783], +517: [101, 783], +518: [69, 785], +519: [101, 785], +520: [73, 783], +521: [105, 783], +522: [73, 785], +523: [105, 785], +524: [79, 783], +525: [111, 783], +526: [79, 785], +527: [111, 785], +528: [82, 783], +529: [114, 783], +530: [82, 785], +531: [114, 785], +532: [85, 783], +533: [117, 783], +534: [85, 785], +535: [117, 785], +536: [83, 806], +537: [115, 806], +538: [84, 806], +539: [116, 806], +542: [72, 780], +543: [104, 780], +550: [65, 775], +551: [97, 775], +552: [69, 807], +553: [101, 807], +554: [79, 776, 772], +555: [111, 776, 772], +556: [79, 771, 772], +557: [111, 771, 772], +558: [79, 775], +559: [111, 775], +560: [79, 775, 772], +561: [111, 775, 772], +562: [89, 772], +563: [121, 772], +832: [768], +833: [769], +835: [787], +836: [776, 769], +884: [697], +894: [59], +901: [168, 769], +902: [913, 769], +903: [183], +904: [917, 769], +905: [919, 769], +906: [921, 769], +908: [927, 769], +910: [933, 769], +911: [937, 769], +912: [953, 776, 769], +938: [921, 776], +939: [933, 776], +940: [945, 769], +941: [949, 769], +942: [951, 769], +943: [953, 769], +944: [965, 776, 769], +970: [953, 776], +971: [965, 776], +972: [959, 769], +973: [965, 769], +974: [969, 769], +979: [978, 769], +980: [978, 776], +1024: [1045, 768], +1025: [1045, 776], +1027: [1043, 769], +1031: [1030, 776], +1036: [1050, 769], +1037: [1048, 768], +1038: [1059, 774], +1049: [1048, 774], +1081: [1080, 774], +1104: [1077, 768], +1105: [1077, 776], +1107: [1075, 769], +1111: [1110, 776], +1116: [1082, 769], +1117: [1080, 768], +1118: [1091, 774], +1142: [1140, 783], +1143: [1141, 783], +1217: [1046, 774], +1218: [1078, 774], +1232: [1040, 774], +1233: [1072, 774], +1234: [1040, 776], +1235: [1072, 776], +1238: [1045, 774], +1239: [1077, 774], +1242: [1240, 776], +1243: [1241, 776], +1244: [1046, 776], +1245: [1078, 776], +1246: [1047, 776], +1247: [1079, 776], +1250: [1048, 772], +1251: [1080, 772], +1252: [1048, 776], +1253: [1080, 776], +1254: [1054, 776], +1255: [1086, 776], +1258: [1256, 776], +1259: [1257, 776], +1260: [1069, 776], +1261: [1101, 776], +1262: [1059, 772], +1263: [1091, 772], +1264: [1059, 776], +1265: [1091, 776], +1266: [1059, 779], +1267: [1091, 779], +1268: [1063, 776], +1269: [1095, 776], +1272: [1067, 776], +1273: [1099, 776], +1570: [1575, 1619], +1571: [1575, 1620], +1572: [1608, 1620], +1573: [1575, 1621], +1574: [1610, 1620], +1728: [1749, 1620], +1730: [1729, 1620], +1747: [1746, 1620], +2345: [2344, 2364], +2353: [2352, 2364], +2356: [2355, 2364], +2392: [2325, 2364], +2393: [2326, 2364], +2394: [2327, 2364], +2395: [2332, 2364], +2396: [2337, 2364], +2397: [2338, 2364], +2398: [2347, 2364], +2399: [2351, 2364], +2507: [2503, 2494], +2508: [2503, 2519], +2524: [2465, 2492], +2525: [2466, 2492], +2527: [2479, 2492], +2611: [2610, 2620], +2614: [2616, 2620], +2649: [2582, 2620], +2650: [2583, 2620], +2651: [2588, 2620], +2654: [2603, 2620], +2888: [2887, 2902], +2891: [2887, 2878], +2892: [2887, 2903], +2908: [2849, 2876], +2909: [2850, 2876], +2964: [2962, 3031], +3018: [3014, 3006], +3019: [3015, 3006], +3020: [3014, 3031], +3144: [3142, 3158], +3264: [3263, 3285], +3271: [3270, 3285], +3272: [3270, 3286], +3274: [3270, 3266], +3275: [3270, 3266, 3285], +3402: [3398, 3390], +3403: [3399, 3390], +3404: [3398, 3415], +3546: [3545, 3530], +3548: [3545, 3535], +3549: [3545, 3535, 3530], +3550: [3545, 3551], +3907: [3906, 4023], +3917: [3916, 4023], +3922: [3921, 4023], +3927: [3926, 4023], +3932: [3931, 4023], +3945: [3904, 4021], +3955: [3953, 3954], +3957: [3953, 3956], +3958: [4018, 3968], +3960: [4019, 3968], +3969: [3953, 3968], +3987: [3986, 4023], +3997: [3996, 4023], +4002: [4001, 4023], +4007: [4006, 4023], +4012: [4011, 4023], +4025: [3984, 4021], +4134: [4133, 4142], +7680: [65, 805], +7681: [97, 805], +7682: [66, 775], +7683: [98, 775], +7684: [66, 803], +7685: [98, 803], +7686: [66, 817], +7687: [98, 817], +7688: [67, 807, 769], +7689: [99, 807, 769], +7690: [68, 775], +7691: [100, 775], +7692: [68, 803], +7693: [100, 803], +7694: [68, 817], +7695: [100, 817], +7696: [68, 807], +7697: [100, 807], +7698: [68, 813], +7699: [100, 813], +7700: [69, 772, 768], +7701: [101, 772, 768], +7702: [69, 772, 769], +7703: [101, 772, 769], +7704: [69, 813], +7705: [101, 813], +7706: [69, 816], +7707: [101, 816], +7708: [69, 807, 774], +7709: [101, 807, 774], +7710: [70, 775], +7711: [102, 775], +7712: [71, 772], +7713: [103, 772], +7714: [72, 775], +7715: [104, 775], +7716: [72, 803], +7717: [104, 803], +7718: [72, 776], +7719: [104, 776], +7720: [72, 807], +7721: [104, 807], +7722: [72, 814], +7723: [104, 814], +7724: [73, 816], +7725: [105, 816], +7726: [73, 776, 769], +7727: [105, 776, 769], +7728: [75, 769], +7729: [107, 769], +7730: [75, 803], +7731: [107, 803], +7732: [75, 817], +7733: [107, 817], +7734: [76, 803], +7735: [108, 803], +7736: [76, 803, 772], +7737: [108, 803, 772], +7738: [76, 817], +7739: [108, 817], +7740: [76, 813], +7741: [108, 813], +7742: [77, 769], +7743: [109, 769], +7744: [77, 775], +7745: [109, 775], +7746: [77, 803], +7747: [109, 803], +7748: [78, 775], +7749: [110, 775], +7750: [78, 803], +7751: [110, 803], +7752: [78, 817], +7753: [110, 817], +7754: [78, 813], +7755: [110, 813], +7756: [79, 771, 769], +7757: [111, 771, 769], +7758: [79, 771, 776], +7759: [111, 771, 776], +7760: [79, 772, 768], +7761: [111, 772, 768], +7762: [79, 772, 769], +7763: [111, 772, 769], +7764: [80, 769], +7765: [112, 769], +7766: [80, 775], +7767: [112, 775], +7768: [82, 775], +7769: [114, 775], +7770: [82, 803], +7771: [114, 803], +7772: [82, 803, 772], +7773: [114, 803, 772], +7774: [82, 817], +7775: [114, 817], +7776: [83, 775], +7777: [115, 775], +7778: [83, 803], +7779: [115, 803], +7780: [83, 769, 775], +7781: [115, 769, 775], +7782: [83, 780, 775], +7783: [115, 780, 775], +7784: [83, 803, 775], +7785: [115, 803, 775], +7786: [84, 775], +7787: [116, 775], +7788: [84, 803], +7789: [116, 803], +7790: [84, 817], +7791: [116, 817], +7792: [84, 813], +7793: [116, 813], +7794: [85, 804], +7795: [117, 804], +7796: [85, 816], +7797: [117, 816], +7798: [85, 813], +7799: [117, 813], +7800: [85, 771, 769], +7801: [117, 771, 769], +7802: [85, 772, 776], +7803: [117, 772, 776], +7804: [86, 771], +7805: [118, 771], +7806: [86, 803], +7807: [118, 803], +7808: [87, 768], +7809: [119, 768], +7810: [87, 769], +7811: [119, 769], +7812: [87, 776], +7813: [119, 776], +7814: [87, 775], +7815: [119, 775], +7816: [87, 803], +7817: [119, 803], +7818: [88, 775], +7819: [120, 775], +7820: [88, 776], +7821: [120, 776], +7822: [89, 775], +7823: [121, 775], +7824: [90, 770], +7825: [122, 770], +7826: [90, 803], +7827: [122, 803], +7828: [90, 817], +7829: [122, 817], +7830: [104, 817], +7831: [116, 776], +7832: [119, 778], +7833: [121, 778], +7835: [383, 775], +7840: [65, 803], +7841: [97, 803], +7842: [65, 777], +7843: [97, 777], +7844: [65, 770, 769], +7845: [97, 770, 769], +7846: [65, 770, 768], +7847: [97, 770, 768], +7848: [65, 770, 777], +7849: [97, 770, 777], +7850: [65, 770, 771], +7851: [97, 770, 771], +7852: [65, 803, 770], +7853: [97, 803, 770], +7854: [65, 774, 769], +7855: [97, 774, 769], +7856: [65, 774, 768], +7857: [97, 774, 768], +7858: [65, 774, 777], +7859: [97, 774, 777], +7860: [65, 774, 771], +7861: [97, 774, 771], +7862: [65, 803, 774], +7863: [97, 803, 774], +7864: [69, 803], +7865: [101, 803], +7866: [69, 777], +7867: [101, 777], +7868: [69, 771], +7869: [101, 771], +7870: [69, 770, 769], +7871: [101, 770, 769], +7872: [69, 770, 768], +7873: [101, 770, 768], +7874: [69, 770, 777], +7875: [101, 770, 777], +7876: [69, 770, 771], +7877: [101, 770, 771], +7878: [69, 803, 770], +7879: [101, 803, 770], +7880: [73, 777], +7881: [105, 777], +7882: [73, 803], +7883: [105, 803], +7884: [79, 803], +7885: [111, 803], +7886: [79, 777], +7887: [111, 777], +7888: [79, 770, 769], +7889: [111, 770, 769], +7890: [79, 770, 768], +7891: [111, 770, 768], +7892: [79, 770, 777], +7893: [111, 770, 777], +7894: [79, 770, 771], +7895: [111, 770, 771], +7896: [79, 803, 770], +7897: [111, 803, 770], +7898: [79, 795, 769], +7899: [111, 795, 769], +7900: [79, 795, 768], +7901: [111, 795, 768], +7902: [79, 795, 777], +7903: [111, 795, 777], +7904: [79, 795, 771], +7905: [111, 795, 771], +7906: [79, 795, 803], +7907: [111, 795, 803], +7908: [85, 803], +7909: [117, 803], +7910: [85, 777], +7911: [117, 777], +7912: [85, 795, 769], +7913: [117, 795, 769], +7914: [85, 795, 768], +7915: [117, 795, 768], +7916: [85, 795, 777], +7917: [117, 795, 777], +7918: [85, 795, 771], +7919: [117, 795, 771], +7920: [85, 795, 803], +7921: [117, 795, 803], +7922: [89, 768], +7923: [121, 768], +7924: [89, 803], +7925: [121, 803], +7926: [89, 777], +7927: [121, 777], +7928: [89, 771], +7929: [121, 771], +7936: [945, 787], +7937: [945, 788], +7938: [945, 787, 768], +7939: [945, 788, 768], +7940: [945, 787, 769], +7941: [945, 788, 769], +7942: [945, 787, 834], +7943: [945, 788, 834], +7944: [913, 787], +7945: [913, 788], +7946: [913, 787, 768], +7947: [913, 788, 768], +7948: [913, 787, 769], +7949: [913, 788, 769], +7950: [913, 787, 834], +7951: [913, 788, 834], +7952: [949, 787], +7953: [949, 788], +7954: [949, 787, 768], +7955: [949, 788, 768], +7956: [949, 787, 769], +7957: [949, 788, 769], +7960: [917, 787], +7961: [917, 788], +7962: [917, 787, 768], +7963: [917, 788, 768], +7964: [917, 787, 769], +7965: [917, 788, 769], +7968: [951, 787], +7969: [951, 788], +7970: [951, 787, 768], +7971: [951, 788, 768], +7972: [951, 787, 769], +7973: [951, 788, 769], +7974: [951, 787, 834], +7975: [951, 788, 834], +7976: [919, 787], +7977: [919, 788], +7978: [919, 787, 768], +7979: [919, 788, 768], +7980: [919, 787, 769], +7981: [919, 788, 769], +7982: [919, 787, 834], +7983: [919, 788, 834], +7984: [953, 787], +7985: [953, 788], +7986: [953, 787, 768], +7987: [953, 788, 768], +7988: [953, 787, 769], +7989: [953, 788, 769], +7990: [953, 787, 834], +7991: [953, 788, 834], +7992: [921, 787], +7993: [921, 788], +7994: [921, 787, 768], +7995: [921, 788, 768], +7996: [921, 787, 769], +7997: [921, 788, 769], +7998: [921, 787, 834], +7999: [921, 788, 834], +8000: [959, 787], +8001: [959, 788], +8002: [959, 787, 768], +8003: [959, 788, 768], +8004: [959, 787, 769], +8005: [959, 788, 769], +8008: [927, 787], +8009: [927, 788], +8010: [927, 787, 768], +8011: [927, 788, 768], +8012: [927, 787, 769], +8013: [927, 788, 769], +8016: [965, 787], +8017: [965, 788], +8018: [965, 787, 768], +8019: [965, 788, 768], +8020: [965, 787, 769], +8021: [965, 788, 769], +8022: [965, 787, 834], +8023: [965, 788, 834], +8025: [933, 788], +8027: [933, 788, 768], +8029: [933, 788, 769], +8031: [933, 788, 834], +8032: [969, 787], +8033: [969, 788], +8034: [969, 787, 768], +8035: [969, 788, 768], +8036: [969, 787, 769], +8037: [969, 788, 769], +8038: [969, 787, 834], +8039: [969, 788, 834], +8040: [937, 787], +8041: [937, 788], +8042: [937, 787, 768], +8043: [937, 788, 768], +8044: [937, 787, 769], +8045: [937, 788, 769], +8046: [937, 787, 834], +8047: [937, 788, 834], +8048: [945, 768], +8049: [945, 769], +8050: [949, 768], +8051: [949, 769], +8052: [951, 768], +8053: [951, 769], +8054: [953, 768], +8055: [953, 769], +8056: [959, 768], +8057: [959, 769], +8058: [965, 768], +8059: [965, 769], +8060: [969, 768], +8061: [969, 769], +8064: [945, 787, 837], +8065: [945, 788, 837], +8066: [945, 787, 768, 837], +8067: [945, 788, 768, 837], +8068: [945, 787, 769, 837], +8069: [945, 788, 769, 837], +8070: [945, 787, 834, 837], +8071: [945, 788, 834, 837], +8072: [913, 787, 837], +8073: [913, 788, 837], +8074: [913, 787, 768, 837], +8075: [913, 788, 768, 837], +8076: [913, 787, 769, 837], +8077: [913, 788, 769, 837], +8078: [913, 787, 834, 837], +8079: [913, 788, 834, 837], +8080: [951, 787, 837], +8081: [951, 788, 837], +8082: [951, 787, 768, 837], +8083: [951, 788, 768, 837], +8084: [951, 787, 769, 837], +8085: [951, 788, 769, 837], +8086: [951, 787, 834, 837], +8087: [951, 788, 834, 837], +8088: [919, 787, 837], +8089: [919, 788, 837], +8090: [919, 787, 768, 837], +8091: [919, 788, 768, 837], +8092: [919, 787, 769, 837], +8093: [919, 788, 769, 837], +8094: [919, 787, 834, 837], +8095: [919, 788, 834, 837], +8096: [969, 787, 837], +8097: [969, 788, 837], +8098: [969, 787, 768, 837], +8099: [969, 788, 768, 837], +8100: [969, 787, 769, 837], +8101: [969, 788, 769, 837], +8102: [969, 787, 834, 837], +8103: [969, 788, 834, 837], +8104: [937, 787, 837], +8105: [937, 788, 837], +8106: [937, 787, 768, 837], +8107: [937, 788, 768, 837], +8108: [937, 787, 769, 837], +8109: [937, 788, 769, 837], +8110: [937, 787, 834, 837], +8111: [937, 788, 834, 837], +8112: [945, 774], +8113: [945, 772], +8114: [945, 768, 837], +8115: [945, 837], +8116: [945, 769, 837], +8118: [945, 834], +8119: [945, 834, 837], +8120: [913, 774], +8121: [913, 772], +8122: [913, 768], +8123: [913, 769], +8124: [913, 837], +8126: [953], +8129: [168, 834], +8130: [951, 768, 837], +8131: [951, 837], +8132: [951, 769, 837], +8134: [951, 834], +8135: [951, 834, 837], +8136: [917, 768], +8137: [917, 769], +8138: [919, 768], +8139: [919, 769], +8140: [919, 837], +8141: [8127, 768], +8142: [8127, 769], +8143: [8127, 834], +8144: [953, 774], +8145: [953, 772], +8146: [953, 776, 768], +8147: [953, 776, 769], +8150: [953, 834], +8151: [953, 776, 834], +8152: [921, 774], +8153: [921, 772], +8154: [921, 768], +8155: [921, 769], +8157: [8190, 768], +8158: [8190, 769], +8159: [8190, 834], +8160: [965, 774], +8161: [965, 772], +8162: [965, 776, 768], +8163: [965, 776, 769], +8164: [961, 787], +8165: [961, 788], +8166: [965, 834], +8167: [965, 776, 834], +8168: [933, 774], +8169: [933, 772], +8170: [933, 768], +8171: [933, 769], +8172: [929, 788], +8173: [168, 768], +8174: [168, 769], +8175: [96], +8178: [969, 768, 837], +8179: [969, 837], +8180: [969, 769, 837], +8182: [969, 834], +8183: [969, 834, 837], +8184: [927, 768], +8185: [927, 769], +8186: [937, 768], +8187: [937, 769], +8188: [937, 837], +8189: [180], +8192: [8194], +8193: [8195], +8486: [937], +8490: [75], +8491: [65, 778], +8602: [8592, 824], +8603: [8594, 824], +8622: [8596, 824], +8653: [8656, 824], +8654: [8660, 824], +8655: [8658, 824], +8708: [8707, 824], +8713: [8712, 824], +8716: [8715, 824], +8740: [8739, 824], +8742: [8741, 824], +8769: [8764, 824], +8772: [8771, 824], +8775: [8773, 824], +8777: [8776, 824], +8800: [61, 824], +8802: [8801, 824], +8813: [8781, 824], +8814: [60, 824], +8815: [62, 824], +8816: [8804, 824], +8817: [8805, 824], +8820: [8818, 824], +8821: [8819, 824], +8824: [8822, 824], +8825: [8823, 824], +8832: [8826, 824], +8833: [8827, 824], +8836: [8834, 824], +8837: [8835, 824], +8840: [8838, 824], +8841: [8839, 824], +8876: [8866, 824], +8877: [8872, 824], +8878: [8873, 824], +8879: [8875, 824], +8928: [8828, 824], +8929: [8829, 824], +8930: [8849, 824], +8931: [8850, 824], +8938: [8882, 824], +8939: [8883, 824], +8940: [8884, 824], +8941: [8885, 824], +9001: [12296], +9002: [12297], +10972: [10973, 824], +12364: [12363, 12441], +12366: [12365, 12441], +12368: [12367, 12441], +12370: [12369, 12441], +12372: [12371, 12441], +12374: [12373, 12441], +12376: [12375, 12441], +12378: [12377, 12441], +12380: [12379, 12441], +12382: [12381, 12441], +12384: [12383, 12441], +12386: [12385, 12441], +12389: [12388, 12441], +12391: [12390, 12441], +12393: [12392, 12441], +12400: [12399, 12441], +12401: [12399, 12442], +12403: [12402, 12441], +12404: [12402, 12442], +12406: [12405, 12441], +12407: [12405, 12442], +12409: [12408, 12441], +12410: [12408, 12442], +12412: [12411, 12441], +12413: [12411, 12442], +12436: [12358, 12441], +12446: [12445, 12441], +12460: [12459, 12441], +12462: [12461, 12441], +12464: [12463, 12441], +12466: [12465, 12441], +12468: [12467, 12441], +12470: [12469, 12441], +12472: [12471, 12441], +12474: [12473, 12441], +12476: [12475, 12441], +12478: [12477, 12441], +12480: [12479, 12441], +12482: [12481, 12441], +12485: [12484, 12441], +12487: [12486, 12441], +12489: [12488, 12441], +12496: [12495, 12441], +12497: [12495, 12442], +12499: [12498, 12441], +12500: [12498, 12442], +12502: [12501, 12441], +12503: [12501, 12442], +12505: [12504, 12441], +12506: [12504, 12442], +12508: [12507, 12441], +12509: [12507, 12442], +12532: [12454, 12441], +12535: [12527, 12441], +12536: [12528, 12441], +12537: [12529, 12441], +12538: [12530, 12441], +12542: [12541, 12441], +63744: [35912], +63745: [26356], +63746: [36554], +63747: [36040], +63748: [28369], +63749: [20018], +63750: [21477], +63751: [40860], +63752: [40860], +63753: [22865], +63754: [37329], +63755: [21895], +63756: [22856], +63757: [25078], +63758: [30313], +63759: [32645], +63760: [34367], +63761: [34746], +63762: [35064], +63763: [37007], +63764: [27138], +63765: [27931], +63766: [28889], +63767: [29662], +63768: [33853], +63769: [37226], +63770: [39409], +63771: [20098], +63772: [21365], +63773: [27396], +63774: [29211], +63775: [34349], +63776: [40478], +63777: [23888], +63778: [28651], +63779: [34253], +63780: [35172], +63781: [25289], +63782: [33240], +63783: [34847], +63784: [24266], +63785: [26391], +63786: [28010], +63787: [29436], +63788: [37070], +63789: [20358], +63790: [20919], +63791: [21214], +63792: [25796], +63793: [27347], +63794: [29200], +63795: [30439], +63796: [32769], +63797: [34310], +63798: [34396], +63799: [36335], +63800: [38706], +63801: [39791], +63802: [40442], +63803: [30860], +63804: [31103], +63805: [32160], +63806: [33737], +63807: [37636], +63808: [40575], +63809: [35542], +63810: [22751], +63811: [24324], +63812: [31840], +63813: [32894], +63814: [29282], +63815: [30922], +63816: [36034], +63817: [38647], +63818: [22744], +63819: [23650], +63820: [27155], +63821: [28122], +63822: [28431], +63823: [32047], +63824: [32311], +63825: [38475], +63826: [21202], +63827: [32907], +63828: [20956], +63829: [20940], +63830: [31260], +63831: [32190], +63832: [33777], +63833: [38517], +63834: [35712], +63835: [25295], +63836: [27138], +63837: [35582], +63838: [20025], +63839: [23527], +63840: [24594], +63841: [29575], +63842: [30064], +63843: [21271], +63844: [30971], +63845: [20415], +63846: [24489], +63847: [19981], +63848: [27852], +63849: [25976], +63850: [32034], +63851: [21443], +63852: [22622], +63853: [30465], +63854: [33865], +63855: [35498], +63856: [27578], +63857: [36784], +63858: [27784], +63859: [25342], +63860: [33509], +63861: [25504], +63862: [30053], +63863: [20142], +63864: [20841], +63865: [20937], +63866: [26753], +63867: [31975], +63868: [33391], +63869: [35538], +63870: [37327], +63871: [21237], +63872: [21570], +63873: [22899], +63874: [24300], +63875: [26053], +63876: [28670], +63877: [31018], +63878: [38317], +63879: [39530], +63880: [40599], +63881: [40654], +63882: [21147], +63883: [26310], +63884: [27511], +63885: [36706], +63886: [24180], +63887: [24976], +63888: [25088], +63889: [25754], +63890: [28451], +63891: [29001], +63892: [29833], +63893: [31178], +63894: [32244], +63895: [32879], +63896: [36646], +63897: [34030], +63898: [36899], +63899: [37706], +63900: [21015], +63901: [21155], +63902: [21693], +63903: [28872], +63904: [35010], +63905: [35498], +63906: [24265], +63907: [24565], +63908: [25467], +63909: [27566], +63910: [31806], +63911: [29557], +63912: [20196], +63913: [22265], +63914: [23527], +63915: [23994], +63916: [24604], +63917: [29618], +63918: [29801], +63919: [32666], +63920: [32838], +63921: [37428], +63922: [38646], +63923: [38728], +63924: [38936], +63925: [20363], +63926: [31150], +63927: [37300], +63928: [38584], +63929: [24801], +63930: [20102], +63931: [20698], +63932: [23534], +63933: [23615], +63934: [26009], +63935: [27138], +63936: [29134], +63937: [30274], +63938: [34044], +63939: [36988], +63940: [40845], +63941: [26248], +63942: [38446], +63943: [21129], +63944: [26491], +63945: [26611], +63946: [27969], +63947: [28316], +63948: [29705], +63949: [30041], +63950: [30827], +63951: [32016], +63952: [39006], +63953: [20845], +63954: [25134], +63955: [38520], +63956: [20523], +63957: [23833], +63958: [28138], +63959: [36650], +63960: [24459], +63961: [24900], +63962: [26647], +63963: [29575], +63964: [38534], +63965: [21033], +63966: [21519], +63967: [23653], +63968: [26131], +63969: [26446], +63970: [26792], +63971: [27877], +63972: [29702], +63973: [30178], +63974: [32633], +63975: [35023], +63976: [35041], +63977: [37324], +63978: [38626], +63979: [21311], +63980: [28346], +63981: [21533], +63982: [29136], +63983: [29848], +63984: [34298], +63985: [38563], +63986: [40023], +63987: [40607], +63988: [26519], +63989: [28107], +63990: [33256], +63991: [31435], +63992: [31520], +63993: [31890], +63994: [29376], +63995: [28825], +63996: [35672], +63997: [20160], +63998: [33590], +63999: [21050], +64000: [20999], +64001: [24230], +64002: [25299], +64003: [31958], +64004: [23429], +64005: [27934], +64006: [26292], +64007: [36667], +64008: [34892], +64009: [38477], +64010: [35211], +64011: [24275], +64012: [20800], +64013: [21952], +64016: [22618], +64018: [26228], +64021: [20958], +64022: [29482], +64023: [30410], +64024: [31036], +64025: [31070], +64026: [31077], +64027: [31119], +64028: [38742], +64029: [31934], +64030: [32701], +64032: [34322], +64034: [35576], +64037: [36920], +64038: [37117], +64042: [39151], +64043: [39164], +64044: [39208], +64045: [40372], +64048: [20398], +64049: [20711], +64050: [20813], +64051: [21193], +64052: [21220], +64053: [21329], +64054: [21917], +64055: [22022], +64056: [22120], +64057: [22592], +64058: [22696], +64059: [23652], +64060: [23662], +64061: [24724], +64062: [24936], +64063: [24974], +64064: [25074], +64065: [25935], +64066: [26082], +64067: [26257], +64068: [26757], +64069: [28023], +64070: [28186], +64071: [28450], +64072: [29038], +64073: [29227], +64074: [29730], +64075: [30865], +64076: [31038], +64077: [31049], +64078: [31048], +64079: [31056], +64080: [31062], +64081: [31069], +64082: [31117], +64083: [31118], +64084: [31296], +64085: [31361], +64086: [31680], +64087: [32244], +64088: [32265], +64089: [32321], +64090: [32626], +64091: [32773], +64092: [33261], +64093: [33401], +64094: [33401], +64095: [33879], +64096: [35088], +64097: [35222], +64098: [35585], +64099: [35641], +64100: [36051], +64101: [36104], +64102: [36790], +64103: [36920], +64104: [38627], +64105: [38911], +64106: [38971], +64285: [1497, 1460], +64287: [1522, 1463], +64298: [1513, 1473], +64299: [1513, 1474], +64300: [1513, 1468, 1473], +64301: [1513, 1468, 1474], +64302: [1488, 1463], +64303: [1488, 1464], +64304: [1488, 1468], +64305: [1489, 1468], +64306: [1490, 1468], +64307: [1491, 1468], +64308: [1492, 1468], +64309: [1493, 1468], +64310: [1494, 1468], +64312: [1496, 1468], +64313: [1497, 1468], +64314: [1498, 1468], +64315: [1499, 1468], +64316: [1500, 1468], +64318: [1502, 1468], +64320: [1504, 1468], +64321: [1505, 1468], +64323: [1507, 1468], +64324: [1508, 1468], +64326: [1510, 1468], +64327: [1511, 1468], +64328: [1512, 1468], +64329: [1513, 1468], +64330: [1514, 1468], +64331: [1493, 1465], +64332: [1489, 1471], +64333: [1499, 1471], +64334: [1508, 1471], +119134: [119127, 119141], +119135: [119128, 119141], +119136: [119128, 119141, 119150], +119137: [119128, 119141, 119151], +119138: [119128, 119141, 119152], +119139: [119128, 119141, 119153], +119140: [119128, 119141, 119154], +119227: [119225, 119141], +119228: [119226, 119141], +119229: [119225, 119141, 119150], +119230: [119226, 119141, 119150], +119231: [119225, 119141, 119151], +119232: [119226, 119141, 119151], +194560: [20029], +194561: [20024], +194562: [20033], +194563: [131362], +194564: [20320], +194565: [20398], +194566: [20411], +194567: [20482], +194568: [20602], +194569: [20633], +194570: [20711], +194571: [20687], +194572: [13470], +194573: [132666], +194574: [20813], +194575: [20820], +194576: [20836], +194577: [20855], +194578: [132380], +194579: [13497], +194580: [20839], +194581: [20877], +194582: [132427], +194583: [20887], +194584: [20900], +194585: [20172], +194586: [20908], +194587: [20917], +194588: [168415], +194589: [20981], +194590: [20995], +194591: [13535], +194592: [21051], +194593: [21062], +194594: [21106], +194595: [21111], +194596: [13589], +194597: [21191], +194598: [21193], +194599: [21220], +194600: [21242], +194601: [21253], +194602: [21254], +194603: [21271], +194604: [21321], +194605: [21329], +194606: [21338], +194607: [21363], +194608: [21373], +194609: [21375], +194610: [21375], +194611: [21375], +194612: [133676], +194613: [28784], +194614: [21450], +194615: [21471], +194616: [133987], +194617: [21483], +194618: [21489], +194619: [21510], +194620: [21662], +194621: [21560], +194622: [21576], +194623: [21608], +194624: [21666], +194625: [21750], +194626: [21776], +194627: [21843], +194628: [21859], +194629: [21892], +194630: [21892], +194631: [21913], +194632: [21931], +194633: [21939], +194634: [21954], +194635: [22294], +194636: [22022], +194637: [22295], +194638: [22097], +194639: [22132], +194640: [20999], +194641: [22766], +194642: [22478], +194643: [22516], +194644: [22541], +194645: [22411], +194646: [22578], +194647: [22577], +194648: [22700], +194649: [136420], +194650: [22770], +194651: [22775], +194652: [22790], +194653: [22810], +194654: [22818], +194655: [22882], +194656: [136872], +194657: [136938], +194658: [23020], +194659: [23067], +194660: [23079], +194661: [23000], +194662: [23142], +194663: [14062], +194664: [136042], +194665: [23304], +194666: [23358], +194667: [23358], +194668: [137672], +194669: [23491], +194670: [23512], +194671: [23527], +194672: [23539], +194673: [138008], +194674: [23551], +194675: [23558], +194676: [24371], +194677: [23586], +194678: [14209], +194679: [23648], +194680: [23662], +194681: [23744], +194682: [23693], +194683: [138724], +194684: [23875], +194685: [138726], +194686: [23918], +194687: [23915], +194688: [23932], +194689: [24033], +194690: [24034], +194691: [14383], +194692: [24061], +194693: [24104], +194694: [24125], +194695: [24169], +194696: [14434], +194697: [139651], +194698: [14460], +194699: [24240], +194700: [24243], +194701: [24246], +194702: [24266], +194703: [172946], +194704: [24318], +194705: [140081], +194706: [140081], +194707: [33281], +194708: [24354], +194709: [24354], +194710: [14535], +194711: [144056], +194712: [156122], +194713: [24418], +194714: [24427], +194715: [14563], +194716: [24474], +194717: [24525], +194718: [24535], +194719: [24569], +194720: [24705], +194721: [14650], +194722: [14620], +194723: [24724], +194724: [141012], +194725: [24775], +194726: [24904], +194727: [24908], +194728: [24910], +194729: [24908], +194730: [24954], +194731: [24974], +194732: [25010], +194733: [24996], +194734: [25007], +194735: [25054], +194736: [25074], +194737: [25078], +194738: [25104], +194739: [25115], +194740: [25181], +194741: [25265], +194742: [25300], +194743: [25424], +194744: [142092], +194745: [25405], +194746: [25340], +194747: [25448], +194748: [25475], +194749: [25572], +194750: [142321], +194751: [25634], +194752: [25541], +194753: [25513], +194754: [14894], +194755: [25705], +194756: [25726], +194757: [25757], +194758: [25719], +194759: [14956], +194760: [25935], +194761: [25964], +194762: [143370], +194763: [26083], +194764: [26360], +194765: [26185], +194766: [15129], +194767: [26257], +194768: [15112], +194769: [15076], +194770: [20882], +194771: [20885], +194772: [26368], +194773: [26268], +194774: [32941], +194775: [17369], +194776: [26391], +194777: [26395], +194778: [26401], +194779: [26462], +194780: [26451], +194781: [144323], +194782: [15177], +194783: [26618], +194784: [26501], +194785: [26706], +194786: [26757], +194787: [144493], +194788: [26766], +194789: [26655], +194790: [26900], +194791: [15261], +194792: [26946], +194793: [27043], +194794: [27114], +194795: [27304], +194796: [145059], +194797: [27355], +194798: [15384], +194799: [27425], +194800: [145575], +194801: [27476], +194802: [15438], +194803: [27506], +194804: [27551], +194805: [27578], +194806: [27579], +194807: [146061], +194808: [138507], +194809: [146170], +194810: [27726], +194811: [146620], +194812: [27839], +194813: [27853], +194814: [27751], +194815: [27926], +194816: [27966], +194817: [28023], +194818: [27969], +194819: [28009], +194820: [28024], +194821: [28037], +194822: [146718], +194823: [27956], +194824: [28207], +194825: [28270], +194826: [15667], +194827: [28363], +194828: [28359], +194829: [147153], +194830: [28153], +194831: [28526], +194832: [147294], +194833: [147342], +194834: [28614], +194835: [28729], +194836: [28702], +194837: [28699], +194838: [15766], +194839: [28746], +194840: [28797], +194841: [28791], +194842: [28845], +194843: [132389], +194844: [28997], +194845: [148067], +194846: [29084], +194847: [17323], +194848: [29224], +194849: [29237], +194850: [29264], +194851: [149000], +194852: [29312], +194853: [29333], +194854: [149301], +194855: [149524], +194856: [29562], +194857: [29579], +194858: [16044], +194859: [29605], +194860: [16056], +194861: [16056], +194862: [29767], +194863: [29788], +194864: [29809], +194865: [29829], +194866: [29898], +194867: [16155], +194868: [29988], +194869: [150582], +194870: [30014], +194871: [150674], +194872: [30064], +194873: [139679], +194874: [30224], +194875: [151457], +194876: [151480], +194877: [151620], +194878: [16380], +194879: [16392], +194880: [30452], +194881: [151795], +194882: [151794], +194883: [151833], +194884: [151859], +194885: [30494], +194886: [30495], +194887: [30495], +194888: [30538], +194889: [16441], +194890: [30603], +194891: [16454], +194892: [16534], +194893: [152605], +194894: [30798], +194895: [30860], +194896: [30924], +194897: [16611], +194898: [153126], +194899: [31062], +194900: [153242], +194901: [153285], +194902: [31119], +194903: [31211], +194904: [16687], +194905: [31296], +194906: [31306], +194907: [31311], +194908: [153980], +194909: [154279], +194910: [154279], +194911: [31406], +194912: [16898], +194913: [154539], +194914: [31686], +194915: [31689], +194916: [16935], +194917: [154752], +194918: [31954], +194919: [17056], +194920: [31976], +194921: [31971], +194922: [32000], +194923: [155526], +194924: [32099], +194925: [17153], +194926: [32199], +194927: [32258], +194928: [32325], +194929: [17204], +194930: [156200], +194931: [156231], +194932: [17241], +194933: [156377], +194934: [32634], +194935: [156478], +194936: [32661], +194937: [32762], +194938: [32773], +194939: [156890], +194940: [156963], +194941: [32864], +194942: [157096], +194943: [32880], +194944: [144223], +194945: [17365], +194946: [32946], +194947: [33027], +194948: [17419], +194949: [33086], +194950: [23221], +194951: [157607], +194952: [157621], +194953: [144275], +194954: [144284], +194955: [33281], +194956: [33284], +194957: [36766], +194958: [17515], +194959: [33425], +194960: [33419], +194961: [33437], +194962: [21171], +194963: [33457], +194964: [33459], +194965: [33469], +194966: [33510], +194967: [158524], +194968: [33509], +194969: [33565], +194970: [33635], +194971: [33709], +194972: [33571], +194973: [33725], +194974: [33767], +194975: [33879], +194976: [33619], +194977: [33738], +194978: [33740], +194979: [33756], +194980: [158774], +194981: [159083], +194982: [158933], +194983: [17707], +194984: [34033], +194985: [34035], +194986: [34070], +194987: [160714], +194988: [34148], +194989: [159532], +194990: [17757], +194991: [17761], +194992: [159665], +194993: [159954], +194994: [17771], +194995: [34384], +194996: [34396], +194997: [34407], +194998: [34409], +194999: [34473], +195000: [34440], +195001: [34574], +195002: [34530], +195003: [34681], +195004: [34600], +195005: [34667], +195006: [34694], +195007: [19799], +195008: [34785], +195009: [34817], +195010: [17913], +195011: [34912], +195012: [34915], +195013: [161383], +195014: [35031], +195015: [35038], +195016: [17973], +195017: [35066], +195018: [13499], +195019: [161966], +195020: [162150], +195021: [18110], +195022: [18119], +195023: [35488], +195024: [35565], +195025: [35722], +195026: [35925], +195027: [162984], +195028: [36011], +195029: [36033], +195030: [36123], +195031: [36215], +195032: [163631], +195033: [133124], +195034: [36299], +195035: [36284], +195036: [36336], +195037: [133342], +195038: [36564], +195039: [36664], +195040: [165330], +195041: [165357], +195042: [37012], +195043: [37105], +195044: [37137], +195045: [165678], +195046: [37147], +195047: [37432], +195048: [37591], +195049: [37592], +195050: [37500], +195051: [37881], +195052: [37909], +195053: [166906], +195054: [38283], +195055: [18837], +195056: [38327], +195057: [167287], +195058: [18918], +195059: [38595], +195060: [23986], +195061: [38691], +195062: [168261], +195063: [168474], +195064: [19054], +195065: [19062], +195066: [38880], +195067: [168970], +195068: [19122], +195069: [169110], +195070: [38923], +195071: [38923], +195072: [38953], +195073: [169398], +195074: [39138], +195075: [19251], +195076: [39209], +195077: [39335], +195078: [39362], +195079: [39422], +195080: [19406], +195081: [170800], +195082: [39698], +195083: [40000], +195084: [40189], +195085: [19662], +195086: [19693], +195087: [40295], +195088: [172238], +195089: [19704], +195090: [172293], +195091: [172558], +195092: [172689], +195093: [40635], +195094: [19798], +195095: [40697], +195096: [40702], +195097: [40709], +195098: [40719], +195099: [40726], +195100: [40763], +195101: [173568], } _compat_decomposition = { -160: (32,), -168: (32, 776), -170: (97,), -175: (32, 772), -178: (50,), -179: (51,), -180: (32, 769), -181: (956,), -184: (32, 807), -185: (49,), -186: (111,), -188: (49, 8260, 52), -189: (49, 8260, 50), -190: (51, 8260, 52), -192: (65, 768), -193: (65, 769), -194: (65, 770), -195: (65, 771), -196: (65, 776), -197: (65, 778), -199: (67, 807), -200: (69, 768), -201: (69, 769), -202: (69, 770), -203: (69, 776), -204: (73, 768), -205: (73, 769), -206: (73, 770), -207: (73, 776), -209: (78, 771), -210: (79, 768), -211: (79, 769), -212: (79, 770), -213: (79, 771), -214: (79, 776), -217: (85, 768), -218: (85, 769), -219: (85, 770), -220: (85, 776), -221: (89, 769), -224: (97, 768), -225: (97, 769), -226: (97, 770), -227: (97, 771), -228: (97, 776), -229: (97, 778), -231: (99, 807), -232: (101, 768), -233: (101, 769), -234: (101, 770), -235: (101, 776), -236: (105, 768), -237: (105, 769), -238: (105, 770), -239: (105, 776), -241: (110, 771), -242: (111, 768), -243: (111, 769), -244: (111, 770), -245: (111, 771), -246: (111, 776), -249: (117, 768), -250: (117, 769), -251: (117, 770), -252: (117, 776), -253: (121, 769), -255: (121, 776), -256: (65, 772), -257: (97, 772), -258: (65, 774), -259: (97, 774), -260: (65, 808), -261: (97, 808), -262: (67, 769), -263: (99, 769), -264: (67, 770), -265: (99, 770), -266: (67, 775), -267: (99, 775), -268: (67, 780), -269: (99, 780), -270: (68, 780), -271: (100, 780), -274: (69, 772), -275: (101, 772), -276: (69, 774), -277: (101, 774), -278: (69, 775), -279: (101, 775), -280: (69, 808), -281: (101, 808), -282: (69, 780), -283: (101, 780), -284: (71, 770), -285: (103, 770), -286: (71, 774), -287: (103, 774), -288: (71, 775), -289: (103, 775), -290: (71, 807), -291: (103, 807), -292: (72, 770), -293: (104, 770), -296: (73, 771), -297: (105, 771), -298: (73, 772), -299: (105, 772), -300: (73, 774), -301: (105, 774), -302: (73, 808), -303: (105, 808), -304: (73, 775), -306: (73, 74), -307: (105, 106), -308: (74, 770), -309: (106, 770), -310: (75, 807), -311: (107, 807), -313: (76, 769), -314: (108, 769), -315: (76, 807), -316: (108, 807), -317: (76, 780), -318: (108, 780), -319: (76, 183), -320: (108, 183), -323: (78, 769), -324: (110, 769), -325: (78, 807), -326: (110, 807), -327: (78, 780), -328: (110, 780), -329: (700, 110), -332: (79, 772), -333: (111, 772), -334: (79, 774), -335: (111, 774), -336: (79, 779), -337: (111, 779), -340: (82, 769), -341: (114, 769), -342: (82, 807), -343: (114, 807), -344: (82, 780), -345: (114, 780), -346: (83, 769), -347: (115, 769), -348: (83, 770), -349: (115, 770), -350: (83, 807), -351: (115, 807), -352: (83, 780), -353: (115, 780), -354: (84, 807), -355: (116, 807), -356: (84, 780), -357: (116, 780), -360: (85, 771), -361: (117, 771), -362: (85, 772), -363: (117, 772), -364: (85, 774), -365: (117, 774), -366: (85, 778), -367: (117, 778), -368: (85, 779), -369: (117, 779), -370: (85, 808), -371: (117, 808), -372: (87, 770), -373: (119, 770), -374: (89, 770), -375: (121, 770), -376: (89, 776), -377: (90, 769), -378: (122, 769), -379: (90, 775), -380: (122, 775), -381: (90, 780), -382: (122, 780), -383: (115,), -416: (79, 795), -417: (111, 795), -431: (85, 795), -432: (117, 795), -452: (68, 90, 780), -453: (68, 122, 780), -454: (100, 122, 780), -455: (76, 74), -456: (76, 106), -457: (108, 106), -458: (78, 74), -459: (78, 106), -460: (110, 106), -461: (65, 780), -462: (97, 780), -463: (73, 780), -464: (105, 780), -465: (79, 780), -466: (111, 780), -467: (85, 780), -468: (117, 780), -469: (85, 776, 772), -470: (117, 776, 772), -471: (85, 776, 769), -472: (117, 776, 769), -473: (85, 776, 780), -474: (117, 776, 780), -475: (85, 776, 768), -476: (117, 776, 768), -478: (65, 776, 772), -479: (97, 776, 772), -480: (65, 775, 772), -481: (97, 775, 772), -482: (198, 772), -483: (230, 772), -486: (71, 780), -487: (103, 780), -488: (75, 780), -489: (107, 780), -490: (79, 808), -491: (111, 808), -492: (79, 808, 772), -493: (111, 808, 772), -494: (439, 780), -495: (658, 780), -496: (106, 780), -497: (68, 90), -498: (68, 122), -499: (100, 122), -500: (71, 769), -501: (103, 769), -504: (78, 768), -505: (110, 768), -506: (65, 778, 769), -507: (97, 778, 769), -508: (198, 769), -509: (230, 769), -510: (216, 769), -511: (248, 769), -512: (65, 783), -513: (97, 783), -514: (65, 785), -515: (97, 785), -516: (69, 783), -517: (101, 783), -518: (69, 785), -519: (101, 785), -520: (73, 783), -521: (105, 783), -522: (73, 785), -523: (105, 785), -524: (79, 783), -525: (111, 783), -526: (79, 785), -527: (111, 785), -528: (82, 783), -529: (114, 783), -530: (82, 785), -531: (114, 785), -532: (85, 783), -533: (117, 783), -534: (85, 785), -535: (117, 785), -536: (83, 806), -537: (115, 806), -538: (84, 806), -539: (116, 806), -542: (72, 780), -543: (104, 780), -550: (65, 775), -551: (97, 775), -552: (69, 807), -553: (101, 807), -554: (79, 776, 772), -555: (111, 776, 772), -556: (79, 771, 772), -557: (111, 771, 772), -558: (79, 775), -559: (111, 775), -560: (79, 775, 772), -561: (111, 775, 772), -562: (89, 772), -563: (121, 772), -688: (104,), -689: (614,), -690: (106,), -691: (114,), -692: (633,), -693: (635,), -694: (641,), -695: (119,), -696: (121,), -728: (32, 774), -729: (32, 775), -730: (32, 778), -731: (32, 808), -732: (32, 771), -733: (32, 779), -736: (611,), -737: (108,), -738: (115,), -739: (120,), -740: (661,), -832: (768,), -833: (769,), -835: (787,), -836: (776, 769), -884: (697,), -890: (32, 837), -894: (59,), -900: (32, 769), -901: (32, 776, 769), -902: (913, 769), -903: (183,), -904: (917, 769), -905: (919, 769), -906: (921, 769), -908: (927, 769), -910: (933, 769), -911: (937, 769), -912: (953, 776, 769), -938: (921, 776), -939: (933, 776), -940: (945, 769), -941: (949, 769), -942: (951, 769), -943: (953, 769), -944: (965, 776, 769), -970: (953, 776), -971: (965, 776), -972: (959, 769), -973: (965, 769), -974: (969, 769), -976: (946,), -977: (952,), -978: (933,), -979: (933, 769), -980: (933, 776), -981: (966,), -982: (960,), -1008: (954,), -1009: (961,), -1010: (962,), -1012: (920,), -1013: (949,), -1024: (1045, 768), -1025: (1045, 776), -1027: (1043, 769), -1031: (1030, 776), -1036: (1050, 769), -1037: (1048, 768), -1038: (1059, 774), -1049: (1048, 774), -1081: (1080, 774), -1104: (1077, 768), -1105: (1077, 776), -1107: (1075, 769), -1111: (1110, 776), -1116: (1082, 769), -1117: (1080, 768), -1118: (1091, 774), -1142: (1140, 783), -1143: (1141, 783), -1217: (1046, 774), -1218: (1078, 774), -1232: (1040, 774), -1233: (1072, 774), -1234: (1040, 776), -1235: (1072, 776), -1238: (1045, 774), -1239: (1077, 774), -1242: (1240, 776), -1243: (1241, 776), -1244: (1046, 776), -1245: (1078, 776), -1246: (1047, 776), -1247: (1079, 776), -1250: (1048, 772), -1251: (1080, 772), -1252: (1048, 776), -1253: (1080, 776), -1254: (1054, 776), -1255: (1086, 776), -1258: (1256, 776), -1259: (1257, 776), -1260: (1069, 776), -1261: (1101, 776), -1262: (1059, 772), -1263: (1091, 772), -1264: (1059, 776), -1265: (1091, 776), -1266: (1059, 779), -1267: (1091, 779), -1268: (1063, 776), -1269: (1095, 776), -1272: (1067, 776), -1273: (1099, 776), -1415: (1381, 1410), -1570: (1575, 1619), -1571: (1575, 1620), -1572: (1608, 1620), -1573: (1575, 1621), -1574: (1610, 1620), -1653: (1575, 1652), -1654: (1608, 1652), -1655: (1735, 1652), -1656: (1610, 1652), -1728: (1749, 1620), -1730: (1729, 1620), -1747: (1746, 1620), -2345: (2344, 2364), -2353: (2352, 2364), -2356: (2355, 2364), -2392: (2325, 2364), -2393: (2326, 2364), -2394: (2327, 2364), -2395: (2332, 2364), -2396: (2337, 2364), -2397: (2338, 2364), -2398: (2347, 2364), -2399: (2351, 2364), -2507: (2503, 2494), -2508: (2503, 2519), -2524: (2465, 2492), -2525: (2466, 2492), -2527: (2479, 2492), -2611: (2610, 2620), -2614: (2616, 2620), -2649: (2582, 2620), -2650: (2583, 2620), -2651: (2588, 2620), -2654: (2603, 2620), -2888: (2887, 2902), -2891: (2887, 2878), -2892: (2887, 2903), -2908: (2849, 2876), -2909: (2850, 2876), -2964: (2962, 3031), -3018: (3014, 3006), -3019: (3015, 3006), -3020: (3014, 3031), -3144: (3142, 3158), -3264: (3263, 3285), -3271: (3270, 3285), -3272: (3270, 3286), -3274: (3270, 3266), -3275: (3270, 3266, 3285), -3402: (3398, 3390), -3403: (3399, 3390), -3404: (3398, 3415), -3546: (3545, 3530), -3548: (3545, 3535), -3549: (3545, 3535, 3530), -3550: (3545, 3551), -3635: (3661, 3634), -3763: (3789, 3762), -3804: (3755, 3737), -3805: (3755, 3745), -3852: (3851,), -3907: (3906, 4023), -3917: (3916, 4023), -3922: (3921, 4023), -3927: (3926, 4023), -3932: (3931, 4023), -3945: (3904, 4021), -3955: (3953, 3954), -3957: (3953, 3956), -3958: (4018, 3968), -3959: (4018, 3953, 3968), -3960: (4019, 3968), -3961: (4019, 3953, 3968), -3969: (3953, 3968), -3987: (3986, 4023), -3997: (3996, 4023), -4002: (4001, 4023), -4007: (4006, 4023), -4012: (4011, 4023), -4025: (3984, 4021), -4134: (4133, 4142), -7680: (65, 805), -7681: (97, 805), -7682: (66, 775), -7683: (98, 775), -7684: (66, 803), -7685: (98, 803), -7686: (66, 817), -7687: (98, 817), -7688: (67, 807, 769), -7689: (99, 807, 769), -7690: (68, 775), -7691: (100, 775), -7692: (68, 803), -7693: (100, 803), -7694: (68, 817), -7695: (100, 817), -7696: (68, 807), -7697: (100, 807), -7698: (68, 813), -7699: (100, 813), -7700: (69, 772, 768), -7701: (101, 772, 768), -7702: (69, 772, 769), -7703: (101, 772, 769), -7704: (69, 813), -7705: (101, 813), -7706: (69, 816), -7707: (101, 816), -7708: (69, 807, 774), -7709: (101, 807, 774), -7710: (70, 775), -7711: (102, 775), -7712: (71, 772), -7713: (103, 772), -7714: (72, 775), -7715: (104, 775), -7716: (72, 803), -7717: (104, 803), -7718: (72, 776), -7719: (104, 776), -7720: (72, 807), -7721: (104, 807), -7722: (72, 814), -7723: (104, 814), -7724: (73, 816), -7725: (105, 816), -7726: (73, 776, 769), -7727: (105, 776, 769), -7728: (75, 769), -7729: (107, 769), -7730: (75, 803), -7731: (107, 803), -7732: (75, 817), -7733: (107, 817), -7734: (76, 803), -7735: (108, 803), -7736: (76, 803, 772), -7737: (108, 803, 772), -7738: (76, 817), -7739: (108, 817), -7740: (76, 813), -7741: (108, 813), -7742: (77, 769), -7743: (109, 769), -7744: (77, 775), -7745: (109, 775), -7746: (77, 803), -7747: (109, 803), -7748: (78, 775), -7749: (110, 775), -7750: (78, 803), -7751: (110, 803), -7752: (78, 817), -7753: (110, 817), -7754: (78, 813), -7755: (110, 813), -7756: (79, 771, 769), -7757: (111, 771, 769), -7758: (79, 771, 776), -7759: (111, 771, 776), -7760: (79, 772, 768), -7761: (111, 772, 768), -7762: (79, 772, 769), -7763: (111, 772, 769), -7764: (80, 769), -7765: (112, 769), -7766: (80, 775), -7767: (112, 775), -7768: (82, 775), -7769: (114, 775), -7770: (82, 803), -7771: (114, 803), -7772: (82, 803, 772), -7773: (114, 803, 772), -7774: (82, 817), -7775: (114, 817), -7776: (83, 775), -7777: (115, 775), -7778: (83, 803), -7779: (115, 803), -7780: (83, 769, 775), -7781: (115, 769, 775), -7782: (83, 780, 775), -7783: (115, 780, 775), -7784: (83, 803, 775), -7785: (115, 803, 775), -7786: (84, 775), -7787: (116, 775), -7788: (84, 803), -7789: (116, 803), -7790: (84, 817), -7791: (116, 817), -7792: (84, 813), -7793: (116, 813), -7794: (85, 804), -7795: (117, 804), -7796: (85, 816), -7797: (117, 816), -7798: (85, 813), -7799: (117, 813), -7800: (85, 771, 769), -7801: (117, 771, 769), -7802: (85, 772, 776), -7803: (117, 772, 776), -7804: (86, 771), -7805: (118, 771), -7806: (86, 803), -7807: (118, 803), -7808: (87, 768), -7809: (119, 768), -7810: (87, 769), -7811: (119, 769), -7812: (87, 776), -7813: (119, 776), -7814: (87, 775), -7815: (119, 775), -7816: (87, 803), -7817: (119, 803), -7818: (88, 775), -7819: (120, 775), -7820: (88, 776), -7821: (120, 776), -7822: (89, 775), -7823: (121, 775), -7824: (90, 770), -7825: (122, 770), -7826: (90, 803), -7827: (122, 803), -7828: (90, 817), -7829: (122, 817), -7830: (104, 817), -7831: (116, 776), -7832: (119, 778), -7833: (121, 778), -7834: (97, 702), -7835: (115, 775), -7840: (65, 803), -7841: (97, 803), -7842: (65, 777), -7843: (97, 777), -7844: (65, 770, 769), -7845: (97, 770, 769), -7846: (65, 770, 768), -7847: (97, 770, 768), -7848: (65, 770, 777), -7849: (97, 770, 777), -7850: (65, 770, 771), -7851: (97, 770, 771), -7852: (65, 803, 770), -7853: (97, 803, 770), -7854: (65, 774, 769), -7855: (97, 774, 769), -7856: (65, 774, 768), -7857: (97, 774, 768), -7858: (65, 774, 777), -7859: (97, 774, 777), -7860: (65, 774, 771), -7861: (97, 774, 771), -7862: (65, 803, 774), -7863: (97, 803, 774), -7864: (69, 803), -7865: (101, 803), -7866: (69, 777), -7867: (101, 777), -7868: (69, 771), -7869: (101, 771), -7870: (69, 770, 769), -7871: (101, 770, 769), -7872: (69, 770, 768), -7873: (101, 770, 768), -7874: (69, 770, 777), -7875: (101, 770, 777), -7876: (69, 770, 771), -7877: (101, 770, 771), -7878: (69, 803, 770), -7879: (101, 803, 770), -7880: (73, 777), -7881: (105, 777), -7882: (73, 803), -7883: (105, 803), -7884: (79, 803), -7885: (111, 803), -7886: (79, 777), -7887: (111, 777), -7888: (79, 770, 769), -7889: (111, 770, 769), -7890: (79, 770, 768), -7891: (111, 770, 768), -7892: (79, 770, 777), -7893: (111, 770, 777), -7894: (79, 770, 771), -7895: (111, 770, 771), -7896: (79, 803, 770), -7897: (111, 803, 770), -7898: (79, 795, 769), -7899: (111, 795, 769), -7900: (79, 795, 768), -7901: (111, 795, 768), -7902: (79, 795, 777), -7903: (111, 795, 777), -7904: (79, 795, 771), -7905: (111, 795, 771), -7906: (79, 795, 803), -7907: (111, 795, 803), -7908: (85, 803), -7909: (117, 803), -7910: (85, 777), -7911: (117, 777), -7912: (85, 795, 769), -7913: (117, 795, 769), -7914: (85, 795, 768), -7915: (117, 795, 768), -7916: (85, 795, 777), -7917: (117, 795, 777), -7918: (85, 795, 771), -7919: (117, 795, 771), -7920: (85, 795, 803), -7921: (117, 795, 803), -7922: (89, 768), -7923: (121, 768), -7924: (89, 803), -7925: (121, 803), -7926: (89, 777), -7927: (121, 777), -7928: (89, 771), -7929: (121, 771), -7936: (945, 787), -7937: (945, 788), -7938: (945, 787, 768), -7939: (945, 788, 768), -7940: (945, 787, 769), -7941: (945, 788, 769), -7942: (945, 787, 834), -7943: (945, 788, 834), -7944: (913, 787), -7945: (913, 788), -7946: (913, 787, 768), -7947: (913, 788, 768), -7948: (913, 787, 769), -7949: (913, 788, 769), -7950: (913, 787, 834), -7951: (913, 788, 834), -7952: (949, 787), -7953: (949, 788), -7954: (949, 787, 768), -7955: (949, 788, 768), -7956: (949, 787, 769), -7957: (949, 788, 769), -7960: (917, 787), -7961: (917, 788), -7962: (917, 787, 768), -7963: (917, 788, 768), -7964: (917, 787, 769), -7965: (917, 788, 769), -7968: (951, 787), -7969: (951, 788), -7970: (951, 787, 768), -7971: (951, 788, 768), -7972: (951, 787, 769), -7973: (951, 788, 769), -7974: (951, 787, 834), -7975: (951, 788, 834), -7976: (919, 787), -7977: (919, 788), -7978: (919, 787, 768), -7979: (919, 788, 768), -7980: (919, 787, 769), -7981: (919, 788, 769), -7982: (919, 787, 834), -7983: (919, 788, 834), -7984: (953, 787), -7985: (953, 788), -7986: (953, 787, 768), -7987: (953, 788, 768), -7988: (953, 787, 769), -7989: (953, 788, 769), -7990: (953, 787, 834), -7991: (953, 788, 834), -7992: (921, 787), -7993: (921, 788), -7994: (921, 787, 768), -7995: (921, 788, 768), -7996: (921, 787, 769), -7997: (921, 788, 769), -7998: (921, 787, 834), -7999: (921, 788, 834), -8000: (959, 787), -8001: (959, 788), -8002: (959, 787, 768), -8003: (959, 788, 768), -8004: (959, 787, 769), -8005: (959, 788, 769), -8008: (927, 787), -8009: (927, 788), -8010: (927, 787, 768), -8011: (927, 788, 768), -8012: (927, 787, 769), -8013: (927, 788, 769), -8016: (965, 787), -8017: (965, 788), -8018: (965, 787, 768), -8019: (965, 788, 768), -8020: (965, 787, 769), -8021: (965, 788, 769), -8022: (965, 787, 834), -8023: (965, 788, 834), -8025: (933, 788), -8027: (933, 788, 768), -8029: (933, 788, 769), -8031: (933, 788, 834), -8032: (969, 787), -8033: (969, 788), -8034: (969, 787, 768), -8035: (969, 788, 768), -8036: (969, 787, 769), -8037: (969, 788, 769), -8038: (969, 787, 834), -8039: (969, 788, 834), -8040: (937, 787), -8041: (937, 788), -8042: (937, 787, 768), -8043: (937, 788, 768), -8044: (937, 787, 769), -8045: (937, 788, 769), -8046: (937, 787, 834), -8047: (937, 788, 834), -8048: (945, 768), -8049: (945, 769), -8050: (949, 768), -8051: (949, 769), -8052: (951, 768), -8053: (951, 769), -8054: (953, 768), -8055: (953, 769), -8056: (959, 768), -8057: (959, 769), -8058: (965, 768), -8059: (965, 769), -8060: (969, 768), -8061: (969, 769), -8064: (945, 787, 837), -8065: (945, 788, 837), -8066: (945, 787, 768, 837), -8067: (945, 788, 768, 837), -8068: (945, 787, 769, 837), -8069: (945, 788, 769, 837), -8070: (945, 787, 834, 837), -8071: (945, 788, 834, 837), -8072: (913, 787, 837), -8073: (913, 788, 837), -8074: (913, 787, 768, 837), -8075: (913, 788, 768, 837), -8076: (913, 787, 769, 837), -8077: (913, 788, 769, 837), -8078: (913, 787, 834, 837), -8079: (913, 788, 834, 837), -8080: (951, 787, 837), -8081: (951, 788, 837), -8082: (951, 787, 768, 837), -8083: (951, 788, 768, 837), -8084: (951, 787, 769, 837), -8085: (951, 788, 769, 837), -8086: (951, 787, 834, 837), -8087: (951, 788, 834, 837), -8088: (919, 787, 837), -8089: (919, 788, 837), -8090: (919, 787, 768, 837), -8091: (919, 788, 768, 837), -8092: (919, 787, 769, 837), -8093: (919, 788, 769, 837), -8094: (919, 787, 834, 837), -8095: (919, 788, 834, 837), -8096: (969, 787, 837), -8097: (969, 788, 837), -8098: (969, 787, 768, 837), -8099: (969, 788, 768, 837), -8100: (969, 787, 769, 837), -8101: (969, 788, 769, 837), -8102: (969, 787, 834, 837), -8103: (969, 788, 834, 837), -8104: (937, 787, 837), -8105: (937, 788, 837), -8106: (937, 787, 768, 837), -8107: (937, 788, 768, 837), -8108: (937, 787, 769, 837), -8109: (937, 788, 769, 837), -8110: (937, 787, 834, 837), -8111: (937, 788, 834, 837), -8112: (945, 774), -8113: (945, 772), -8114: (945, 768, 837), -8115: (945, 837), -8116: (945, 769, 837), -8118: (945, 834), -8119: (945, 834, 837), -8120: (913, 774), -8121: (913, 772), -8122: (913, 768), -8123: (913, 769), -8124: (913, 837), -8125: (32, 787), -8126: (953,), -8127: (32, 787), -8128: (32, 834), -8129: (32, 776, 834), -8130: (951, 768, 837), -8131: (951, 837), -8132: (951, 769, 837), -8134: (951, 834), -8135: (951, 834, 837), -8136: (917, 768), -8137: (917, 769), -8138: (919, 768), -8139: (919, 769), -8140: (919, 837), -8141: (32, 787, 768), -8142: (32, 787, 769), -8143: (32, 787, 834), -8144: (953, 774), -8145: (953, 772), -8146: (953, 776, 768), -8147: (953, 776, 769), -8150: (953, 834), -8151: (953, 776, 834), -8152: (921, 774), -8153: (921, 772), -8154: (921, 768), -8155: (921, 769), -8157: (32, 788, 768), -8158: (32, 788, 769), -8159: (32, 788, 834), -8160: (965, 774), -8161: (965, 772), -8162: (965, 776, 768), -8163: (965, 776, 769), -8164: (961, 787), -8165: (961, 788), -8166: (965, 834), -8167: (965, 776, 834), -8168: (933, 774), -8169: (933, 772), -8170: (933, 768), -8171: (933, 769), -8172: (929, 788), -8173: (32, 776, 768), -8174: (32, 776, 769), -8175: (96,), -8178: (969, 768, 837), -8179: (969, 837), -8180: (969, 769, 837), -8182: (969, 834), -8183: (969, 834, 837), -8184: (927, 768), -8185: (927, 769), -8186: (937, 768), -8187: (937, 769), -8188: (937, 837), -8189: (32, 769), -8190: (32, 788), -8192: (32,), -8193: (32,), -8194: (32,), -8195: (32,), -8196: (32,), -8197: (32,), -8198: (32,), -8199: (32,), -8200: (32,), -8201: (32,), -8202: (32,), -8209: (8208,), -8215: (32, 819), -8228: (46,), -8229: (46, 46), -8230: (46, 46, 46), -8239: (32,), -8243: (8242, 8242), -8244: (8242, 8242, 8242), -8246: (8245, 8245), -8247: (8245, 8245, 8245), -8252: (33, 33), -8254: (32, 773), -8263: (63, 63), -8264: (63, 33), -8265: (33, 63), -8279: (8242, 8242, 8242, 8242), -8287: (32,), -8304: (48,), -8305: (105,), -8308: (52,), -8309: (53,), -8310: (54,), -8311: (55,), -8312: (56,), -8313: (57,), -8314: (43,), -8315: (8722,), -8316: (61,), -8317: (40,), -8318: (41,), -8319: (110,), -8320: (48,), -8321: (49,), -8322: (50,), -8323: (51,), -8324: (52,), -8325: (53,), -8326: (54,), -8327: (55,), -8328: (56,), -8329: (57,), -8330: (43,), -8331: (8722,), -8332: (61,), -8333: (40,), -8334: (41,), -8360: (82, 115), -8448: (97, 47, 99), -8449: (97, 47, 115), -8450: (67,), -8451: (176, 67), -8453: (99, 47, 111), -8454: (99, 47, 117), -8455: (400,), -8457: (176, 70), -8458: (103,), -8459: (72,), -8460: (72,), -8461: (72,), -8462: (104,), -8463: (295,), -8464: (73,), -8465: (73,), -8466: (76,), -8467: (108,), -8469: (78,), -8470: (78, 111), -8473: (80,), -8474: (81,), -8475: (82,), -8476: (82,), -8477: (82,), -8480: (83, 77), -8481: (84, 69, 76), -8482: (84, 77), -8484: (90,), -8486: (937,), -8488: (90,), -8490: (75,), -8491: (65, 778), -8492: (66,), -8493: (67,), -8495: (101,), -8496: (69,), -8497: (70,), -8499: (77,), -8500: (111,), -8501: (1488,), -8502: (1489,), -8503: (1490,), -8504: (1491,), -8505: (105,), -8509: (947,), -8510: (915,), -8511: (928,), -8512: (8721,), -8517: (68,), -8518: (100,), -8519: (101,), -8520: (105,), -8521: (106,), -8531: (49, 8260, 51), -8532: (50, 8260, 51), -8533: (49, 8260, 53), -8534: (50, 8260, 53), -8535: (51, 8260, 53), -8536: (52, 8260, 53), -8537: (49, 8260, 54), -8538: (53, 8260, 54), -8539: (49, 8260, 56), -8540: (51, 8260, 56), -8541: (53, 8260, 56), -8542: (55, 8260, 56), -8543: (49, 8260), -8544: (73,), -8545: (73, 73), -8546: (73, 73, 73), -8547: (73, 86), -8548: (86,), -8549: (86, 73), -8550: (86, 73, 73), -8551: (86, 73, 73, 73), -8552: (73, 88), -8553: (88,), -8554: (88, 73), -8555: (88, 73, 73), -8556: (76,), -8557: (67,), -8558: (68,), -8559: (77,), -8560: (105,), -8561: (105, 105), -8562: (105, 105, 105), -8563: (105, 118), -8564: (118,), -8565: (118, 105), -8566: (118, 105, 105), -8567: (118, 105, 105, 105), -8568: (105, 120), -8569: (120,), -8570: (120, 105), -8571: (120, 105, 105), -8572: (108,), -8573: (99,), -8574: (100,), -8575: (109,), -8602: (8592, 824), -8603: (8594, 824), -8622: (8596, 824), -8653: (8656, 824), -8654: (8660, 824), -8655: (8658, 824), -8708: (8707, 824), -8713: (8712, 824), -8716: (8715, 824), -8740: (8739, 824), -8742: (8741, 824), -8748: (8747, 8747), -8749: (8747, 8747, 8747), -8751: (8750, 8750), -8752: (8750, 8750, 8750), -8769: (8764, 824), -8772: (8771, 824), -8775: (8773, 824), -8777: (8776, 824), -8800: (61, 824), -8802: (8801, 824), -8813: (8781, 824), -8814: (60, 824), -8815: (62, 824), -8816: (8804, 824), -8817: (8805, 824), -8820: (8818, 824), -8821: (8819, 824), -8824: (8822, 824), -8825: (8823, 824), -8832: (8826, 824), -8833: (8827, 824), -8836: (8834, 824), -8837: (8835, 824), -8840: (8838, 824), -8841: (8839, 824), -8876: (8866, 824), -8877: (8872, 824), -8878: (8873, 824), -8879: (8875, 824), -8928: (8828, 824), -8929: (8829, 824), -8930: (8849, 824), -8931: (8850, 824), -8938: (8882, 824), -8939: (8883, 824), -8940: (8884, 824), -8941: (8885, 824), -9001: (12296,), -9002: (12297,), -9312: (49,), -9313: (50,), -9314: (51,), -9315: (52,), -9316: (53,), -9317: (54,), -9318: (55,), -9319: (56,), -9320: (57,), -9321: (49, 48), -9322: (49, 49), -9323: (49, 50), -9324: (49, 51), -9325: (49, 52), -9326: (49, 53), -9327: (49, 54), -9328: (49, 55), -9329: (49, 56), -9330: (49, 57), -9331: (50, 48), -9332: (40, 49, 41), -9333: (40, 50, 41), -9334: (40, 51, 41), -9335: (40, 52, 41), -9336: (40, 53, 41), -9337: (40, 54, 41), -9338: (40, 55, 41), -9339: (40, 56, 41), -9340: (40, 57, 41), -9341: (40, 49, 48, 41), -9342: (40, 49, 49, 41), -9343: (40, 49, 50, 41), -9344: (40, 49, 51, 41), -9345: (40, 49, 52, 41), -9346: (40, 49, 53, 41), -9347: (40, 49, 54, 41), -9348: (40, 49, 55, 41), -9349: (40, 49, 56, 41), -9350: (40, 49, 57, 41), -9351: (40, 50, 48, 41), -9352: (49, 46), -9353: (50, 46), -9354: (51, 46), -9355: (52, 46), -9356: (53, 46), -9357: (54, 46), -9358: (55, 46), -9359: (56, 46), -9360: (57, 46), -9361: (49, 48, 46), -9362: (49, 49, 46), -9363: (49, 50, 46), -9364: (49, 51, 46), -9365: (49, 52, 46), -9366: (49, 53, 46), -9367: (49, 54, 46), -9368: (49, 55, 46), -9369: (49, 56, 46), -9370: (49, 57, 46), -9371: (50, 48, 46), -9372: (40, 97, 41), -9373: (40, 98, 41), -9374: (40, 99, 41), -9375: (40, 100, 41), -9376: (40, 101, 41), -9377: (40, 102, 41), -9378: (40, 103, 41), -9379: (40, 104, 41), -9380: (40, 105, 41), -9381: (40, 106, 41), -9382: (40, 107, 41), -9383: (40, 108, 41), -9384: (40, 109, 41), -9385: (40, 110, 41), -9386: (40, 111, 41), -9387: (40, 112, 41), -9388: (40, 113, 41), -9389: (40, 114, 41), -9390: (40, 115, 41), -9391: (40, 116, 41), -9392: (40, 117, 41), -9393: (40, 118, 41), -9394: (40, 119, 41), -9395: (40, 120, 41), -9396: (40, 121, 41), -9397: (40, 122, 41), -9398: (65,), -9399: (66,), -9400: (67,), -9401: (68,), -9402: (69,), -9403: (70,), -9404: (71,), -9405: (72,), -9406: (73,), -9407: (74,), -9408: (75,), -9409: (76,), -9410: (77,), -9411: (78,), -9412: (79,), -9413: (80,), -9414: (81,), -9415: (82,), -9416: (83,), -9417: (84,), -9418: (85,), -9419: (86,), -9420: (87,), -9421: (88,), -9422: (89,), -9423: (90,), -9424: (97,), -9425: (98,), -9426: (99,), -9427: (100,), -9428: (101,), -9429: (102,), -9430: (103,), -9431: (104,), -9432: (105,), -9433: (106,), -9434: (107,), -9435: (108,), -9436: (109,), -9437: (110,), -9438: (111,), -9439: (112,), -9440: (113,), -9441: (114,), -9442: (115,), -9443: (116,), -9444: (117,), -9445: (118,), -9446: (119,), -9447: (120,), -9448: (121,), -9449: (122,), -9450: (48,), -10764: (8747, 8747, 8747, 8747), -10868: (58, 58, 61), -10869: (61, 61), -10870: (61, 61, 61), -10972: (10973, 824), -11935: (27597,), -12019: (40863,), -12032: (19968,), -12033: (20008,), -12034: (20022,), -12035: (20031,), -12036: (20057,), -12037: (20101,), -12038: (20108,), -12039: (20128,), -12040: (20154,), -12041: (20799,), -12042: (20837,), -12043: (20843,), -12044: (20866,), -12045: (20886,), -12046: (20907,), -12047: (20960,), -12048: (20981,), -12049: (20992,), -12050: (21147,), -12051: (21241,), -12052: (21269,), -12053: (21274,), -12054: (21304,), -12055: (21313,), -12056: (21340,), -12057: (21353,), -12058: (21378,), -12059: (21430,), -12060: (21448,), -12061: (21475,), -12062: (22231,), -12063: (22303,), -12064: (22763,), -12065: (22786,), -12066: (22794,), -12067: (22805,), -12068: (22823,), -12069: (22899,), -12070: (23376,), -12071: (23424,), -12072: (23544,), -12073: (23567,), -12074: (23586,), -12075: (23608,), -12076: (23662,), -12077: (23665,), -12078: (24027,), -12079: (24037,), -12080: (24049,), -12081: (24062,), -12082: (24178,), -12083: (24186,), -12084: (24191,), -12085: (24308,), -12086: (24318,), -12087: (24331,), -12088: (24339,), -12089: (24400,), -12090: (24417,), -12091: (24435,), -12092: (24515,), -12093: (25096,), -12094: (25142,), -12095: (25163,), -12096: (25903,), -12097: (25908,), -12098: (25991,), -12099: (26007,), -12100: (26020,), -12101: (26041,), -12102: (26080,), -12103: (26085,), -12104: (26352,), -12105: (26376,), -12106: (26408,), -12107: (27424,), -12108: (27490,), -12109: (27513,), -12110: (27571,), -12111: (27595,), -12112: (27604,), -12113: (27611,), -12114: (27663,), -12115: (27668,), -12116: (27700,), -12117: (28779,), -12118: (29226,), -12119: (29238,), -12120: (29243,), -12121: (29247,), -12122: (29255,), -12123: (29273,), -12124: (29275,), -12125: (29356,), -12126: (29572,), -12127: (29577,), -12128: (29916,), -12129: (29926,), -12130: (29976,), -12131: (29983,), -12132: (29992,), -12133: (30000,), -12134: (30091,), -12135: (30098,), -12136: (30326,), -12137: (30333,), -12138: (30382,), -12139: (30399,), -12140: (30446,), -12141: (30683,), -12142: (30690,), -12143: (30707,), -12144: (31034,), -12145: (31160,), -12146: (31166,), -12147: (31348,), -12148: (31435,), -12149: (31481,), -12150: (31859,), -12151: (31992,), -12152: (32566,), -12153: (32593,), -12154: (32650,), -12155: (32701,), -12156: (32769,), -12157: (32780,), -12158: (32786,), -12159: (32819,), -12160: (32895,), -12161: (32905,), -12162: (33251,), -12163: (33258,), -12164: (33267,), -12165: (33276,), -12166: (33292,), -12167: (33307,), -12168: (33311,), -12169: (33390,), -12170: (33394,), -12171: (33400,), -12172: (34381,), -12173: (34411,), -12174: (34880,), -12175: (34892,), -12176: (34915,), -12177: (35198,), -12178: (35211,), -12179: (35282,), -12180: (35328,), -12181: (35895,), -12182: (35910,), -12183: (35925,), -12184: (35960,), -12185: (35997,), -12186: (36196,), -12187: (36208,), -12188: (36275,), -12189: (36523,), -12190: (36554,), -12191: (36763,), -12192: (36784,), -12193: (36789,), -12194: (37009,), -12195: (37193,), -12196: (37318,), -12197: (37324,), -12198: (37329,), -12199: (38263,), -12200: (38272,), -12201: (38428,), -12202: (38582,), -12203: (38585,), -12204: (38632,), -12205: (38737,), -12206: (38750,), -12207: (38754,), -12208: (38761,), -12209: (38859,), -12210: (38893,), -12211: (38899,), -12212: (38913,), -12213: (39080,), -12214: (39131,), -12215: (39135,), -12216: (39318,), -12217: (39321,), -12218: (39340,), -12219: (39592,), -12220: (39640,), -12221: (39647,), -12222: (39717,), -12223: (39727,), -12224: (39730,), -12225: (39740,), -12226: (39770,), -12227: (40165,), -12228: (40565,), -12229: (40575,), -12230: (40613,), -12231: (40635,), -12232: (40643,), -12233: (40653,), -12234: (40657,), -12235: (40697,), -12236: (40701,), -12237: (40718,), -12238: (40723,), -12239: (40736,), -12240: (40763,), -12241: (40778,), -12242: (40786,), -12243: (40845,), -12244: (40860,), -12245: (40864,), -12288: (32,), -12342: (12306,), -12344: (21313,), -12345: (21316,), -12346: (21317,), -12364: (12363, 12441), -12366: (12365, 12441), -12368: (12367, 12441), -12370: (12369, 12441), -12372: (12371, 12441), -12374: (12373, 12441), -12376: (12375, 12441), -12378: (12377, 12441), -12380: (12379, 12441), -12382: (12381, 12441), -12384: (12383, 12441), -12386: (12385, 12441), -12389: (12388, 12441), -12391: (12390, 12441), -12393: (12392, 12441), -12400: (12399, 12441), -12401: (12399, 12442), -12403: (12402, 12441), -12404: (12402, 12442), -12406: (12405, 12441), -12407: (12405, 12442), -12409: (12408, 12441), -12410: (12408, 12442), -12412: (12411, 12441), -12413: (12411, 12442), -12436: (12358, 12441), -12443: (32, 12441), -12444: (32, 12442), -12446: (12445, 12441), -12447: (12424, 12426), -12460: (12459, 12441), -12462: (12461, 12441), -12464: (12463, 12441), -12466: (12465, 12441), -12468: (12467, 12441), -12470: (12469, 12441), -12472: (12471, 12441), -12474: (12473, 12441), -12476: (12475, 12441), -12478: (12477, 12441), -12480: (12479, 12441), -12482: (12481, 12441), -12485: (12484, 12441), -12487: (12486, 12441), -12489: (12488, 12441), -12496: (12495, 12441), -12497: (12495, 12442), -12499: (12498, 12441), -12500: (12498, 12442), -12502: (12501, 12441), -12503: (12501, 12442), -12505: (12504, 12441), -12506: (12504, 12442), -12508: (12507, 12441), -12509: (12507, 12442), -12532: (12454, 12441), -12535: (12527, 12441), -12536: (12528, 12441), -12537: (12529, 12441), -12538: (12530, 12441), -12542: (12541, 12441), -12543: (12467, 12488), -12593: (4352,), -12594: (4353,), -12595: (4522,), -12596: (4354,), -12597: (4524,), -12598: (4525,), -12599: (4355,), -12600: (4356,), -12601: (4357,), -12602: (4528,), -12603: (4529,), -12604: (4530,), -12605: (4531,), -12606: (4532,), -12607: (4533,), -12608: (4378,), -12609: (4358,), -12610: (4359,), -12611: (4360,), -12612: (4385,), -12613: (4361,), -12614: (4362,), -12615: (4363,), -12616: (4364,), -12617: (4365,), -12618: (4366,), -12619: (4367,), -12620: (4368,), -12621: (4369,), -12622: (4370,), -12623: (4449,), -12624: (4450,), -12625: (4451,), -12626: (4452,), -12627: (4453,), -12628: (4454,), -12629: (4455,), -12630: (4456,), -12631: (4457,), -12632: (4458,), -12633: (4459,), -12634: (4460,), -12635: (4461,), -12636: (4462,), -12637: (4463,), -12638: (4464,), -12639: (4465,), -12640: (4466,), -12641: (4467,), -12642: (4468,), -12643: (4469,), -12644: (4448,), -12645: (4372,), -12646: (4373,), -12647: (4551,), -12648: (4552,), -12649: (4556,), -12650: (4558,), -12651: (4563,), -12652: (4567,), -12653: (4569,), -12654: (4380,), -12655: (4573,), -12656: (4575,), -12657: (4381,), -12658: (4382,), -12659: (4384,), -12660: (4386,), -12661: (4387,), -12662: (4391,), -12663: (4393,), -12664: (4395,), -12665: (4396,), -12666: (4397,), -12667: (4398,), -12668: (4399,), -12669: (4402,), -12670: (4406,), -12671: (4416,), -12672: (4423,), -12673: (4428,), -12674: (4593,), -12675: (4594,), -12676: (4439,), -12677: (4440,), -12678: (4441,), -12679: (4484,), -12680: (4485,), -12681: (4488,), -12682: (4497,), -12683: (4498,), -12684: (4500,), -12685: (4510,), -12686: (4513,), -12690: (19968,), -12691: (20108,), -12692: (19977,), -12693: (22235,), -12694: (19978,), -12695: (20013,), -12696: (19979,), -12697: (30002,), -12698: (20057,), -12699: (19993,), -12700: (19969,), -12701: (22825,), -12702: (22320,), -12703: (20154,), -12800: (40, 4352, 41), -12801: (40, 4354, 41), -12802: (40, 4355, 41), -12803: (40, 4357, 41), -12804: (40, 4358, 41), -12805: (40, 4359, 41), -12806: (40, 4361, 41), -12807: (40, 4363, 41), -12808: (40, 4364, 41), -12809: (40, 4366, 41), -12810: (40, 4367, 41), -12811: (40, 4368, 41), -12812: (40, 4369, 41), -12813: (40, 4370, 41), -12814: (40, 4352, 4449, 41), -12815: (40, 4354, 4449, 41), -12816: (40, 4355, 4449, 41), -12817: (40, 4357, 4449, 41), -12818: (40, 4358, 4449, 41), -12819: (40, 4359, 4449, 41), -12820: (40, 4361, 4449, 41), -12821: (40, 4363, 4449, 41), -12822: (40, 4364, 4449, 41), -12823: (40, 4366, 4449, 41), -12824: (40, 4367, 4449, 41), -12825: (40, 4368, 4449, 41), -12826: (40, 4369, 4449, 41), -12827: (40, 4370, 4449, 41), -12828: (40, 4364, 4462, 41), -12832: (40, 19968, 41), -12833: (40, 20108, 41), -12834: (40, 19977, 41), -12835: (40, 22235, 41), -12836: (40, 20116, 41), -12837: (40, 20845, 41), -12838: (40, 19971, 41), -12839: (40, 20843, 41), -12840: (40, 20061, 41), -12841: (40, 21313, 41), -12842: (40, 26376, 41), -12843: (40, 28779, 41), -12844: (40, 27700, 41), -12845: (40, 26408, 41), -12846: (40, 37329, 41), -12847: (40, 22303, 41), -12848: (40, 26085, 41), -12849: (40, 26666, 41), -12850: (40, 26377, 41), -12851: (40, 31038, 41), -12852: (40, 21517, 41), -12853: (40, 29305, 41), -12854: (40, 36001, 41), -12855: (40, 31069, 41), -12856: (40, 21172, 41), -12857: (40, 20195, 41), -12858: (40, 21628, 41), -12859: (40, 23398, 41), -12860: (40, 30435, 41), -12861: (40, 20225, 41), -12862: (40, 36039, 41), -12863: (40, 21332, 41), -12864: (40, 31085, 41), -12865: (40, 20241, 41), -12866: (40, 33258, 41), -12867: (40, 33267, 41), -12881: (50, 49), -12882: (50, 50), -12883: (50, 51), -12884: (50, 52), -12885: (50, 53), -12886: (50, 54), -12887: (50, 55), -12888: (50, 56), -12889: (50, 57), -12890: (51, 48), -12891: (51, 49), -12892: (51, 50), -12893: (51, 51), -12894: (51, 52), -12895: (51, 53), -12896: (4352,), -12897: (4354,), -12898: (4355,), -12899: (4357,), -12900: (4358,), -12901: (4359,), -12902: (4361,), -12903: (4363,), -12904: (4364,), -12905: (4366,), -12906: (4367,), -12907: (4368,), -12908: (4369,), -12909: (4370,), -12910: (4352, 4449), -12911: (4354, 4449), -12912: (4355, 4449), -12913: (4357, 4449), -12914: (4358, 4449), -12915: (4359, 4449), -12916: (4361, 4449), -12917: (4363, 4449), -12918: (4364, 4449), -12919: (4366, 4449), -12920: (4367, 4449), -12921: (4368, 4449), -12922: (4369, 4449), -12923: (4370, 4449), -12928: (19968,), -12929: (20108,), -12930: (19977,), -12931: (22235,), -12932: (20116,), -12933: (20845,), -12934: (19971,), -12935: (20843,), -12936: (20061,), -12937: (21313,), -12938: (26376,), -12939: (28779,), -12940: (27700,), -12941: (26408,), -12942: (37329,), -12943: (22303,), -12944: (26085,), -12945: (26666,), -12946: (26377,), -12947: (31038,), -12948: (21517,), -12949: (29305,), -12950: (36001,), -12951: (31069,), -12952: (21172,), -12953: (31192,), -12954: (30007,), -12955: (22899,), -12956: (36969,), -12957: (20778,), -12958: (21360,), -12959: (27880,), -12960: (38917,), -12961: (20241,), -12962: (20889,), -12963: (27491,), -12964: (19978,), -12965: (20013,), -12966: (19979,), -12967: (24038,), -12968: (21491,), -12969: (21307,), -12970: (23447,), -12971: (23398,), -12972: (30435,), -12973: (20225,), -12974: (36039,), -12975: (21332,), -12976: (22812,), -12977: (51, 54), -12978: (51, 55), -12979: (51, 56), -12980: (51, 57), -12981: (52, 48), -12982: (52, 49), -12983: (52, 50), -12984: (52, 51), -12985: (52, 52), -12986: (52, 53), -12987: (52, 54), -12988: (52, 55), -12989: (52, 56), -12990: (52, 57), -12991: (53, 48), -12992: (49, 26376), -12993: (50, 26376), -12994: (51, 26376), -12995: (52, 26376), -12996: (53, 26376), -12997: (54, 26376), -12998: (55, 26376), -12999: (56, 26376), -13000: (57, 26376), -13001: (49, 48, 26376), -13002: (49, 49, 26376), -13003: (49, 50, 26376), -13008: (12450,), -13009: (12452,), -13010: (12454,), -13011: (12456,), -13012: (12458,), -13013: (12459,), -13014: (12461,), -13015: (12463,), -13016: (12465,), -13017: (12467,), -13018: (12469,), -13019: (12471,), -13020: (12473,), -13021: (12475,), -13022: (12477,), -13023: (12479,), -13024: (12481,), -13025: (12484,), -13026: (12486,), -13027: (12488,), -13028: (12490,), -13029: (12491,), -13030: (12492,), -13031: (12493,), -13032: (12494,), -13033: (12495,), -13034: (12498,), -13035: (12501,), -13036: (12504,), -13037: (12507,), -13038: (12510,), -13039: (12511,), -13040: (12512,), -13041: (12513,), -13042: (12514,), -13043: (12516,), -13044: (12518,), -13045: (12520,), -13046: (12521,), -13047: (12522,), -13048: (12523,), -13049: (12524,), -13050: (12525,), -13051: (12527,), -13052: (12528,), -13053: (12529,), -13054: (12530,), -13056: (12450, 12495, 12442, 12540, 12488), -13057: (12450, 12523, 12501, 12449), -13058: (12450, 12531, 12504, 12442, 12450), -13059: (12450, 12540, 12523), -13060: (12452, 12491, 12531, 12463, 12441), -13061: (12452, 12531, 12481), -13062: (12454, 12457, 12531), -13063: (12456, 12473, 12463, 12540, 12488, 12441), -13064: (12456, 12540, 12459, 12540), -13065: (12458, 12531, 12473), -13066: (12458, 12540, 12512), -13067: (12459, 12452, 12522), -13068: (12459, 12521, 12483, 12488), -13069: (12459, 12525, 12522, 12540), -13070: (12459, 12441, 12525, 12531), -13071: (12459, 12441, 12531, 12510), -13072: (12461, 12441, 12459, 12441), -13073: (12461, 12441, 12491, 12540), -13074: (12461, 12517, 12522, 12540), -13075: (12461, 12441, 12523, 12479, 12441, 12540), -13076: (12461, 12525), -13077: (12461, 12525, 12463, 12441, 12521, 12512), -13078: (12461, 12525, 12513, 12540, 12488, 12523), -13079: (12461, 12525, 12527, 12483, 12488), -13080: (12463, 12441, 12521, 12512), -13081: (12463, 12441, 12521, 12512, 12488, 12531), -13082: (12463, 12523, 12475, 12441, 12452, 12525), -13083: (12463, 12525, 12540, 12493), -13084: (12465, 12540, 12473), -13085: (12467, 12523, 12490), -13086: (12467, 12540, 12507, 12442), -13087: (12469, 12452, 12463, 12523), -13088: (12469, 12531, 12481, 12540, 12512), -13089: (12471, 12522, 12531, 12463, 12441), -13090: (12475, 12531, 12481), -13091: (12475, 12531, 12488), -13092: (12479, 12441, 12540, 12473), -13093: (12486, 12441, 12471), -13094: (12488, 12441, 12523), -13095: (12488, 12531), -13096: (12490, 12494), -13097: (12494, 12483, 12488), -13098: (12495, 12452, 12484), -13099: (12495, 12442, 12540, 12475, 12531, 12488), -13100: (12495, 12442, 12540, 12484), -13101: (12495, 12441, 12540, 12524, 12523), -13102: (12498, 12442, 12450, 12473, 12488, 12523), -13103: (12498, 12442, 12463, 12523), -13104: (12498, 12442, 12467), -13105: (12498, 12441, 12523), -13106: (12501, 12449, 12521, 12483, 12488, 12441), -13107: (12501, 12451, 12540, 12488), -13108: (12501, 12441, 12483, 12471, 12455, 12523), -13109: (12501, 12521, 12531), -13110: (12504, 12463, 12479, 12540, 12523), -13111: (12504, 12442, 12477), -13112: (12504, 12442, 12491, 12498), -13113: (12504, 12523, 12484), -13114: (12504, 12442, 12531, 12473), -13115: (12504, 12442, 12540, 12471, 12441), -13116: (12504, 12441, 12540, 12479), -13117: (12507, 12442, 12452, 12531, 12488), -13118: (12507, 12441, 12523, 12488), -13119: (12507, 12531), -13120: (12507, 12442, 12531, 12488, 12441), -13121: (12507, 12540, 12523), -13122: (12507, 12540, 12531), -13123: (12510, 12452, 12463, 12525), -13124: (12510, 12452, 12523), -13125: (12510, 12483, 12495), -13126: (12510, 12523, 12463), -13127: (12510, 12531, 12471, 12519, 12531), -13128: (12511, 12463, 12525, 12531), -13129: (12511, 12522), -13130: (12511, 12522, 12495, 12441, 12540, 12523), -13131: (12513, 12459, 12441), -13132: (12513, 12459, 12441, 12488, 12531), -13133: (12513, 12540, 12488, 12523), -13134: (12516, 12540, 12488, 12441), -13135: (12516, 12540, 12523), -13136: (12518, 12450, 12531), -13137: (12522, 12483, 12488, 12523), -13138: (12522, 12521), -13139: (12523, 12498, 12442, 12540), -13140: (12523, 12540, 12501, 12441, 12523), -13141: (12524, 12512), -13142: (12524, 12531, 12488, 12465, 12441, 12531), -13143: (12527, 12483, 12488), -13144: (48, 28857), -13145: (49, 28857), -13146: (50, 28857), -13147: (51, 28857), -13148: (52, 28857), -13149: (53, 28857), -13150: (54, 28857), -13151: (55, 28857), -13152: (56, 28857), -13153: (57, 28857), -13154: (49, 48, 28857), -13155: (49, 49, 28857), -13156: (49, 50, 28857), -13157: (49, 51, 28857), -13158: (49, 52, 28857), -13159: (49, 53, 28857), -13160: (49, 54, 28857), -13161: (49, 55, 28857), -13162: (49, 56, 28857), -13163: (49, 57, 28857), -13164: (50, 48, 28857), -13165: (50, 49, 28857), -13166: (50, 50, 28857), -13167: (50, 51, 28857), -13168: (50, 52, 28857), -13169: (104, 80, 97), -13170: (100, 97), -13171: (65, 85), -13172: (98, 97, 114), -13173: (111, 86), -13174: (112, 99), -13179: (24179, 25104), -13180: (26157, 21644), -13181: (22823, 27491), -13182: (26126, 27835), -13183: (26666, 24335, 20250, 31038), -13184: (112, 65), -13185: (110, 65), -13186: (956, 65), -13187: (109, 65), -13188: (107, 65), -13189: (75, 66), -13190: (77, 66), -13191: (71, 66), -13192: (99, 97, 108), -13193: (107, 99, 97, 108), -13194: (112, 70), -13195: (110, 70), -13196: (956, 70), -13197: (956, 103), -13198: (109, 103), -13199: (107, 103), -13200: (72, 122), -13201: (107, 72, 122), -13202: (77, 72, 122), -13203: (71, 72, 122), -13204: (84, 72, 122), -13205: (956, 108), -13206: (109, 108), -13207: (100, 108), -13208: (107, 108), -13209: (102, 109), -13210: (110, 109), -13211: (956, 109), -13212: (109, 109), -13213: (99, 109), -13214: (107, 109), -13215: (109, 109, 50), -13216: (99, 109, 50), -13217: (109, 50), -13218: (107, 109, 50), -13219: (109, 109, 51), -13220: (99, 109, 51), -13221: (109, 51), -13222: (107, 109, 51), -13223: (109, 8725, 115), -13224: (109, 8725, 115, 50), -13225: (80, 97), -13226: (107, 80, 97), -13227: (77, 80, 97), -13228: (71, 80, 97), -13229: (114, 97, 100), -13230: (114, 97, 100, 8725, 115), -13231: (114, 97, 100, 8725, 115, 50), -13232: (112, 115), -13233: (110, 115), -13234: (956, 115), -13235: (109, 115), -13236: (112, 86), -13237: (110, 86), -13238: (956, 86), -13239: (109, 86), -13240: (107, 86), -13241: (77, 86), -13242: (112, 87), -13243: (110, 87), -13244: (956, 87), -13245: (109, 87), -13246: (107, 87), -13247: (77, 87), -13248: (107, 937), -13249: (77, 937), -13250: (97, 46, 109, 46), -13251: (66, 113), -13252: (99, 99), -13253: (99, 100), -13254: (67, 8725, 107, 103), -13255: (67, 111, 46), -13256: (100, 66), -13257: (71, 121), -13258: (104, 97), -13259: (72, 80), -13260: (105, 110), -13261: (75, 75), -13262: (75, 77), -13263: (107, 116), -13264: (108, 109), -13265: (108, 110), -13266: (108, 111, 103), -13267: (108, 120), -13268: (109, 98), -13269: (109, 105, 108), -13270: (109, 111, 108), -13271: (80, 72), -13272: (112, 46, 109, 46), -13273: (80, 80, 77), -13274: (80, 82), -13275: (115, 114), -13276: (83, 118), -13277: (87, 98), -13280: (49, 26085), -13281: (50, 26085), -13282: (51, 26085), -13283: (52, 26085), -13284: (53, 26085), -13285: (54, 26085), -13286: (55, 26085), -13287: (56, 26085), -13288: (57, 26085), -13289: (49, 48, 26085), -13290: (49, 49, 26085), -13291: (49, 50, 26085), -13292: (49, 51, 26085), -13293: (49, 52, 26085), -13294: (49, 53, 26085), -13295: (49, 54, 26085), -13296: (49, 55, 26085), -13297: (49, 56, 26085), -13298: (49, 57, 26085), -13299: (50, 48, 26085), -13300: (50, 49, 26085), -13301: (50, 50, 26085), -13302: (50, 51, 26085), -13303: (50, 52, 26085), -13304: (50, 53, 26085), -13305: (50, 54, 26085), -13306: (50, 55, 26085), -13307: (50, 56, 26085), -13308: (50, 57, 26085), -13309: (51, 48, 26085), -13310: (51, 49, 26085), -63744: (35912,), -63745: (26356,), -63746: (36554,), -63747: (36040,), -63748: (28369,), -63749: (20018,), -63750: (21477,), -63751: (40860,), -63752: (40860,), -63753: (22865,), -63754: (37329,), -63755: (21895,), -63756: (22856,), -63757: (25078,), -63758: (30313,), -63759: (32645,), -63760: (34367,), -63761: (34746,), -63762: (35064,), -63763: (37007,), -63764: (27138,), -63765: (27931,), -63766: (28889,), -63767: (29662,), -63768: (33853,), -63769: (37226,), -63770: (39409,), -63771: (20098,), -63772: (21365,), -63773: (27396,), -63774: (29211,), -63775: (34349,), -63776: (40478,), -63777: (23888,), -63778: (28651,), -63779: (34253,), -63780: (35172,), -63781: (25289,), -63782: (33240,), -63783: (34847,), -63784: (24266,), -63785: (26391,), -63786: (28010,), -63787: (29436,), -63788: (37070,), -63789: (20358,), -63790: (20919,), -63791: (21214,), -63792: (25796,), -63793: (27347,), -63794: (29200,), -63795: (30439,), -63796: (32769,), -63797: (34310,), -63798: (34396,), -63799: (36335,), -63800: (38706,), -63801: (39791,), -63802: (40442,), -63803: (30860,), -63804: (31103,), -63805: (32160,), -63806: (33737,), -63807: (37636,), -63808: (40575,), -63809: (35542,), -63810: (22751,), -63811: (24324,), -63812: (31840,), -63813: (32894,), -63814: (29282,), -63815: (30922,), -63816: (36034,), -63817: (38647,), -63818: (22744,), -63819: (23650,), -63820: (27155,), -63821: (28122,), -63822: (28431,), -63823: (32047,), -63824: (32311,), -63825: (38475,), -63826: (21202,), -63827: (32907,), -63828: (20956,), -63829: (20940,), -63830: (31260,), -63831: (32190,), -63832: (33777,), -63833: (38517,), -63834: (35712,), -63835: (25295,), -63836: (27138,), -63837: (35582,), -63838: (20025,), -63839: (23527,), -63840: (24594,), -63841: (29575,), -63842: (30064,), -63843: (21271,), -63844: (30971,), -63845: (20415,), -63846: (24489,), -63847: (19981,), -63848: (27852,), -63849: (25976,), -63850: (32034,), -63851: (21443,), -63852: (22622,), -63853: (30465,), -63854: (33865,), -63855: (35498,), -63856: (27578,), -63857: (36784,), -63858: (27784,), -63859: (25342,), -63860: (33509,), -63861: (25504,), -63862: (30053,), -63863: (20142,), -63864: (20841,), -63865: (20937,), -63866: (26753,), -63867: (31975,), -63868: (33391,), -63869: (35538,), -63870: (37327,), -63871: (21237,), -63872: (21570,), -63873: (22899,), -63874: (24300,), -63875: (26053,), -63876: (28670,), -63877: (31018,), -63878: (38317,), -63879: (39530,), -63880: (40599,), -63881: (40654,), -63882: (21147,), -63883: (26310,), -63884: (27511,), -63885: (36706,), -63886: (24180,), -63887: (24976,), -63888: (25088,), -63889: (25754,), -63890: (28451,), -63891: (29001,), -63892: (29833,), -63893: (31178,), -63894: (32244,), -63895: (32879,), -63896: (36646,), -63897: (34030,), -63898: (36899,), -63899: (37706,), -63900: (21015,), -63901: (21155,), -63902: (21693,), -63903: (28872,), -63904: (35010,), -63905: (35498,), -63906: (24265,), -63907: (24565,), -63908: (25467,), -63909: (27566,), -63910: (31806,), -63911: (29557,), -63912: (20196,), -63913: (22265,), -63914: (23527,), -63915: (23994,), -63916: (24604,), -63917: (29618,), -63918: (29801,), -63919: (32666,), -63920: (32838,), -63921: (37428,), -63922: (38646,), -63923: (38728,), -63924: (38936,), -63925: (20363,), -63926: (31150,), -63927: (37300,), -63928: (38584,), -63929: (24801,), -63930: (20102,), -63931: (20698,), -63932: (23534,), -63933: (23615,), -63934: (26009,), -63935: (27138,), -63936: (29134,), -63937: (30274,), -63938: (34044,), -63939: (36988,), -63940: (40845,), -63941: (26248,), -63942: (38446,), -63943: (21129,), -63944: (26491,), -63945: (26611,), -63946: (27969,), -63947: (28316,), -63948: (29705,), -63949: (30041,), -63950: (30827,), -63951: (32016,), -63952: (39006,), -63953: (20845,), -63954: (25134,), -63955: (38520,), -63956: (20523,), -63957: (23833,), -63958: (28138,), -63959: (36650,), -63960: (24459,), -63961: (24900,), -63962: (26647,), -63963: (29575,), -63964: (38534,), -63965: (21033,), -63966: (21519,), -63967: (23653,), -63968: (26131,), -63969: (26446,), -63970: (26792,), -63971: (27877,), -63972: (29702,), -63973: (30178,), -63974: (32633,), -63975: (35023,), -63976: (35041,), -63977: (37324,), -63978: (38626,), -63979: (21311,), -63980: (28346,), -63981: (21533,), -63982: (29136,), -63983: (29848,), -63984: (34298,), -63985: (38563,), -63986: (40023,), -63987: (40607,), -63988: (26519,), -63989: (28107,), -63990: (33256,), -63991: (31435,), -63992: (31520,), -63993: (31890,), -63994: (29376,), -63995: (28825,), -63996: (35672,), -63997: (20160,), -63998: (33590,), -63999: (21050,), -64000: (20999,), -64001: (24230,), -64002: (25299,), -64003: (31958,), -64004: (23429,), -64005: (27934,), -64006: (26292,), -64007: (36667,), -64008: (34892,), -64009: (38477,), -64010: (35211,), -64011: (24275,), -64012: (20800,), -64013: (21952,), -64016: (22618,), -64018: (26228,), -64021: (20958,), -64022: (29482,), -64023: (30410,), -64024: (31036,), -64025: (31070,), -64026: (31077,), -64027: (31119,), -64028: (38742,), -64029: (31934,), -64030: (32701,), -64032: (34322,), -64034: (35576,), -64037: (36920,), -64038: (37117,), -64042: (39151,), -64043: (39164,), -64044: (39208,), -64045: (40372,), -64048: (20398,), -64049: (20711,), -64050: (20813,), -64051: (21193,), -64052: (21220,), -64053: (21329,), -64054: (21917,), -64055: (22022,), -64056: (22120,), -64057: (22592,), -64058: (22696,), -64059: (23652,), -64060: (23662,), -64061: (24724,), -64062: (24936,), -64063: (24974,), -64064: (25074,), -64065: (25935,), -64066: (26082,), -64067: (26257,), -64068: (26757,), -64069: (28023,), -64070: (28186,), -64071: (28450,), -64072: (29038,), -64073: (29227,), -64074: (29730,), -64075: (30865,), -64076: (31038,), -64077: (31049,), -64078: (31048,), -64079: (31056,), -64080: (31062,), -64081: (31069,), -64082: (31117,), -64083: (31118,), -64084: (31296,), -64085: (31361,), -64086: (31680,), -64087: (32244,), -64088: (32265,), -64089: (32321,), -64090: (32626,), -64091: (32773,), -64092: (33261,), -64093: (33401,), -64094: (33401,), -64095: (33879,), -64096: (35088,), -64097: (35222,), -64098: (35585,), -64099: (35641,), -64100: (36051,), -64101: (36104,), -64102: (36790,), -64103: (36920,), -64104: (38627,), -64105: (38911,), -64106: (38971,), -64256: (102, 102), -64257: (102, 105), -64258: (102, 108), -64259: (102, 102, 105), -64260: (102, 102, 108), -64261: (115, 116), -64262: (115, 116), -64275: (1396, 1398), -64276: (1396, 1381), -64277: (1396, 1387), -64278: (1406, 1398), -64279: (1396, 1389), -64285: (1497, 1460), -64287: (1522, 1463), -64288: (1506,), -64289: (1488,), -64290: (1491,), -64291: (1492,), -64292: (1499,), -64293: (1500,), -64294: (1501,), -64295: (1512,), -64296: (1514,), -64297: (43,), -64298: (1513, 1473), -64299: (1513, 1474), -64300: (1513, 1468, 1473), -64301: (1513, 1468, 1474), -64302: (1488, 1463), -64303: (1488, 1464), -64304: (1488, 1468), -64305: (1489, 1468), -64306: (1490, 1468), -64307: (1491, 1468), -64308: (1492, 1468), -64309: (1493, 1468), -64310: (1494, 1468), -64312: (1496, 1468), -64313: (1497, 1468), -64314: (1498, 1468), -64315: (1499, 1468), -64316: (1500, 1468), -64318: (1502, 1468), -64320: (1504, 1468), -64321: (1505, 1468), -64323: (1507, 1468), -64324: (1508, 1468), -64326: (1510, 1468), -64327: (1511, 1468), -64328: (1512, 1468), -64329: (1513, 1468), -64330: (1514, 1468), -64331: (1493, 1465), -64332: (1489, 1471), -64333: (1499, 1471), -64334: (1508, 1471), -64335: (1488, 1500), -64336: (1649,), -64337: (1649,), -64338: (1659,), -64339: (1659,), -64340: (1659,), -64341: (1659,), -64342: (1662,), -64343: (1662,), -64344: (1662,), -64345: (1662,), -64346: (1664,), -64347: (1664,), -64348: (1664,), -64349: (1664,), -64350: (1658,), -64351: (1658,), -64352: (1658,), -64353: (1658,), -64354: (1663,), -64355: (1663,), -64356: (1663,), -64357: (1663,), -64358: (1657,), -64359: (1657,), -64360: (1657,), -64361: (1657,), -64362: (1700,), -64363: (1700,), -64364: (1700,), -64365: (1700,), -64366: (1702,), -64367: (1702,), -64368: (1702,), -64369: (1702,), -64370: (1668,), -64371: (1668,), -64372: (1668,), -64373: (1668,), -64374: (1667,), -64375: (1667,), -64376: (1667,), -64377: (1667,), -64378: (1670,), -64379: (1670,), -64380: (1670,), -64381: (1670,), -64382: (1671,), -64383: (1671,), -64384: (1671,), -64385: (1671,), -64386: (1677,), -64387: (1677,), -64388: (1676,), -64389: (1676,), -64390: (1678,), -64391: (1678,), -64392: (1672,), -64393: (1672,), -64394: (1688,), -64395: (1688,), -64396: (1681,), -64397: (1681,), -64398: (1705,), -64399: (1705,), -64400: (1705,), -64401: (1705,), -64402: (1711,), -64403: (1711,), -64404: (1711,), -64405: (1711,), -64406: (1715,), -64407: (1715,), -64408: (1715,), -64409: (1715,), -64410: (1713,), -64411: (1713,), -64412: (1713,), -64413: (1713,), -64414: (1722,), -64415: (1722,), -64416: (1723,), -64417: (1723,), -64418: (1723,), -64419: (1723,), -64420: (1749, 1620), -64421: (1749, 1620), -64422: (1729,), -64423: (1729,), -64424: (1729,), -64425: (1729,), -64426: (1726,), -64427: (1726,), -64428: (1726,), -64429: (1726,), -64430: (1746,), -64431: (1746,), -64432: (1746, 1620), -64433: (1746, 1620), -64467: (1709,), -64468: (1709,), -64469: (1709,), -64470: (1709,), -64471: (1735,), -64472: (1735,), -64473: (1734,), -64474: (1734,), -64475: (1736,), -64476: (1736,), -64477: (1735, 1652), -64478: (1739,), -64479: (1739,), -64480: (1733,), -64481: (1733,), -64482: (1737,), -64483: (1737,), -64484: (1744,), -64485: (1744,), -64486: (1744,), -64487: (1744,), -64488: (1609,), -64489: (1609,), -64490: (1610, 1620, 1575), -64491: (1610, 1620, 1575), -64492: (1610, 1620, 1749), -64493: (1610, 1620, 1749), -64494: (1610, 1620, 1608), -64495: (1610, 1620, 1608), -64496: (1610, 1620, 1735), -64497: (1610, 1620, 1735), -64498: (1610, 1620, 1734), -64499: (1610, 1620, 1734), -64500: (1610, 1620, 1736), -64501: (1610, 1620, 1736), -64502: (1610, 1620, 1744), -64503: (1610, 1620, 1744), -64504: (1610, 1620, 1744), -64505: (1610, 1620, 1609), -64506: (1610, 1620, 1609), -64507: (1610, 1620, 1609), -64508: (1740,), -64509: (1740,), -64510: (1740,), -64511: (1740,), -64512: (1610, 1620, 1580), -64513: (1610, 1620, 1581), -64514: (1610, 1620, 1605), -64515: (1610, 1620, 1609), -64516: (1610, 1620, 1610), -64517: (1576, 1580), -64518: (1576, 1581), -64519: (1576, 1582), -64520: (1576, 1605), -64521: (1576, 1609), -64522: (1576, 1610), -64523: (1578, 1580), -64524: (1578, 1581), -64525: (1578, 1582), -64526: (1578, 1605), -64527: (1578, 1609), -64528: (1578, 1610), -64529: (1579, 1580), -64530: (1579, 1605), -64531: (1579, 1609), -64532: (1579, 1610), -64533: (1580, 1581), -64534: (1580, 1605), -64535: (1581, 1580), -64536: (1581, 1605), -64537: (1582, 1580), -64538: (1582, 1581), -64539: (1582, 1605), -64540: (1587, 1580), -64541: (1587, 1581), -64542: (1587, 1582), -64543: (1587, 1605), -64544: (1589, 1581), -64545: (1589, 1605), -64546: (1590, 1580), -64547: (1590, 1581), -64548: (1590, 1582), -64549: (1590, 1605), -64550: (1591, 1581), -64551: (1591, 1605), -64552: (1592, 1605), -64553: (1593, 1580), -64554: (1593, 1605), -64555: (1594, 1580), -64556: (1594, 1605), -64557: (1601, 1580), -64558: (1601, 1581), -64559: (1601, 1582), -64560: (1601, 1605), -64561: (1601, 1609), -64562: (1601, 1610), -64563: (1602, 1581), -64564: (1602, 1605), -64565: (1602, 1609), -64566: (1602, 1610), -64567: (1603, 1575), -64568: (1603, 1580), -64569: (1603, 1581), -64570: (1603, 1582), -64571: (1603, 1604), -64572: (1603, 1605), -64573: (1603, 1609), -64574: (1603, 1610), -64575: (1604, 1580), -64576: (1604, 1581), -64577: (1604, 1582), -64578: (1604, 1605), -64579: (1604, 1609), -64580: (1604, 1610), -64581: (1605, 1580), -64582: (1605, 1581), -64583: (1605, 1582), -64584: (1605, 1605), -64585: (1605, 1609), -64586: (1605, 1610), -64587: (1606, 1580), -64588: (1606, 1581), -64589: (1606, 1582), -64590: (1606, 1605), -64591: (1606, 1609), -64592: (1606, 1610), -64593: (1607, 1580), -64594: (1607, 1605), -64595: (1607, 1609), -64596: (1607, 1610), -64597: (1610, 1580), -64598: (1610, 1581), -64599: (1610, 1582), -64600: (1610, 1605), -64601: (1610, 1609), -64602: (1610, 1610), -64603: (1584, 1648), -64604: (1585, 1648), -64605: (1609, 1648), -64606: (32, 1612, 1617), -64607: (32, 1613, 1617), -64608: (32, 1614, 1617), -64609: (32, 1615, 1617), -64610: (32, 1616, 1617), -64611: (32, 1617, 1648), -64612: (1610, 1620, 1585), -64613: (1610, 1620, 1586), -64614: (1610, 1620, 1605), -64615: (1610, 1620, 1606), -64616: (1610, 1620, 1609), -64617: (1610, 1620, 1610), -64618: (1576, 1585), -64619: (1576, 1586), -64620: (1576, 1605), -64621: (1576, 1606), -64622: (1576, 1609), -64623: (1576, 1610), -64624: (1578, 1585), -64625: (1578, 1586), -64626: (1578, 1605), -64627: (1578, 1606), -64628: (1578, 1609), -64629: (1578, 1610), -64630: (1579, 1585), -64631: (1579, 1586), -64632: (1579, 1605), -64633: (1579, 1606), -64634: (1579, 1609), -64635: (1579, 1610), -64636: (1601, 1609), -64637: (1601, 1610), -64638: (1602, 1609), -64639: (1602, 1610), -64640: (1603, 1575), -64641: (1603, 1604), -64642: (1603, 1605), -64643: (1603, 1609), -64644: (1603, 1610), -64645: (1604, 1605), -64646: (1604, 1609), -64647: (1604, 1610), -64648: (1605, 1575), -64649: (1605, 1605), -64650: (1606, 1585), -64651: (1606, 1586), -64652: (1606, 1605), -64653: (1606, 1606), -64654: (1606, 1609), -64655: (1606, 1610), -64656: (1609, 1648), -64657: (1610, 1585), -64658: (1610, 1586), -64659: (1610, 1605), -64660: (1610, 1606), -64661: (1610, 1609), -64662: (1610, 1610), -64663: (1610, 1620, 1580), -64664: (1610, 1620, 1581), -64665: (1610, 1620, 1582), -64666: (1610, 1620, 1605), -64667: (1610, 1620, 1607), -64668: (1576, 1580), -64669: (1576, 1581), -64670: (1576, 1582), -64671: (1576, 1605), -64672: (1576, 1607), -64673: (1578, 1580), -64674: (1578, 1581), -64675: (1578, 1582), -64676: (1578, 1605), -64677: (1578, 1607), -64678: (1579, 1605), -64679: (1580, 1581), -64680: (1580, 1605), -64681: (1581, 1580), -64682: (1581, 1605), -64683: (1582, 1580), -64684: (1582, 1605), -64685: (1587, 1580), -64686: (1587, 1581), -64687: (1587, 1582), -64688: (1587, 1605), -64689: (1589, 1581), -64690: (1589, 1582), -64691: (1589, 1605), -64692: (1590, 1580), -64693: (1590, 1581), -64694: (1590, 1582), -64695: (1590, 1605), -64696: (1591, 1581), -64697: (1592, 1605), -64698: (1593, 1580), -64699: (1593, 1605), -64700: (1594, 1580), -64701: (1594, 1605), -64702: (1601, 1580), -64703: (1601, 1581), -64704: (1601, 1582), -64705: (1601, 1605), -64706: (1602, 1581), -64707: (1602, 1605), -64708: (1603, 1580), -64709: (1603, 1581), -64710: (1603, 1582), -64711: (1603, 1604), -64712: (1603, 1605), -64713: (1604, 1580), -64714: (1604, 1581), -64715: (1604, 1582), -64716: (1604, 1605), -64717: (1604, 1607), -64718: (1605, 1580), -64719: (1605, 1581), -64720: (1605, 1582), -64721: (1605, 1605), -64722: (1606, 1580), -64723: (1606, 1581), -64724: (1606, 1582), -64725: (1606, 1605), -64726: (1606, 1607), -64727: (1607, 1580), -64728: (1607, 1605), -64729: (1607, 1648), -64730: (1610, 1580), -64731: (1610, 1581), -64732: (1610, 1582), -64733: (1610, 1605), -64734: (1610, 1607), -64735: (1610, 1620, 1605), -64736: (1610, 1620, 1607), -64737: (1576, 1605), -64738: (1576, 1607), -64739: (1578, 1605), -64740: (1578, 1607), -64741: (1579, 1605), -64742: (1579, 1607), -64743: (1587, 1605), -64744: (1587, 1607), -64745: (1588, 1605), -64746: (1588, 1607), -64747: (1603, 1604), -64748: (1603, 1605), -64749: (1604, 1605), -64750: (1606, 1605), -64751: (1606, 1607), -64752: (1610, 1605), -64753: (1610, 1607), -64754: (1600, 1614, 1617), -64755: (1600, 1615, 1617), -64756: (1600, 1616, 1617), -64757: (1591, 1609), -64758: (1591, 1610), -64759: (1593, 1609), -64760: (1593, 1610), -64761: (1594, 1609), -64762: (1594, 1610), -64763: (1587, 1609), -64764: (1587, 1610), -64765: (1588, 1609), -64766: (1588, 1610), -64767: (1581, 1609), -64768: (1581, 1610), -64769: (1580, 1609), -64770: (1580, 1610), -64771: (1582, 1609), -64772: (1582, 1610), -64773: (1589, 1609), -64774: (1589, 1610), -64775: (1590, 1609), -64776: (1590, 1610), -64777: (1588, 1580), -64778: (1588, 1581), -64779: (1588, 1582), -64780: (1588, 1605), -64781: (1588, 1585), -64782: (1587, 1585), -64783: (1589, 1585), -64784: (1590, 1585), -64785: (1591, 1609), -64786: (1591, 1610), -64787: (1593, 1609), -64788: (1593, 1610), -64789: (1594, 1609), -64790: (1594, 1610), -64791: (1587, 1609), -64792: (1587, 1610), -64793: (1588, 1609), -64794: (1588, 1610), -64795: (1581, 1609), -64796: (1581, 1610), -64797: (1580, 1609), -64798: (1580, 1610), -64799: (1582, 1609), -64800: (1582, 1610), -64801: (1589, 1609), -64802: (1589, 1610), -64803: (1590, 1609), -64804: (1590, 1610), -64805: (1588, 1580), -64806: (1588, 1581), -64807: (1588, 1582), -64808: (1588, 1605), -64809: (1588, 1585), -64810: (1587, 1585), -64811: (1589, 1585), -64812: (1590, 1585), -64813: (1588, 1580), -64814: (1588, 1581), -64815: (1588, 1582), -64816: (1588, 1605), -64817: (1587, 1607), -64818: (1588, 1607), -64819: (1591, 1605), -64820: (1587, 1580), -64821: (1587, 1581), -64822: (1587, 1582), -64823: (1588, 1580), -64824: (1588, 1581), -64825: (1588, 1582), -64826: (1591, 1605), -64827: (1592, 1605), -64828: (1575, 1611), -64829: (1575, 1611), -64848: (1578, 1580, 1605), -64849: (1578, 1581, 1580), -64850: (1578, 1581, 1580), -64851: (1578, 1581, 1605), -64852: (1578, 1582, 1605), -64853: (1578, 1605, 1580), -64854: (1578, 1605, 1581), -64855: (1578, 1605, 1582), -64856: (1580, 1605, 1581), -64857: (1580, 1605, 1581), -64858: (1581, 1605, 1610), -64859: (1581, 1605, 1609), -64860: (1587, 1581, 1580), -64861: (1587, 1580, 1581), -64862: (1587, 1580, 1609), -64863: (1587, 1605, 1581), -64864: (1587, 1605, 1581), -64865: (1587, 1605, 1580), -64866: (1587, 1605, 1605), -64867: (1587, 1605, 1605), -64868: (1589, 1581, 1581), -64869: (1589, 1581, 1581), -64870: (1589, 1605, 1605), -64871: (1588, 1581, 1605), -64872: (1588, 1581, 1605), -64873: (1588, 1580, 1610), -64874: (1588, 1605, 1582), -64875: (1588, 1605, 1582), -64876: (1588, 1605, 1605), -64877: (1588, 1605, 1605), -64878: (1590, 1581, 1609), -64879: (1590, 1582, 1605), -64880: (1590, 1582, 1605), -64881: (1591, 1605, 1581), -64882: (1591, 1605, 1581), -64883: (1591, 1605, 1605), -64884: (1591, 1605, 1610), -64885: (1593, 1580, 1605), -64886: (1593, 1605, 1605), -64887: (1593, 1605, 1605), -64888: (1593, 1605, 1609), -64889: (1594, 1605, 1605), -64890: (1594, 1605, 1610), -64891: (1594, 1605, 1609), -64892: (1601, 1582, 1605), -64893: (1601, 1582, 1605), -64894: (1602, 1605, 1581), -64895: (1602, 1605, 1605), -64896: (1604, 1581, 1605), -64897: (1604, 1581, 1610), -64898: (1604, 1581, 1609), -64899: (1604, 1580, 1580), -64900: (1604, 1580, 1580), -64901: (1604, 1582, 1605), -64902: (1604, 1582, 1605), -64903: (1604, 1605, 1581), -64904: (1604, 1605, 1581), -64905: (1605, 1581, 1580), -64906: (1605, 1581, 1605), -64907: (1605, 1581, 1610), -64908: (1605, 1580, 1581), -64909: (1605, 1580, 1605), -64910: (1605, 1582, 1580), -64911: (1605, 1582, 1605), -64914: (1605, 1580, 1582), -64915: (1607, 1605, 1580), -64916: (1607, 1605, 1605), -64917: (1606, 1581, 1605), -64918: (1606, 1581, 1609), -64919: (1606, 1580, 1605), -64920: (1606, 1580, 1605), -64921: (1606, 1580, 1609), -64922: (1606, 1605, 1610), -64923: (1606, 1605, 1609), -64924: (1610, 1605, 1605), -64925: (1610, 1605, 1605), -64926: (1576, 1582, 1610), -64927: (1578, 1580, 1610), -64928: (1578, 1580, 1609), -64929: (1578, 1582, 1610), -64930: (1578, 1582, 1609), -64931: (1578, 1605, 1610), -64932: (1578, 1605, 1609), -64933: (1580, 1605, 1610), -64934: (1580, 1581, 1609), -64935: (1580, 1605, 1609), -64936: (1587, 1582, 1609), -64937: (1589, 1581, 1610), -64938: (1588, 1581, 1610), -64939: (1590, 1581, 1610), -64940: (1604, 1580, 1610), -64941: (1604, 1605, 1610), -64942: (1610, 1581, 1610), -64943: (1610, 1580, 1610), -64944: (1610, 1605, 1610), -64945: (1605, 1605, 1610), -64946: (1602, 1605, 1610), -64947: (1606, 1581, 1610), -64948: (1602, 1605, 1581), -64949: (1604, 1581, 1605), -64950: (1593, 1605, 1610), -64951: (1603, 1605, 1610), -64952: (1606, 1580, 1581), -64953: (1605, 1582, 1610), -64954: (1604, 1580, 1605), -64955: (1603, 1605, 1605), -64956: (1604, 1580, 1605), -64957: (1606, 1580, 1581), -64958: (1580, 1581, 1610), -64959: (1581, 1580, 1610), -64960: (1605, 1580, 1610), -64961: (1601, 1605, 1610), -64962: (1576, 1581, 1610), -64963: (1603, 1605, 1605), -64964: (1593, 1580, 1605), -64965: (1589, 1605, 1605), -64966: (1587, 1582, 1610), -64967: (1606, 1580, 1610), -65008: (1589, 1604, 1746), -65009: (1602, 1604, 1746), -65010: (1575, 1604, 1604, 1607), -65011: (1575, 1603, 1576, 1585), -65012: (1605, 1581, 1605, 1583), -65013: (1589, 1604, 1593, 1605), -65014: (1585, 1587, 1608, 1604), -65015: (1593, 1604, 1610, 1607), -65016: (1608, 1587, 1604, 1605), -65017: (1589, 1604, 1609), -65018: (1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605), -65019: (1580, 1604, 32, 1580, 1604, 1575, 1604, 1607), -65020: (1585, 1740, 1575, 1604), -65072: (46, 46), -65073: (8212,), -65074: (8211,), -65075: (95,), -65076: (95,), -65077: (40,), -65078: (41,), -65079: (123,), -65080: (125,), -65081: (12308,), -65082: (12309,), -65083: (12304,), -65084: (12305,), -65085: (12298,), -65086: (12299,), -65087: (12296,), -65088: (12297,), -65089: (12300,), -65090: (12301,), -65091: (12302,), -65092: (12303,), -65097: (32, 773), -65098: (32, 773), -65099: (32, 773), -65100: (32, 773), -65101: (95,), -65102: (95,), -65103: (95,), -65104: (44,), -65105: (12289,), -65106: (46,), -65108: (59,), -65109: (58,), -65110: (63,), -65111: (33,), -65112: (8212,), -65113: (40,), -65114: (41,), -65115: (123,), -65116: (125,), -65117: (12308,), -65118: (12309,), -65119: (35,), -65120: (38,), -65121: (42,), -65122: (43,), -65123: (45,), -65124: (60,), -65125: (62,), -65126: (61,), -65128: (92,), -65129: (36,), -65130: (37,), -65131: (64,), -65136: (32, 1611), -65137: (1600, 1611), -65138: (32, 1612), -65140: (32, 1613), -65142: (32, 1614), -65143: (1600, 1614), -65144: (32, 1615), -65145: (1600, 1615), -65146: (32, 1616), -65147: (1600, 1616), -65148: (32, 1617), -65149: (1600, 1617), -65150: (32, 1618), -65151: (1600, 1618), -65152: (1569,), -65153: (1575, 1619), -65154: (1575, 1619), -65155: (1575, 1620), -65156: (1575, 1620), -65157: (1608, 1620), -65158: (1608, 1620), -65159: (1575, 1621), -65160: (1575, 1621), -65161: (1610, 1620), -65162: (1610, 1620), -65163: (1610, 1620), -65164: (1610, 1620), -65165: (1575,), -65166: (1575,), -65167: (1576,), -65168: (1576,), -65169: (1576,), -65170: (1576,), -65171: (1577,), -65172: (1577,), -65173: (1578,), -65174: (1578,), -65175: (1578,), -65176: (1578,), -65177: (1579,), -65178: (1579,), -65179: (1579,), -65180: (1579,), -65181: (1580,), -65182: (1580,), -65183: (1580,), -65184: (1580,), -65185: (1581,), -65186: (1581,), -65187: (1581,), -65188: (1581,), -65189: (1582,), -65190: (1582,), -65191: (1582,), -65192: (1582,), -65193: (1583,), -65194: (1583,), -65195: (1584,), -65196: (1584,), -65197: (1585,), -65198: (1585,), -65199: (1586,), -65200: (1586,), -65201: (1587,), -65202: (1587,), -65203: (1587,), -65204: (1587,), -65205: (1588,), -65206: (1588,), -65207: (1588,), -65208: (1588,), -65209: (1589,), -65210: (1589,), -65211: (1589,), -65212: (1589,), -65213: (1590,), -65214: (1590,), -65215: (1590,), -65216: (1590,), -65217: (1591,), -65218: (1591,), -65219: (1591,), -65220: (1591,), -65221: (1592,), -65222: (1592,), -65223: (1592,), -65224: (1592,), -65225: (1593,), -65226: (1593,), -65227: (1593,), -65228: (1593,), -65229: (1594,), -65230: (1594,), -65231: (1594,), -65232: (1594,), -65233: (1601,), -65234: (1601,), -65235: (1601,), -65236: (1601,), -65237: (1602,), -65238: (1602,), -65239: (1602,), -65240: (1602,), -65241: (1603,), -65242: (1603,), -65243: (1603,), -65244: (1603,), -65245: (1604,), -65246: (1604,), -65247: (1604,), -65248: (1604,), -65249: (1605,), -65250: (1605,), -65251: (1605,), -65252: (1605,), -65253: (1606,), -65254: (1606,), -65255: (1606,), -65256: (1606,), -65257: (1607,), -65258: (1607,), -65259: (1607,), -65260: (1607,), -65261: (1608,), -65262: (1608,), -65263: (1609,), -65264: (1609,), -65265: (1610,), -65266: (1610,), -65267: (1610,), -65268: (1610,), -65269: (1604, 1575, 1619), -65270: (1604, 1575, 1619), -65271: (1604, 1575, 1620), -65272: (1604, 1575, 1620), -65273: (1604, 1575, 1621), -65274: (1604, 1575, 1621), -65275: (1604, 1575), -65276: (1604, 1575), -65281: (33,), -65282: (34,), -65283: (35,), -65284: (36,), -65285: (37,), -65286: (38,), -65287: (39,), -65288: (40,), -65289: (41,), -65290: (42,), -65291: (43,), -65292: (44,), -65293: (45,), -65294: (46,), -65295: (47,), -65296: (48,), -65297: (49,), -65298: (50,), -65299: (51,), -65300: (52,), -65301: (53,), -65302: (54,), -65303: (55,), -65304: (56,), -65305: (57,), -65306: (58,), -65307: (59,), -65308: (60,), -65309: (61,), -65310: (62,), -65311: (63,), -65312: (64,), -65313: (65,), -65314: (66,), -65315: (67,), -65316: (68,), -65317: (69,), -65318: (70,), -65319: (71,), -65320: (72,), -65321: (73,), -65322: (74,), -65323: (75,), -65324: (76,), -65325: (77,), -65326: (78,), -65327: (79,), -65328: (80,), -65329: (81,), -65330: (82,), -65331: (83,), -65332: (84,), -65333: (85,), -65334: (86,), -65335: (87,), -65336: (88,), -65337: (89,), -65338: (90,), -65339: (91,), -65340: (92,), -65341: (93,), -65342: (94,), -65343: (95,), -65344: (96,), -65345: (97,), -65346: (98,), -65347: (99,), -65348: (100,), -65349: (101,), -65350: (102,), -65351: (103,), -65352: (104,), -65353: (105,), -65354: (106,), -65355: (107,), -65356: (108,), -65357: (109,), -65358: (110,), -65359: (111,), -65360: (112,), -65361: (113,), -65362: (114,), -65363: (115,), -65364: (116,), -65365: (117,), -65366: (118,), -65367: (119,), -65368: (120,), -65369: (121,), -65370: (122,), -65371: (123,), -65372: (124,), -65373: (125,), -65374: (126,), -65375: (10629,), -65376: (10630,), -65377: (12290,), -65378: (12300,), -65379: (12301,), -65380: (12289,), -65381: (12539,), -65382: (12530,), -65383: (12449,), -65384: (12451,), -65385: (12453,), -65386: (12455,), -65387: (12457,), -65388: (12515,), -65389: (12517,), -65390: (12519,), -65391: (12483,), -65392: (12540,), -65393: (12450,), -65394: (12452,), -65395: (12454,), -65396: (12456,), -65397: (12458,), -65398: (12459,), -65399: (12461,), -65400: (12463,), -65401: (12465,), -65402: (12467,), -65403: (12469,), -65404: (12471,), -65405: (12473,), -65406: (12475,), -65407: (12477,), -65408: (12479,), -65409: (12481,), -65410: (12484,), -65411: (12486,), -65412: (12488,), -65413: (12490,), -65414: (12491,), -65415: (12492,), -65416: (12493,), -65417: (12494,), -65418: (12495,), -65419: (12498,), -65420: (12501,), -65421: (12504,), -65422: (12507,), -65423: (12510,), -65424: (12511,), -65425: (12512,), -65426: (12513,), -65427: (12514,), -65428: (12516,), -65429: (12518,), -65430: (12520,), -65431: (12521,), -65432: (12522,), -65433: (12523,), -65434: (12524,), -65435: (12525,), -65436: (12527,), -65437: (12531,), -65438: (12441,), -65439: (12442,), -65440: (4448,), -65441: (4352,), -65442: (4353,), -65443: (4522,), -65444: (4354,), -65445: (4524,), -65446: (4525,), -65447: (4355,), -65448: (4356,), -65449: (4357,), -65450: (4528,), -65451: (4529,), -65452: (4530,), -65453: (4531,), -65454: (4532,), -65455: (4533,), -65456: (4378,), -65457: (4358,), -65458: (4359,), -65459: (4360,), -65460: (4385,), -65461: (4361,), -65462: (4362,), -65463: (4363,), -65464: (4364,), -65465: (4365,), -65466: (4366,), -65467: (4367,), -65468: (4368,), -65469: (4369,), -65470: (4370,), -65474: (4449,), -65475: (4450,), -65476: (4451,), -65477: (4452,), -65478: (4453,), -65479: (4454,), -65482: (4455,), -65483: (4456,), -65484: (4457,), -65485: (4458,), -65486: (4459,), -65487: (4460,), -65490: (4461,), -65491: (4462,), -65492: (4463,), -65493: (4464,), -65494: (4465,), -65495: (4466,), -65498: (4467,), -65499: (4468,), -65500: (4469,), -65504: (162,), -65505: (163,), -65506: (172,), -65507: (32, 772), -65508: (166,), -65509: (165,), -65510: (8361,), -65512: (9474,), -65513: (8592,), -65514: (8593,), -65515: (8594,), -65516: (8595,), -65517: (9632,), -65518: (9675,), -119134: (119127, 119141), -119135: (119128, 119141), -119136: (119128, 119141, 119150), -119137: (119128, 119141, 119151), -119138: (119128, 119141, 119152), -119139: (119128, 119141, 119153), -119140: (119128, 119141, 119154), -119227: (119225, 119141), -119228: (119226, 119141), -119229: (119225, 119141, 119150), -119230: (119226, 119141, 119150), -119231: (119225, 119141, 119151), -119232: (119226, 119141, 119151), -119808: (65,), -119809: (66,), -119810: (67,), -119811: (68,), -119812: (69,), -119813: (70,), -119814: (71,), -119815: (72,), -119816: (73,), -119817: (74,), -119818: (75,), -119819: (76,), -119820: (77,), -119821: (78,), -119822: (79,), -119823: (80,), -119824: (81,), -119825: (82,), -119826: (83,), -119827: (84,), -119828: (85,), -119829: (86,), -119830: (87,), -119831: (88,), -119832: (89,), -119833: (90,), -119834: (97,), -119835: (98,), -119836: (99,), -119837: (100,), -119838: (101,), -119839: (102,), -119840: (103,), -119841: (104,), -119842: (105,), -119843: (106,), -119844: (107,), -119845: (108,), -119846: (109,), -119847: (110,), -119848: (111,), -119849: (112,), -119850: (113,), -119851: (114,), -119852: (115,), -119853: (116,), -119854: (117,), -119855: (118,), -119856: (119,), -119857: (120,), -119858: (121,), -119859: (122,), -119860: (65,), -119861: (66,), -119862: (67,), -119863: (68,), -119864: (69,), -119865: (70,), -119866: (71,), -119867: (72,), -119868: (73,), -119869: (74,), -119870: (75,), -119871: (76,), -119872: (77,), -119873: (78,), -119874: (79,), -119875: (80,), -119876: (81,), -119877: (82,), -119878: (83,), -119879: (84,), -119880: (85,), -119881: (86,), -119882: (87,), -119883: (88,), -119884: (89,), -119885: (90,), -119886: (97,), -119887: (98,), -119888: (99,), -119889: (100,), -119890: (101,), -119891: (102,), -119892: (103,), -119894: (105,), -119895: (106,), -119896: (107,), -119897: (108,), -119898: (109,), -119899: (110,), -119900: (111,), -119901: (112,), -119902: (113,), -119903: (114,), -119904: (115,), -119905: (116,), -119906: (117,), -119907: (118,), -119908: (119,), -119909: (120,), -119910: (121,), -119911: (122,), -119912: (65,), -119913: (66,), -119914: (67,), -119915: (68,), -119916: (69,), -119917: (70,), -119918: (71,), -119919: (72,), -119920: (73,), -119921: (74,), -119922: (75,), -119923: (76,), -119924: (77,), -119925: (78,), -119926: (79,), -119927: (80,), -119928: (81,), -119929: (82,), -119930: (83,), -119931: (84,), -119932: (85,), -119933: (86,), -119934: (87,), -119935: (88,), -119936: (89,), -119937: (90,), -119938: (97,), -119939: (98,), -119940: (99,), -119941: (100,), -119942: (101,), -119943: (102,), -119944: (103,), -119945: (104,), -119946: (105,), -119947: (106,), -119948: (107,), -119949: (108,), -119950: (109,), -119951: (110,), -119952: (111,), -119953: (112,), -119954: (113,), -119955: (114,), -119956: (115,), -119957: (116,), -119958: (117,), -119959: (118,), -119960: (119,), -119961: (120,), -119962: (121,), -119963: (122,), -119964: (65,), -119966: (67,), -119967: (68,), -119970: (71,), -119973: (74,), -119974: (75,), -119977: (78,), -119978: (79,), -119979: (80,), -119980: (81,), -119982: (83,), -119983: (84,), -119984: (85,), -119985: (86,), -119986: (87,), -119987: (88,), -119988: (89,), -119989: (90,), -119990: (97,), -119991: (98,), -119992: (99,), -119993: (100,), -119995: (102,), -119997: (104,), -119998: (105,), -119999: (106,), -120000: (107,), -120002: (109,), -120003: (110,), -120005: (112,), -120006: (113,), -120007: (114,), -120008: (115,), -120009: (116,), -120010: (117,), -120011: (118,), -120012: (119,), -120013: (120,), -120014: (121,), -120015: (122,), -120016: (65,), -120017: (66,), -120018: (67,), -120019: (68,), -120020: (69,), -120021: (70,), -120022: (71,), -120023: (72,), -120024: (73,), -120025: (74,), -120026: (75,), -120027: (76,), -120028: (77,), -120029: (78,), -120030: (79,), -120031: (80,), -120032: (81,), -120033: (82,), -120034: (83,), -120035: (84,), -120036: (85,), -120037: (86,), -120038: (87,), -120039: (88,), -120040: (89,), -120041: (90,), -120042: (97,), -120043: (98,), -120044: (99,), -120045: (100,), -120046: (101,), -120047: (102,), -120048: (103,), -120049: (104,), -120050: (105,), -120051: (106,), -120052: (107,), -120053: (108,), -120054: (109,), -120055: (110,), -120056: (111,), -120057: (112,), -120058: (113,), -120059: (114,), -120060: (115,), -120061: (116,), -120062: (117,), -120063: (118,), -120064: (119,), -120065: (120,), -120066: (121,), -120067: (122,), -120068: (65,), -120069: (66,), -120071: (68,), -120072: (69,), -120073: (70,), -120074: (71,), -120077: (74,), -120078: (75,), -120079: (76,), -120080: (77,), -120081: (78,), -120082: (79,), -120083: (80,), -120084: (81,), -120086: (83,), -120087: (84,), -120088: (85,), -120089: (86,), -120090: (87,), -120091: (88,), -120092: (89,), -120094: (97,), -120095: (98,), -120096: (99,), -120097: (100,), -120098: (101,), -120099: (102,), -120100: (103,), -120101: (104,), -120102: (105,), -120103: (106,), -120104: (107,), -120105: (108,), -120106: (109,), -120107: (110,), -120108: (111,), -120109: (112,), -120110: (113,), -120111: (114,), -120112: (115,), -120113: (116,), -120114: (117,), -120115: (118,), -120116: (119,), -120117: (120,), -120118: (121,), -120119: (122,), -120120: (65,), -120121: (66,), -120123: (68,), -120124: (69,), -120125: (70,), -120126: (71,), -120128: (73,), -120129: (74,), -120130: (75,), -120131: (76,), -120132: (77,), -120134: (79,), -120138: (83,), -120139: (84,), -120140: (85,), -120141: (86,), -120142: (87,), -120143: (88,), -120144: (89,), -120146: (97,), -120147: (98,), -120148: (99,), -120149: (100,), -120150: (101,), -120151: (102,), -120152: (103,), -120153: (104,), -120154: (105,), -120155: (106,), -120156: (107,), -120157: (108,), -120158: (109,), -120159: (110,), -120160: (111,), -120161: (112,), -120162: (113,), -120163: (114,), -120164: (115,), -120165: (116,), -120166: (117,), -120167: (118,), -120168: (119,), -120169: (120,), -120170: (121,), -120171: (122,), -120172: (65,), -120173: (66,), -120174: (67,), -120175: (68,), -120176: (69,), -120177: (70,), -120178: (71,), -120179: (72,), -120180: (73,), -120181: (74,), -120182: (75,), -120183: (76,), -120184: (77,), -120185: (78,), -120186: (79,), -120187: (80,), -120188: (81,), -120189: (82,), -120190: (83,), -120191: (84,), -120192: (85,), -120193: (86,), -120194: (87,), -120195: (88,), -120196: (89,), -120197: (90,), -120198: (97,), -120199: (98,), -120200: (99,), -120201: (100,), -120202: (101,), -120203: (102,), -120204: (103,), -120205: (104,), -120206: (105,), -120207: (106,), -120208: (107,), -120209: (108,), -120210: (109,), -120211: (110,), -120212: (111,), -120213: (112,), -120214: (113,), -120215: (114,), -120216: (115,), -120217: (116,), -120218: (117,), -120219: (118,), -120220: (119,), -120221: (120,), -120222: (121,), -120223: (122,), -120224: (65,), -120225: (66,), -120226: (67,), -120227: (68,), -120228: (69,), -120229: (70,), -120230: (71,), -120231: (72,), -120232: (73,), -120233: (74,), -120234: (75,), -120235: (76,), -120236: (77,), -120237: (78,), -120238: (79,), -120239: (80,), -120240: (81,), -120241: (82,), -120242: (83,), -120243: (84,), -120244: (85,), -120245: (86,), -120246: (87,), -120247: (88,), -120248: (89,), -120249: (90,), -120250: (97,), -120251: (98,), -120252: (99,), -120253: (100,), -120254: (101,), -120255: (102,), -120256: (103,), -120257: (104,), -120258: (105,), -120259: (106,), -120260: (107,), -120261: (108,), -120262: (109,), -120263: (110,), -120264: (111,), -120265: (112,), -120266: (113,), -120267: (114,), -120268: (115,), -120269: (116,), -120270: (117,), -120271: (118,), -120272: (119,), -120273: (120,), -120274: (121,), -120275: (122,), -120276: (65,), -120277: (66,), -120278: (67,), -120279: (68,), -120280: (69,), -120281: (70,), -120282: (71,), -120283: (72,), -120284: (73,), -120285: (74,), -120286: (75,), -120287: (76,), -120288: (77,), -120289: (78,), -120290: (79,), -120291: (80,), -120292: (81,), -120293: (82,), -120294: (83,), -120295: (84,), -120296: (85,), -120297: (86,), -120298: (87,), -120299: (88,), -120300: (89,), -120301: (90,), -120302: (97,), -120303: (98,), -120304: (99,), -120305: (100,), -120306: (101,), -120307: (102,), -120308: (103,), -120309: (104,), -120310: (105,), -120311: (106,), -120312: (107,), -120313: (108,), -120314: (109,), -120315: (110,), -120316: (111,), -120317: (112,), -120318: (113,), -120319: (114,), -120320: (115,), -120321: (116,), -120322: (117,), -120323: (118,), -120324: (119,), -120325: (120,), -120326: (121,), -120327: (122,), -120328: (65,), -120329: (66,), -120330: (67,), -120331: (68,), -120332: (69,), -120333: (70,), -120334: (71,), -120335: (72,), -120336: (73,), -120337: (74,), -120338: (75,), -120339: (76,), -120340: (77,), -120341: (78,), -120342: (79,), -120343: (80,), -120344: (81,), -120345: (82,), -120346: (83,), -120347: (84,), -120348: (85,), -120349: (86,), -120350: (87,), -120351: (88,), -120352: (89,), -120353: (90,), -120354: (97,), -120355: (98,), -120356: (99,), -120357: (100,), -120358: (101,), -120359: (102,), -120360: (103,), -120361: (104,), -120362: (105,), -120363: (106,), -120364: (107,), -120365: (108,), -120366: (109,), -120367: (110,), -120368: (111,), -120369: (112,), -120370: (113,), -120371: (114,), -120372: (115,), -120373: (116,), -120374: (117,), -120375: (118,), -120376: (119,), -120377: (120,), -120378: (121,), -120379: (122,), -120380: (65,), -120381: (66,), -120382: (67,), -120383: (68,), -120384: (69,), -120385: (70,), -120386: (71,), -120387: (72,), -120388: (73,), -120389: (74,), -120390: (75,), -120391: (76,), -120392: (77,), -120393: (78,), -120394: (79,), -120395: (80,), -120396: (81,), -120397: (82,), -120398: (83,), -120399: (84,), -120400: (85,), -120401: (86,), -120402: (87,), -120403: (88,), -120404: (89,), -120405: (90,), -120406: (97,), -120407: (98,), -120408: (99,), -120409: (100,), -120410: (101,), -120411: (102,), -120412: (103,), -120413: (104,), -120414: (105,), -120415: (106,), -120416: (107,), -120417: (108,), -120418: (109,), -120419: (110,), -120420: (111,), -120421: (112,), -120422: (113,), -120423: (114,), -120424: (115,), -120425: (116,), -120426: (117,), -120427: (118,), -120428: (119,), -120429: (120,), -120430: (121,), -120431: (122,), -120432: (65,), -120433: (66,), -120434: (67,), -120435: (68,), -120436: (69,), -120437: (70,), -120438: (71,), -120439: (72,), -120440: (73,), -120441: (74,), -120442: (75,), -120443: (76,), -120444: (77,), -120445: (78,), -120446: (79,), -120447: (80,), -120448: (81,), -120449: (82,), -120450: (83,), -120451: (84,), -120452: (85,), -120453: (86,), -120454: (87,), -120455: (88,), -120456: (89,), -120457: (90,), -120458: (97,), -120459: (98,), -120460: (99,), -120461: (100,), -120462: (101,), -120463: (102,), -120464: (103,), -120465: (104,), -120466: (105,), -120467: (106,), -120468: (107,), -120469: (108,), -120470: (109,), -120471: (110,), -120472: (111,), -120473: (112,), -120474: (113,), -120475: (114,), -120476: (115,), -120477: (116,), -120478: (117,), -120479: (118,), -120480: (119,), -120481: (120,), -120482: (121,), -120483: (122,), -120488: (913,), -120489: (914,), -120490: (915,), -120491: (916,), -120492: (917,), -120493: (918,), -120494: (919,), -120495: (920,), -120496: (921,), -120497: (922,), -120498: (923,), -120499: (924,), -120500: (925,), -120501: (926,), -120502: (927,), -120503: (928,), -120504: (929,), -120505: (920,), -120506: (931,), -120507: (932,), -120508: (933,), -120509: (934,), -120510: (935,), -120511: (936,), -120512: (937,), -120513: (8711,), -120514: (945,), -120515: (946,), -120516: (947,), -120517: (948,), -120518: (949,), -120519: (950,), -120520: (951,), -120521: (952,), -120522: (953,), -120523: (954,), -120524: (955,), -120525: (956,), -120526: (957,), -120527: (958,), -120528: (959,), -120529: (960,), -120530: (961,), -120531: (962,), -120532: (963,), -120533: (964,), -120534: (965,), -120535: (966,), -120536: (967,), -120537: (968,), -120538: (969,), -120539: (8706,), -120540: (949,), -120541: (952,), -120542: (954,), -120543: (966,), -120544: (961,), -120545: (960,), -120546: (913,), -120547: (914,), -120548: (915,), -120549: (916,), -120550: (917,), -120551: (918,), -120552: (919,), -120553: (920,), -120554: (921,), -120555: (922,), -120556: (923,), -120557: (924,), -120558: (925,), -120559: (926,), -120560: (927,), -120561: (928,), -120562: (929,), -120563: (920,), -120564: (931,), -120565: (932,), -120566: (933,), -120567: (934,), -120568: (935,), -120569: (936,), -120570: (937,), -120571: (8711,), -120572: (945,), -120573: (946,), -120574: (947,), -120575: (948,), -120576: (949,), -120577: (950,), -120578: (951,), -120579: (952,), -120580: (953,), -120581: (954,), -120582: (955,), -120583: (956,), -120584: (957,), -120585: (958,), -120586: (959,), -120587: (960,), -120588: (961,), -120589: (962,), -120590: (963,), -120591: (964,), -120592: (965,), -120593: (966,), -120594: (967,), -120595: (968,), -120596: (969,), -120597: (8706,), -120598: (949,), -120599: (952,), -120600: (954,), -120601: (966,), -120602: (961,), -120603: (960,), -120604: (913,), -120605: (914,), -120606: (915,), -120607: (916,), -120608: (917,), -120609: (918,), -120610: (919,), -120611: (920,), -120612: (921,), -120613: (922,), -120614: (923,), -120615: (924,), -120616: (925,), -120617: (926,), -120618: (927,), -120619: (928,), -120620: (929,), -120621: (920,), -120622: (931,), -120623: (932,), -120624: (933,), -120625: (934,), -120626: (935,), -120627: (936,), -120628: (937,), -120629: (8711,), -120630: (945,), -120631: (946,), -120632: (947,), -120633: (948,), -120634: (949,), -120635: (950,), -120636: (951,), -120637: (952,), -120638: (953,), -120639: (954,), -120640: (955,), -120641: (956,), -120642: (957,), -120643: (958,), -120644: (959,), -120645: (960,), -120646: (961,), -120647: (962,), -120648: (963,), -120649: (964,), -120650: (965,), -120651: (966,), -120652: (967,), -120653: (968,), -120654: (969,), -120655: (8706,), -120656: (949,), -120657: (952,), -120658: (954,), -120659: (966,), -120660: (961,), -120661: (960,), -120662: (913,), -120663: (914,), -120664: (915,), -120665: (916,), -120666: (917,), -120667: (918,), -120668: (919,), -120669: (920,), -120670: (921,), -120671: (922,), -120672: (923,), -120673: (924,), -120674: (925,), -120675: (926,), -120676: (927,), -120677: (928,), -120678: (929,), -120679: (920,), -120680: (931,), -120681: (932,), -120682: (933,), -120683: (934,), -120684: (935,), -120685: (936,), -120686: (937,), -120687: (8711,), -120688: (945,), -120689: (946,), -120690: (947,), -120691: (948,), -120692: (949,), -120693: (950,), -120694: (951,), -120695: (952,), -120696: (953,), -120697: (954,), -120698: (955,), -120699: (956,), -120700: (957,), -120701: (958,), -120702: (959,), -120703: (960,), -120704: (961,), -120705: (962,), -120706: (963,), -120707: (964,), -120708: (965,), -120709: (966,), -120710: (967,), -120711: (968,), -120712: (969,), -120713: (8706,), -120714: (949,), -120715: (952,), -120716: (954,), -120717: (966,), -120718: (961,), -120719: (960,), -120720: (913,), -120721: (914,), -120722: (915,), -120723: (916,), -120724: (917,), -120725: (918,), -120726: (919,), -120727: (920,), -120728: (921,), -120729: (922,), -120730: (923,), -120731: (924,), -120732: (925,), -120733: (926,), -120734: (927,), -120735: (928,), -120736: (929,), -120737: (920,), -120738: (931,), -120739: (932,), -120740: (933,), -120741: (934,), -120742: (935,), -120743: (936,), -120744: (937,), -120745: (8711,), -120746: (945,), -120747: (946,), -120748: (947,), -120749: (948,), -120750: (949,), -120751: (950,), -120752: (951,), -120753: (952,), -120754: (953,), -120755: (954,), -120756: (955,), -120757: (956,), -120758: (957,), -120759: (958,), -120760: (959,), -120761: (960,), -120762: (961,), -120763: (962,), -120764: (963,), -120765: (964,), -120766: (965,), -120767: (966,), -120768: (967,), -120769: (968,), -120770: (969,), -120771: (8706,), -120772: (949,), -120773: (952,), -120774: (954,), -120775: (966,), -120776: (961,), -120777: (960,), -120782: (48,), -120783: (49,), -120784: (50,), -120785: (51,), -120786: (52,), -120787: (53,), -120788: (54,), -120789: (55,), -120790: (56,), -120791: (57,), -120792: (48,), -120793: (49,), -120794: (50,), -120795: (51,), -120796: (52,), -120797: (53,), -120798: (54,), -120799: (55,), -120800: (56,), -120801: (57,), -120802: (48,), -120803: (49,), -120804: (50,), -120805: (51,), -120806: (52,), -120807: (53,), -120808: (54,), -120809: (55,), -120810: (56,), -120811: (57,), -120812: (48,), -120813: (49,), -120814: (50,), -120815: (51,), -120816: (52,), -120817: (53,), -120818: (54,), -120819: (55,), -120820: (56,), -120821: (57,), -120822: (48,), -120823: (49,), -120824: (50,), -120825: (51,), -120826: (52,), -120827: (53,), -120828: (54,), -120829: (55,), -120830: (56,), -120831: (57,), -194560: (20029,), -194561: (20024,), -194562: (20033,), -194563: (131362,), -194564: (20320,), -194565: (20398,), -194566: (20411,), -194567: (20482,), -194568: (20602,), -194569: (20633,), -194570: (20711,), -194571: (20687,), -194572: (13470,), -194573: (132666,), -194574: (20813,), -194575: (20820,), -194576: (20836,), -194577: (20855,), -194578: (132380,), -194579: (13497,), -194580: (20839,), -194581: (20877,), -194582: (132427,), -194583: (20887,), -194584: (20900,), -194585: (20172,), -194586: (20908,), -194587: (20917,), -194588: (168415,), -194589: (20981,), -194590: (20995,), -194591: (13535,), -194592: (21051,), -194593: (21062,), -194594: (21106,), -194595: (21111,), -194596: (13589,), -194597: (21191,), -194598: (21193,), -194599: (21220,), -194600: (21242,), -194601: (21253,), -194602: (21254,), -194603: (21271,), -194604: (21321,), -194605: (21329,), -194606: (21338,), -194607: (21363,), -194608: (21373,), -194609: (21375,), -194610: (21375,), -194611: (21375,), -194612: (133676,), -194613: (28784,), -194614: (21450,), -194615: (21471,), -194616: (133987,), -194617: (21483,), -194618: (21489,), -194619: (21510,), -194620: (21662,), -194621: (21560,), -194622: (21576,), -194623: (21608,), -194624: (21666,), -194625: (21750,), -194626: (21776,), -194627: (21843,), -194628: (21859,), -194629: (21892,), -194630: (21892,), -194631: (21913,), -194632: (21931,), -194633: (21939,), -194634: (21954,), -194635: (22294,), -194636: (22022,), -194637: (22295,), -194638: (22097,), -194639: (22132,), -194640: (20999,), -194641: (22766,), -194642: (22478,), -194643: (22516,), -194644: (22541,), -194645: (22411,), -194646: (22578,), -194647: (22577,), -194648: (22700,), -194649: (136420,), -194650: (22770,), -194651: (22775,), -194652: (22790,), -194653: (22810,), -194654: (22818,), -194655: (22882,), -194656: (136872,), -194657: (136938,), -194658: (23020,), -194659: (23067,), -194660: (23079,), -194661: (23000,), -194662: (23142,), -194663: (14062,), -194664: (136042,), -194665: (23304,), -194666: (23358,), -194667: (23358,), -194668: (137672,), -194669: (23491,), -194670: (23512,), -194671: (23527,), -194672: (23539,), -194673: (138008,), -194674: (23551,), -194675: (23558,), -194676: (24371,), -194677: (23586,), -194678: (14209,), -194679: (23648,), -194680: (23662,), -194681: (23744,), -194682: (23693,), -194683: (138724,), -194684: (23875,), -194685: (138726,), -194686: (23918,), -194687: (23915,), -194688: (23932,), -194689: (24033,), -194690: (24034,), -194691: (14383,), -194692: (24061,), -194693: (24104,), -194694: (24125,), -194695: (24169,), -194696: (14434,), -194697: (139651,), -194698: (14460,), -194699: (24240,), -194700: (24243,), -194701: (24246,), -194702: (24266,), -194703: (172946,), -194704: (24318,), -194705: (140081,), -194706: (140081,), -194707: (33281,), -194708: (24354,), -194709: (24354,), -194710: (14535,), -194711: (144056,), -194712: (156122,), -194713: (24418,), -194714: (24427,), -194715: (14563,), -194716: (24474,), -194717: (24525,), -194718: (24535,), -194719: (24569,), -194720: (24705,), -194721: (14650,), -194722: (14620,), -194723: (24724,), -194724: (141012,), -194725: (24775,), -194726: (24904,), -194727: (24908,), -194728: (24910,), -194729: (24908,), -194730: (24954,), -194731: (24974,), -194732: (25010,), -194733: (24996,), -194734: (25007,), -194735: (25054,), -194736: (25074,), -194737: (25078,), -194738: (25104,), -194739: (25115,), -194740: (25181,), -194741: (25265,), -194742: (25300,), -194743: (25424,), -194744: (142092,), -194745: (25405,), -194746: (25340,), -194747: (25448,), -194748: (25475,), -194749: (25572,), -194750: (142321,), -194751: (25634,), -194752: (25541,), -194753: (25513,), -194754: (14894,), -194755: (25705,), -194756: (25726,), -194757: (25757,), -194758: (25719,), -194759: (14956,), -194760: (25935,), -194761: (25964,), -194762: (143370,), -194763: (26083,), -194764: (26360,), -194765: (26185,), -194766: (15129,), -194767: (26257,), -194768: (15112,), -194769: (15076,), -194770: (20882,), -194771: (20885,), -194772: (26368,), -194773: (26268,), -194774: (32941,), -194775: (17369,), -194776: (26391,), -194777: (26395,), -194778: (26401,), -194779: (26462,), -194780: (26451,), -194781: (144323,), -194782: (15177,), -194783: (26618,), -194784: (26501,), -194785: (26706,), -194786: (26757,), -194787: (144493,), -194788: (26766,), -194789: (26655,), -194790: (26900,), -194791: (15261,), -194792: (26946,), -194793: (27043,), -194794: (27114,), -194795: (27304,), -194796: (145059,), -194797: (27355,), -194798: (15384,), -194799: (27425,), -194800: (145575,), -194801: (27476,), -194802: (15438,), -194803: (27506,), -194804: (27551,), -194805: (27578,), -194806: (27579,), -194807: (146061,), -194808: (138507,), -194809: (146170,), -194810: (27726,), -194811: (146620,), -194812: (27839,), -194813: (27853,), -194814: (27751,), -194815: (27926,), -194816: (27966,), -194817: (28023,), -194818: (27969,), -194819: (28009,), -194820: (28024,), -194821: (28037,), -194822: (146718,), -194823: (27956,), -194824: (28207,), -194825: (28270,), -194826: (15667,), -194827: (28363,), -194828: (28359,), -194829: (147153,), -194830: (28153,), -194831: (28526,), -194832: (147294,), -194833: (147342,), -194834: (28614,), -194835: (28729,), -194836: (28702,), -194837: (28699,), -194838: (15766,), -194839: (28746,), -194840: (28797,), -194841: (28791,), -194842: (28845,), -194843: (132389,), -194844: (28997,), -194845: (148067,), -194846: (29084,), -194847: (17323,), -194848: (29224,), -194849: (29237,), -194850: (29264,), -194851: (149000,), -194852: (29312,), -194853: (29333,), -194854: (149301,), -194855: (149524,), -194856: (29562,), -194857: (29579,), -194858: (16044,), -194859: (29605,), -194860: (16056,), -194861: (16056,), -194862: (29767,), -194863: (29788,), -194864: (29809,), -194865: (29829,), -194866: (29898,), -194867: (16155,), -194868: (29988,), -194869: (150582,), -194870: (30014,), -194871: (150674,), -194872: (30064,), -194873: (139679,), -194874: (30224,), -194875: (151457,), -194876: (151480,), -194877: (151620,), -194878: (16380,), -194879: (16392,), -194880: (30452,), -194881: (151795,), -194882: (151794,), -194883: (151833,), -194884: (151859,), -194885: (30494,), -194886: (30495,), -194887: (30495,), -194888: (30538,), -194889: (16441,), -194890: (30603,), -194891: (16454,), -194892: (16534,), -194893: (152605,), -194894: (30798,), -194895: (30860,), -194896: (30924,), -194897: (16611,), -194898: (153126,), -194899: (31062,), -194900: (153242,), -194901: (153285,), -194902: (31119,), -194903: (31211,), -194904: (16687,), -194905: (31296,), -194906: (31306,), -194907: (31311,), -194908: (153980,), -194909: (154279,), -194910: (154279,), -194911: (31406,), -194912: (16898,), -194913: (154539,), -194914: (31686,), -194915: (31689,), -194916: (16935,), -194917: (154752,), -194918: (31954,), -194919: (17056,), -194920: (31976,), -194921: (31971,), -194922: (32000,), -194923: (155526,), -194924: (32099,), -194925: (17153,), -194926: (32199,), -194927: (32258,), -194928: (32325,), -194929: (17204,), -194930: (156200,), -194931: (156231,), -194932: (17241,), -194933: (156377,), -194934: (32634,), -194935: (156478,), -194936: (32661,), -194937: (32762,), -194938: (32773,), -194939: (156890,), -194940: (156963,), -194941: (32864,), -194942: (157096,), -194943: (32880,), -194944: (144223,), -194945: (17365,), -194946: (32946,), -194947: (33027,), -194948: (17419,), -194949: (33086,), -194950: (23221,), -194951: (157607,), -194952: (157621,), -194953: (144275,), -194954: (144284,), -194955: (33281,), -194956: (33284,), -194957: (36766,), -194958: (17515,), -194959: (33425,), -194960: (33419,), -194961: (33437,), -194962: (21171,), -194963: (33457,), -194964: (33459,), -194965: (33469,), -194966: (33510,), -194967: (158524,), -194968: (33509,), -194969: (33565,), -194970: (33635,), -194971: (33709,), -194972: (33571,), -194973: (33725,), -194974: (33767,), -194975: (33879,), -194976: (33619,), -194977: (33738,), -194978: (33740,), -194979: (33756,), -194980: (158774,), -194981: (159083,), -194982: (158933,), -194983: (17707,), -194984: (34033,), -194985: (34035,), -194986: (34070,), -194987: (160714,), -194988: (34148,), -194989: (159532,), -194990: (17757,), -194991: (17761,), -194992: (159665,), -194993: (159954,), -194994: (17771,), -194995: (34384,), -194996: (34396,), -194997: (34407,), -194998: (34409,), -194999: (34473,), -195000: (34440,), -195001: (34574,), -195002: (34530,), -195003: (34681,), -195004: (34600,), -195005: (34667,), -195006: (34694,), -195007: (19799,), -195008: (34785,), -195009: (34817,), -195010: (17913,), -195011: (34912,), -195012: (34915,), -195013: (161383,), -195014: (35031,), -195015: (35038,), -195016: (17973,), -195017: (35066,), -195018: (13499,), -195019: (161966,), -195020: (162150,), -195021: (18110,), -195022: (18119,), -195023: (35488,), -195024: (35565,), -195025: (35722,), -195026: (35925,), -195027: (162984,), -195028: (36011,), -195029: (36033,), -195030: (36123,), -195031: (36215,), -195032: (163631,), -195033: (133124,), -195034: (36299,), -195035: (36284,), -195036: (36336,), -195037: (133342,), -195038: (36564,), -195039: (36664,), -195040: (165330,), -195041: (165357,), -195042: (37012,), -195043: (37105,), -195044: (37137,), -195045: (165678,), -195046: (37147,), -195047: (37432,), -195048: (37591,), -195049: (37592,), -195050: (37500,), -195051: (37881,), -195052: (37909,), -195053: (166906,), -195054: (38283,), -195055: (18837,), -195056: (38327,), -195057: (167287,), -195058: (18918,), -195059: (38595,), -195060: (23986,), -195061: (38691,), -195062: (168261,), -195063: (168474,), -195064: (19054,), -195065: (19062,), -195066: (38880,), -195067: (168970,), -195068: (19122,), -195069: (169110,), -195070: (38923,), -195071: (38923,), -195072: (38953,), -195073: (169398,), -195074: (39138,), -195075: (19251,), -195076: (39209,), -195077: (39335,), -195078: (39362,), -195079: (39422,), -195080: (19406,), -195081: (170800,), -195082: (39698,), -195083: (40000,), -195084: (40189,), -195085: (19662,), -195086: (19693,), -195087: (40295,), -195088: (172238,), -195089: (19704,), -195090: (172293,), -195091: (172558,), -195092: (172689,), -195093: (40635,), -195094: (19798,), -195095: (40697,), -195096: (40702,), -195097: (40709,), -195098: (40719,), -195099: (40726,), -195100: (40763,), -195101: (173568,), +160: [32], +168: [32, 776], +170: [97], +175: [32, 772], +178: [50], +179: [51], +180: [32, 769], +181: [956], +184: [32, 807], +185: [49], +186: [111], +188: [49, 8260, 52], +189: [49, 8260, 50], +190: [51, 8260, 52], +192: [65, 768], +193: [65, 769], +194: [65, 770], +195: [65, 771], +196: [65, 776], +197: [65, 778], +199: [67, 807], +200: [69, 768], +201: [69, 769], +202: [69, 770], +203: [69, 776], +204: [73, 768], +205: [73, 769], +206: [73, 770], +207: [73, 776], +209: [78, 771], +210: [79, 768], +211: [79, 769], +212: [79, 770], +213: [79, 771], +214: [79, 776], +217: [85, 768], +218: [85, 769], +219: [85, 770], +220: [85, 776], +221: [89, 769], +224: [97, 768], +225: [97, 769], +226: [97, 770], +227: [97, 771], +228: [97, 776], +229: [97, 778], +231: [99, 807], +232: [101, 768], +233: [101, 769], +234: [101, 770], +235: [101, 776], +236: [105, 768], +237: [105, 769], +238: [105, 770], +239: [105, 776], +241: [110, 771], +242: [111, 768], +243: [111, 769], +244: [111, 770], +245: [111, 771], +246: [111, 776], +249: [117, 768], +250: [117, 769], +251: [117, 770], +252: [117, 776], +253: [121, 769], +255: [121, 776], +256: [65, 772], +257: [97, 772], +258: [65, 774], +259: [97, 774], +260: [65, 808], +261: [97, 808], +262: [67, 769], +263: [99, 769], +264: [67, 770], +265: [99, 770], +266: [67, 775], +267: [99, 775], +268: [67, 780], +269: [99, 780], +270: [68, 780], +271: [100, 780], +274: [69, 772], +275: [101, 772], +276: [69, 774], +277: [101, 774], +278: [69, 775], +279: [101, 775], +280: [69, 808], +281: [101, 808], +282: [69, 780], +283: [101, 780], +284: [71, 770], +285: [103, 770], +286: [71, 774], +287: [103, 774], +288: [71, 775], +289: [103, 775], +290: [71, 807], +291: [103, 807], +292: [72, 770], +293: [104, 770], +296: [73, 771], +297: [105, 771], +298: [73, 772], +299: [105, 772], +300: [73, 774], +301: [105, 774], +302: [73, 808], +303: [105, 808], +304: [73, 775], +306: [73, 74], +307: [105, 106], +308: [74, 770], +309: [106, 770], +310: [75, 807], +311: [107, 807], +313: [76, 769], +314: [108, 769], +315: [76, 807], +316: [108, 807], +317: [76, 780], +318: [108, 780], +319: [76, 183], +320: [108, 183], +323: [78, 769], +324: [110, 769], +325: [78, 807], +326: [110, 807], +327: [78, 780], +328: [110, 780], +329: [700, 110], +332: [79, 772], +333: [111, 772], +334: [79, 774], +335: [111, 774], +336: [79, 779], +337: [111, 779], +340: [82, 769], +341: [114, 769], +342: [82, 807], +343: [114, 807], +344: [82, 780], +345: [114, 780], +346: [83, 769], +347: [115, 769], +348: [83, 770], +349: [115, 770], +350: [83, 807], +351: [115, 807], +352: [83, 780], +353: [115, 780], +354: [84, 807], +355: [116, 807], +356: [84, 780], +357: [116, 780], +360: [85, 771], +361: [117, 771], +362: [85, 772], +363: [117, 772], +364: [85, 774], +365: [117, 774], +366: [85, 778], +367: [117, 778], +368: [85, 779], +369: [117, 779], +370: [85, 808], +371: [117, 808], +372: [87, 770], +373: [119, 770], +374: [89, 770], +375: [121, 770], +376: [89, 776], +377: [90, 769], +378: [122, 769], +379: [90, 775], +380: [122, 775], +381: [90, 780], +382: [122, 780], +383: [115], +416: [79, 795], +417: [111, 795], +431: [85, 795], +432: [117, 795], +452: [68, 90, 780], +453: [68, 122, 780], +454: [100, 122, 780], +455: [76, 74], +456: [76, 106], +457: [108, 106], +458: [78, 74], +459: [78, 106], +460: [110, 106], +461: [65, 780], +462: [97, 780], +463: [73, 780], +464: [105, 780], +465: [79, 780], +466: [111, 780], +467: [85, 780], +468: [117, 780], +469: [85, 776, 772], +470: [117, 776, 772], +471: [85, 776, 769], +472: [117, 776, 769], +473: [85, 776, 780], +474: [117, 776, 780], +475: [85, 776, 768], +476: [117, 776, 768], +478: [65, 776, 772], +479: [97, 776, 772], +480: [65, 775, 772], +481: [97, 775, 772], +482: [198, 772], +483: [230, 772], +486: [71, 780], +487: [103, 780], +488: [75, 780], +489: [107, 780], +490: [79, 808], +491: [111, 808], +492: [79, 808, 772], +493: [111, 808, 772], +494: [439, 780], +495: [658, 780], +496: [106, 780], +497: [68, 90], +498: [68, 122], +499: [100, 122], +500: [71, 769], +501: [103, 769], +504: [78, 768], +505: [110, 768], +506: [65, 778, 769], +507: [97, 778, 769], +508: [198, 769], +509: [230, 769], +510: [216, 769], +511: [248, 769], +512: [65, 783], +513: [97, 783], +514: [65, 785], +515: [97, 785], +516: [69, 783], +517: [101, 783], +518: [69, 785], +519: [101, 785], +520: [73, 783], +521: [105, 783], +522: [73, 785], +523: [105, 785], +524: [79, 783], +525: [111, 783], +526: [79, 785], +527: [111, 785], +528: [82, 783], +529: [114, 783], +530: [82, 785], +531: [114, 785], +532: [85, 783], +533: [117, 783], +534: [85, 785], +535: [117, 785], +536: [83, 806], +537: [115, 806], +538: [84, 806], +539: [116, 806], +542: [72, 780], +543: [104, 780], +550: [65, 775], +551: [97, 775], +552: [69, 807], +553: [101, 807], +554: [79, 776, 772], +555: [111, 776, 772], +556: [79, 771, 772], +557: [111, 771, 772], +558: [79, 775], +559: [111, 775], +560: [79, 775, 772], +561: [111, 775, 772], +562: [89, 772], +563: [121, 772], +688: [104], +689: [614], +690: [106], +691: [114], +692: [633], +693: [635], +694: [641], +695: [119], +696: [121], +728: [32, 774], +729: [32, 775], +730: [32, 778], +731: [32, 808], +732: [32, 771], +733: [32, 779], +736: [611], +737: [108], +738: [115], +739: [120], +740: [661], +832: [768], +833: [769], +835: [787], +836: [776, 769], +884: [697], +890: [32, 837], +894: [59], +900: [32, 769], +901: [32, 776, 769], +902: [913, 769], +903: [183], +904: [917, 769], +905: [919, 769], +906: [921, 769], +908: [927, 769], +910: [933, 769], +911: [937, 769], +912: [953, 776, 769], +938: [921, 776], +939: [933, 776], +940: [945, 769], +941: [949, 769], +942: [951, 769], +943: [953, 769], +944: [965, 776, 769], +970: [953, 776], +971: [965, 776], +972: [959, 769], +973: [965, 769], +974: [969, 769], +976: [946], +977: [952], +978: [933], +979: [933, 769], +980: [933, 776], +981: [966], +982: [960], +1008: [954], +1009: [961], +1010: [962], +1012: [920], +1013: [949], +1024: [1045, 768], +1025: [1045, 776], +1027: [1043, 769], +1031: [1030, 776], +1036: [1050, 769], +1037: [1048, 768], +1038: [1059, 774], +1049: [1048, 774], +1081: [1080, 774], +1104: [1077, 768], +1105: [1077, 776], +1107: [1075, 769], +1111: [1110, 776], +1116: [1082, 769], +1117: [1080, 768], +1118: [1091, 774], +1142: [1140, 783], +1143: [1141, 783], +1217: [1046, 774], +1218: [1078, 774], +1232: [1040, 774], +1233: [1072, 774], +1234: [1040, 776], +1235: [1072, 776], +1238: [1045, 774], +1239: [1077, 774], +1242: [1240, 776], +1243: [1241, 776], +1244: [1046, 776], +1245: [1078, 776], +1246: [1047, 776], +1247: [1079, 776], +1250: [1048, 772], +1251: [1080, 772], +1252: [1048, 776], +1253: [1080, 776], +1254: [1054, 776], +1255: [1086, 776], +1258: [1256, 776], +1259: [1257, 776], +1260: [1069, 776], +1261: [1101, 776], +1262: [1059, 772], +1263: [1091, 772], +1264: [1059, 776], +1265: [1091, 776], +1266: [1059, 779], +1267: [1091, 779], +1268: [1063, 776], +1269: [1095, 776], +1272: [1067, 776], +1273: [1099, 776], +1415: [1381, 1410], +1570: [1575, 1619], +1571: [1575, 1620], +1572: [1608, 1620], +1573: [1575, 1621], +1574: [1610, 1620], +1653: [1575, 1652], +1654: [1608, 1652], +1655: [1735, 1652], +1656: [1610, 1652], +1728: [1749, 1620], +1730: [1729, 1620], +1747: [1746, 1620], +2345: [2344, 2364], +2353: [2352, 2364], +2356: [2355, 2364], +2392: [2325, 2364], +2393: [2326, 2364], +2394: [2327, 2364], +2395: [2332, 2364], +2396: [2337, 2364], +2397: [2338, 2364], +2398: [2347, 2364], +2399: [2351, 2364], +2507: [2503, 2494], +2508: [2503, 2519], +2524: [2465, 2492], +2525: [2466, 2492], +2527: [2479, 2492], +2611: [2610, 2620], +2614: [2616, 2620], +2649: [2582, 2620], +2650: [2583, 2620], +2651: [2588, 2620], +2654: [2603, 2620], +2888: [2887, 2902], +2891: [2887, 2878], +2892: [2887, 2903], +2908: [2849, 2876], +2909: [2850, 2876], +2964: [2962, 3031], +3018: [3014, 3006], +3019: [3015, 3006], +3020: [3014, 3031], +3144: [3142, 3158], +3264: [3263, 3285], +3271: [3270, 3285], +3272: [3270, 3286], +3274: [3270, 3266], +3275: [3270, 3266, 3285], +3402: [3398, 3390], +3403: [3399, 3390], +3404: [3398, 3415], +3546: [3545, 3530], +3548: [3545, 3535], +3549: [3545, 3535, 3530], +3550: [3545, 3551], +3635: [3661, 3634], +3763: [3789, 3762], +3804: [3755, 3737], +3805: [3755, 3745], +3852: [3851], +3907: [3906, 4023], +3917: [3916, 4023], +3922: [3921, 4023], +3927: [3926, 4023], +3932: [3931, 4023], +3945: [3904, 4021], +3955: [3953, 3954], +3957: [3953, 3956], +3958: [4018, 3968], +3959: [4018, 3953, 3968], +3960: [4019, 3968], +3961: [4019, 3953, 3968], +3969: [3953, 3968], +3987: [3986, 4023], +3997: [3996, 4023], +4002: [4001, 4023], +4007: [4006, 4023], +4012: [4011, 4023], +4025: [3984, 4021], +4134: [4133, 4142], +7680: [65, 805], +7681: [97, 805], +7682: [66, 775], +7683: [98, 775], +7684: [66, 803], +7685: [98, 803], +7686: [66, 817], +7687: [98, 817], +7688: [67, 807, 769], +7689: [99, 807, 769], +7690: [68, 775], +7691: [100, 775], +7692: [68, 803], +7693: [100, 803], +7694: [68, 817], +7695: [100, 817], +7696: [68, 807], +7697: [100, 807], +7698: [68, 813], +7699: [100, 813], +7700: [69, 772, 768], +7701: [101, 772, 768], +7702: [69, 772, 769], +7703: [101, 772, 769], +7704: [69, 813], +7705: [101, 813], +7706: [69, 816], +7707: [101, 816], +7708: [69, 807, 774], +7709: [101, 807, 774], +7710: [70, 775], +7711: [102, 775], +7712: [71, 772], +7713: [103, 772], +7714: [72, 775], +7715: [104, 775], +7716: [72, 803], +7717: [104, 803], +7718: [72, 776], +7719: [104, 776], +7720: [72, 807], +7721: [104, 807], +7722: [72, 814], +7723: [104, 814], +7724: [73, 816], +7725: [105, 816], +7726: [73, 776, 769], +7727: [105, 776, 769], +7728: [75, 769], +7729: [107, 769], +7730: [75, 803], +7731: [107, 803], +7732: [75, 817], +7733: [107, 817], +7734: [76, 803], +7735: [108, 803], +7736: [76, 803, 772], +7737: [108, 803, 772], +7738: [76, 817], +7739: [108, 817], +7740: [76, 813], +7741: [108, 813], +7742: [77, 769], +7743: [109, 769], +7744: [77, 775], +7745: [109, 775], +7746: [77, 803], +7747: [109, 803], +7748: [78, 775], +7749: [110, 775], +7750: [78, 803], +7751: [110, 803], +7752: [78, 817], +7753: [110, 817], +7754: [78, 813], +7755: [110, 813], +7756: [79, 771, 769], +7757: [111, 771, 769], +7758: [79, 771, 776], +7759: [111, 771, 776], +7760: [79, 772, 768], +7761: [111, 772, 768], +7762: [79, 772, 769], +7763: [111, 772, 769], +7764: [80, 769], +7765: [112, 769], +7766: [80, 775], +7767: [112, 775], +7768: [82, 775], +7769: [114, 775], +7770: [82, 803], +7771: [114, 803], +7772: [82, 803, 772], +7773: [114, 803, 772], +7774: [82, 817], +7775: [114, 817], +7776: [83, 775], +7777: [115, 775], +7778: [83, 803], +7779: [115, 803], +7780: [83, 769, 775], +7781: [115, 769, 775], +7782: [83, 780, 775], +7783: [115, 780, 775], +7784: [83, 803, 775], +7785: [115, 803, 775], +7786: [84, 775], +7787: [116, 775], +7788: [84, 803], +7789: [116, 803], +7790: [84, 817], +7791: [116, 817], +7792: [84, 813], +7793: [116, 813], +7794: [85, 804], +7795: [117, 804], +7796: [85, 816], +7797: [117, 816], +7798: [85, 813], +7799: [117, 813], +7800: [85, 771, 769], +7801: [117, 771, 769], +7802: [85, 772, 776], +7803: [117, 772, 776], +7804: [86, 771], +7805: [118, 771], +7806: [86, 803], +7807: [118, 803], +7808: [87, 768], +7809: [119, 768], +7810: [87, 769], +7811: [119, 769], +7812: [87, 776], +7813: [119, 776], +7814: [87, 775], +7815: [119, 775], +7816: [87, 803], +7817: [119, 803], +7818: [88, 775], +7819: [120, 775], +7820: [88, 776], +7821: [120, 776], +7822: [89, 775], +7823: [121, 775], +7824: [90, 770], +7825: [122, 770], +7826: [90, 803], +7827: [122, 803], +7828: [90, 817], +7829: [122, 817], +7830: [104, 817], +7831: [116, 776], +7832: [119, 778], +7833: [121, 778], +7834: [97, 702], +7835: [115, 775], +7840: [65, 803], +7841: [97, 803], +7842: [65, 777], +7843: [97, 777], +7844: [65, 770, 769], +7845: [97, 770, 769], +7846: [65, 770, 768], +7847: [97, 770, 768], +7848: [65, 770, 777], +7849: [97, 770, 777], +7850: [65, 770, 771], +7851: [97, 770, 771], +7852: [65, 803, 770], +7853: [97, 803, 770], +7854: [65, 774, 769], +7855: [97, 774, 769], +7856: [65, 774, 768], +7857: [97, 774, 768], +7858: [65, 774, 777], +7859: [97, 774, 777], +7860: [65, 774, 771], +7861: [97, 774, 771], +7862: [65, 803, 774], +7863: [97, 803, 774], +7864: [69, 803], +7865: [101, 803], +7866: [69, 777], +7867: [101, 777], +7868: [69, 771], +7869: [101, 771], +7870: [69, 770, 769], +7871: [101, 770, 769], +7872: [69, 770, 768], +7873: [101, 770, 768], +7874: [69, 770, 777], +7875: [101, 770, 777], +7876: [69, 770, 771], +7877: [101, 770, 771], +7878: [69, 803, 770], +7879: [101, 803, 770], +7880: [73, 777], +7881: [105, 777], +7882: [73, 803], +7883: [105, 803], +7884: [79, 803], +7885: [111, 803], +7886: [79, 777], +7887: [111, 777], +7888: [79, 770, 769], +7889: [111, 770, 769], +7890: [79, 770, 768], +7891: [111, 770, 768], +7892: [79, 770, 777], +7893: [111, 770, 777], +7894: [79, 770, 771], +7895: [111, 770, 771], +7896: [79, 803, 770], +7897: [111, 803, 770], +7898: [79, 795, 769], +7899: [111, 795, 769], +7900: [79, 795, 768], +7901: [111, 795, 768], +7902: [79, 795, 777], +7903: [111, 795, 777], +7904: [79, 795, 771], +7905: [111, 795, 771], +7906: [79, 795, 803], +7907: [111, 795, 803], +7908: [85, 803], +7909: [117, 803], +7910: [85, 777], +7911: [117, 777], +7912: [85, 795, 769], +7913: [117, 795, 769], +7914: [85, 795, 768], +7915: [117, 795, 768], +7916: [85, 795, 777], +7917: [117, 795, 777], +7918: [85, 795, 771], +7919: [117, 795, 771], +7920: [85, 795, 803], +7921: [117, 795, 803], +7922: [89, 768], +7923: [121, 768], +7924: [89, 803], +7925: [121, 803], +7926: [89, 777], +7927: [121, 777], +7928: [89, 771], +7929: [121, 771], +7936: [945, 787], +7937: [945, 788], +7938: [945, 787, 768], +7939: [945, 788, 768], +7940: [945, 787, 769], +7941: [945, 788, 769], +7942: [945, 787, 834], +7943: [945, 788, 834], +7944: [913, 787], +7945: [913, 788], +7946: [913, 787, 768], +7947: [913, 788, 768], +7948: [913, 787, 769], +7949: [913, 788, 769], +7950: [913, 787, 834], +7951: [913, 788, 834], +7952: [949, 787], +7953: [949, 788], +7954: [949, 787, 768], +7955: [949, 788, 768], +7956: [949, 787, 769], +7957: [949, 788, 769], +7960: [917, 787], +7961: [917, 788], +7962: [917, 787, 768], +7963: [917, 788, 768], +7964: [917, 787, 769], +7965: [917, 788, 769], +7968: [951, 787], +7969: [951, 788], +7970: [951, 787, 768], +7971: [951, 788, 768], +7972: [951, 787, 769], +7973: [951, 788, 769], +7974: [951, 787, 834], +7975: [951, 788, 834], +7976: [919, 787], +7977: [919, 788], +7978: [919, 787, 768], +7979: [919, 788, 768], +7980: [919, 787, 769], +7981: [919, 788, 769], +7982: [919, 787, 834], +7983: [919, 788, 834], +7984: [953, 787], +7985: [953, 788], +7986: [953, 787, 768], +7987: [953, 788, 768], +7988: [953, 787, 769], +7989: [953, 788, 769], +7990: [953, 787, 834], +7991: [953, 788, 834], +7992: [921, 787], +7993: [921, 788], +7994: [921, 787, 768], +7995: [921, 788, 768], +7996: [921, 787, 769], +7997: [921, 788, 769], +7998: [921, 787, 834], +7999: [921, 788, 834], +8000: [959, 787], +8001: [959, 788], +8002: [959, 787, 768], +8003: [959, 788, 768], +8004: [959, 787, 769], +8005: [959, 788, 769], +8008: [927, 787], +8009: [927, 788], +8010: [927, 787, 768], +8011: [927, 788, 768], +8012: [927, 787, 769], +8013: [927, 788, 769], +8016: [965, 787], +8017: [965, 788], +8018: [965, 787, 768], +8019: [965, 788, 768], +8020: [965, 787, 769], +8021: [965, 788, 769], +8022: [965, 787, 834], +8023: [965, 788, 834], +8025: [933, 788], +8027: [933, 788, 768], +8029: [933, 788, 769], +8031: [933, 788, 834], +8032: [969, 787], +8033: [969, 788], +8034: [969, 787, 768], +8035: [969, 788, 768], +8036: [969, 787, 769], +8037: [969, 788, 769], +8038: [969, 787, 834], +8039: [969, 788, 834], +8040: [937, 787], +8041: [937, 788], +8042: [937, 787, 768], +8043: [937, 788, 768], +8044: [937, 787, 769], +8045: [937, 788, 769], +8046: [937, 787, 834], +8047: [937, 788, 834], +8048: [945, 768], +8049: [945, 769], +8050: [949, 768], +8051: [949, 769], +8052: [951, 768], +8053: [951, 769], +8054: [953, 768], +8055: [953, 769], +8056: [959, 768], +8057: [959, 769], +8058: [965, 768], +8059: [965, 769], +8060: [969, 768], +8061: [969, 769], +8064: [945, 787, 837], +8065: [945, 788, 837], +8066: [945, 787, 768, 837], +8067: [945, 788, 768, 837], +8068: [945, 787, 769, 837], +8069: [945, 788, 769, 837], +8070: [945, 787, 834, 837], +8071: [945, 788, 834, 837], +8072: [913, 787, 837], +8073: [913, 788, 837], +8074: [913, 787, 768, 837], +8075: [913, 788, 768, 837], +8076: [913, 787, 769, 837], +8077: [913, 788, 769, 837], +8078: [913, 787, 834, 837], +8079: [913, 788, 834, 837], +8080: [951, 787, 837], +8081: [951, 788, 837], +8082: [951, 787, 768, 837], +8083: [951, 788, 768, 837], +8084: [951, 787, 769, 837], +8085: [951, 788, 769, 837], +8086: [951, 787, 834, 837], +8087: [951, 788, 834, 837], +8088: [919, 787, 837], +8089: [919, 788, 837], +8090: [919, 787, 768, 837], +8091: [919, 788, 768, 837], +8092: [919, 787, 769, 837], +8093: [919, 788, 769, 837], +8094: [919, 787, 834, 837], +8095: [919, 788, 834, 837], +8096: [969, 787, 837], +8097: [969, 788, 837], +8098: [969, 787, 768, 837], +8099: [969, 788, 768, 837], +8100: [969, 787, 769, 837], +8101: [969, 788, 769, 837], +8102: [969, 787, 834, 837], +8103: [969, 788, 834, 837], +8104: [937, 787, 837], +8105: [937, 788, 837], +8106: [937, 787, 768, 837], +8107: [937, 788, 768, 837], +8108: [937, 787, 769, 837], +8109: [937, 788, 769, 837], +8110: [937, 787, 834, 837], +8111: [937, 788, 834, 837], +8112: [945, 774], +8113: [945, 772], +8114: [945, 768, 837], +8115: [945, 837], +8116: [945, 769, 837], +8118: [945, 834], +8119: [945, 834, 837], +8120: [913, 774], +8121: [913, 772], +8122: [913, 768], +8123: [913, 769], +8124: [913, 837], +8125: [32, 787], +8126: [953], +8127: [32, 787], +8128: [32, 834], +8129: [32, 776, 834], +8130: [951, 768, 837], +8131: [951, 837], +8132: [951, 769, 837], +8134: [951, 834], +8135: [951, 834, 837], +8136: [917, 768], +8137: [917, 769], +8138: [919, 768], +8139: [919, 769], +8140: [919, 837], +8141: [32, 787, 768], +8142: [32, 787, 769], +8143: [32, 787, 834], +8144: [953, 774], +8145: [953, 772], +8146: [953, 776, 768], +8147: [953, 776, 769], +8150: [953, 834], +8151: [953, 776, 834], +8152: [921, 774], +8153: [921, 772], +8154: [921, 768], +8155: [921, 769], +8157: [32, 788, 768], +8158: [32, 788, 769], +8159: [32, 788, 834], +8160: [965, 774], +8161: [965, 772], +8162: [965, 776, 768], +8163: [965, 776, 769], +8164: [961, 787], +8165: [961, 788], +8166: [965, 834], +8167: [965, 776, 834], +8168: [933, 774], +8169: [933, 772], +8170: [933, 768], +8171: [933, 769], +8172: [929, 788], +8173: [32, 776, 768], +8174: [32, 776, 769], +8175: [96], +8178: [969, 768, 837], +8179: [969, 837], +8180: [969, 769, 837], +8182: [969, 834], +8183: [969, 834, 837], +8184: [927, 768], +8185: [927, 769], +8186: [937, 768], +8187: [937, 769], +8188: [937, 837], +8189: [32, 769], +8190: [32, 788], +8192: [32], +8193: [32], +8194: [32], +8195: [32], +8196: [32], +8197: [32], +8198: [32], +8199: [32], +8200: [32], +8201: [32], +8202: [32], +8209: [8208], +8215: [32, 819], +8228: [46], +8229: [46, 46], +8230: [46, 46, 46], +8239: [32], +8243: [8242, 8242], +8244: [8242, 8242, 8242], +8246: [8245, 8245], +8247: [8245, 8245, 8245], +8252: [33, 33], +8254: [32, 773], +8263: [63, 63], +8264: [63, 33], +8265: [33, 63], +8279: [8242, 8242, 8242, 8242], +8287: [32], +8304: [48], +8305: [105], +8308: [52], +8309: [53], +8310: [54], +8311: [55], +8312: [56], +8313: [57], +8314: [43], +8315: [8722], +8316: [61], +8317: [40], +8318: [41], +8319: [110], +8320: [48], +8321: [49], +8322: [50], +8323: [51], +8324: [52], +8325: [53], +8326: [54], +8327: [55], +8328: [56], +8329: [57], +8330: [43], +8331: [8722], +8332: [61], +8333: [40], +8334: [41], +8360: [82, 115], +8448: [97, 47, 99], +8449: [97, 47, 115], +8450: [67], +8451: [176, 67], +8453: [99, 47, 111], +8454: [99, 47, 117], +8455: [400], +8457: [176, 70], +8458: [103], +8459: [72], +8460: [72], +8461: [72], +8462: [104], +8463: [295], +8464: [73], +8465: [73], +8466: [76], +8467: [108], +8469: [78], +8470: [78, 111], +8473: [80], +8474: [81], +8475: [82], +8476: [82], +8477: [82], +8480: [83, 77], +8481: [84, 69, 76], +8482: [84, 77], +8484: [90], +8486: [937], +8488: [90], +8490: [75], +8491: [65, 778], +8492: [66], +8493: [67], +8495: [101], +8496: [69], +8497: [70], +8499: [77], +8500: [111], +8501: [1488], +8502: [1489], +8503: [1490], +8504: [1491], +8505: [105], +8509: [947], +8510: [915], +8511: [928], +8512: [8721], +8517: [68], +8518: [100], +8519: [101], +8520: [105], +8521: [106], +8531: [49, 8260, 51], +8532: [50, 8260, 51], +8533: [49, 8260, 53], +8534: [50, 8260, 53], +8535: [51, 8260, 53], +8536: [52, 8260, 53], +8537: [49, 8260, 54], +8538: [53, 8260, 54], +8539: [49, 8260, 56], +8540: [51, 8260, 56], +8541: [53, 8260, 56], +8542: [55, 8260, 56], +8543: [49, 8260], +8544: [73], +8545: [73, 73], +8546: [73, 73, 73], +8547: [73, 86], +8548: [86], +8549: [86, 73], +8550: [86, 73, 73], +8551: [86, 73, 73, 73], +8552: [73, 88], +8553: [88], +8554: [88, 73], +8555: [88, 73, 73], +8556: [76], +8557: [67], +8558: [68], +8559: [77], +8560: [105], +8561: [105, 105], +8562: [105, 105, 105], +8563: [105, 118], +8564: [118], +8565: [118, 105], +8566: [118, 105, 105], +8567: [118, 105, 105, 105], +8568: [105, 120], +8569: [120], +8570: [120, 105], +8571: [120, 105, 105], +8572: [108], +8573: [99], +8574: [100], +8575: [109], +8602: [8592, 824], +8603: [8594, 824], +8622: [8596, 824], +8653: [8656, 824], +8654: [8660, 824], +8655: [8658, 824], +8708: [8707, 824], +8713: [8712, 824], +8716: [8715, 824], +8740: [8739, 824], +8742: [8741, 824], +8748: [8747, 8747], +8749: [8747, 8747, 8747], +8751: [8750, 8750], +8752: [8750, 8750, 8750], +8769: [8764, 824], +8772: [8771, 824], +8775: [8773, 824], +8777: [8776, 824], +8800: [61, 824], +8802: [8801, 824], +8813: [8781, 824], +8814: [60, 824], +8815: [62, 824], +8816: [8804, 824], +8817: [8805, 824], +8820: [8818, 824], +8821: [8819, 824], +8824: [8822, 824], +8825: [8823, 824], +8832: [8826, 824], +8833: [8827, 824], +8836: [8834, 824], +8837: [8835, 824], +8840: [8838, 824], +8841: [8839, 824], +8876: [8866, 824], +8877: [8872, 824], +8878: [8873, 824], +8879: [8875, 824], +8928: [8828, 824], +8929: [8829, 824], +8930: [8849, 824], +8931: [8850, 824], +8938: [8882, 824], +8939: [8883, 824], +8940: [8884, 824], +8941: [8885, 824], +9001: [12296], +9002: [12297], +9312: [49], +9313: [50], +9314: [51], +9315: [52], +9316: [53], +9317: [54], +9318: [55], +9319: [56], +9320: [57], +9321: [49, 48], +9322: [49, 49], +9323: [49, 50], +9324: [49, 51], +9325: [49, 52], +9326: [49, 53], +9327: [49, 54], +9328: [49, 55], +9329: [49, 56], +9330: [49, 57], +9331: [50, 48], +9332: [40, 49, 41], +9333: [40, 50, 41], +9334: [40, 51, 41], +9335: [40, 52, 41], +9336: [40, 53, 41], +9337: [40, 54, 41], +9338: [40, 55, 41], +9339: [40, 56, 41], +9340: [40, 57, 41], +9341: [40, 49, 48, 41], +9342: [40, 49, 49, 41], +9343: [40, 49, 50, 41], +9344: [40, 49, 51, 41], +9345: [40, 49, 52, 41], +9346: [40, 49, 53, 41], +9347: [40, 49, 54, 41], +9348: [40, 49, 55, 41], +9349: [40, 49, 56, 41], +9350: [40, 49, 57, 41], +9351: [40, 50, 48, 41], +9352: [49, 46], +9353: [50, 46], +9354: [51, 46], +9355: [52, 46], +9356: [53, 46], +9357: [54, 46], +9358: [55, 46], +9359: [56, 46], +9360: [57, 46], +9361: [49, 48, 46], +9362: [49, 49, 46], +9363: [49, 50, 46], +9364: [49, 51, 46], +9365: [49, 52, 46], +9366: [49, 53, 46], +9367: [49, 54, 46], +9368: [49, 55, 46], +9369: [49, 56, 46], +9370: [49, 57, 46], +9371: [50, 48, 46], +9372: [40, 97, 41], +9373: [40, 98, 41], +9374: [40, 99, 41], +9375: [40, 100, 41], +9376: [40, 101, 41], +9377: [40, 102, 41], +9378: [40, 103, 41], +9379: [40, 104, 41], +9380: [40, 105, 41], +9381: [40, 106, 41], +9382: [40, 107, 41], +9383: [40, 108, 41], +9384: [40, 109, 41], +9385: [40, 110, 41], +9386: [40, 111, 41], +9387: [40, 112, 41], +9388: [40, 113, 41], +9389: [40, 114, 41], +9390: [40, 115, 41], +9391: [40, 116, 41], +9392: [40, 117, 41], +9393: [40, 118, 41], +9394: [40, 119, 41], +9395: [40, 120, 41], +9396: [40, 121, 41], +9397: [40, 122, 41], +9398: [65], +9399: [66], +9400: [67], +9401: [68], +9402: [69], +9403: [70], +9404: [71], +9405: [72], +9406: [73], +9407: [74], +9408: [75], +9409: [76], +9410: [77], +9411: [78], +9412: [79], +9413: [80], +9414: [81], +9415: [82], +9416: [83], +9417: [84], +9418: [85], +9419: [86], +9420: [87], +9421: [88], +9422: [89], +9423: [90], +9424: [97], +9425: [98], +9426: [99], +9427: [100], +9428: [101], +9429: [102], +9430: [103], +9431: [104], +9432: [105], +9433: [106], +9434: [107], +9435: [108], +9436: [109], +9437: [110], +9438: [111], +9439: [112], +9440: [113], +9441: [114], +9442: [115], +9443: [116], +9444: [117], +9445: [118], +9446: [119], +9447: [120], +9448: [121], +9449: [122], +9450: [48], +10764: [8747, 8747, 8747, 8747], +10868: [58, 58, 61], +10869: [61, 61], +10870: [61, 61, 61], +10972: [10973, 824], +11935: [27597], +12019: [40863], +12032: [19968], +12033: [20008], +12034: [20022], +12035: [20031], +12036: [20057], +12037: [20101], +12038: [20108], +12039: [20128], +12040: [20154], +12041: [20799], +12042: [20837], +12043: [20843], +12044: [20866], +12045: [20886], +12046: [20907], +12047: [20960], +12048: [20981], +12049: [20992], +12050: [21147], +12051: [21241], +12052: [21269], +12053: [21274], +12054: [21304], +12055: [21313], +12056: [21340], +12057: [21353], +12058: [21378], +12059: [21430], +12060: [21448], +12061: [21475], +12062: [22231], +12063: [22303], +12064: [22763], +12065: [22786], +12066: [22794], +12067: [22805], +12068: [22823], +12069: [22899], +12070: [23376], +12071: [23424], +12072: [23544], +12073: [23567], +12074: [23586], +12075: [23608], +12076: [23662], +12077: [23665], +12078: [24027], +12079: [24037], +12080: [24049], +12081: [24062], +12082: [24178], +12083: [24186], +12084: [24191], +12085: [24308], +12086: [24318], +12087: [24331], +12088: [24339], +12089: [24400], +12090: [24417], +12091: [24435], +12092: [24515], +12093: [25096], +12094: [25142], +12095: [25163], +12096: [25903], +12097: [25908], +12098: [25991], +12099: [26007], +12100: [26020], +12101: [26041], +12102: [26080], +12103: [26085], +12104: [26352], +12105: [26376], +12106: [26408], +12107: [27424], +12108: [27490], +12109: [27513], +12110: [27571], +12111: [27595], +12112: [27604], +12113: [27611], +12114: [27663], +12115: [27668], +12116: [27700], +12117: [28779], +12118: [29226], +12119: [29238], +12120: [29243], +12121: [29247], +12122: [29255], +12123: [29273], +12124: [29275], +12125: [29356], +12126: [29572], +12127: [29577], +12128: [29916], +12129: [29926], +12130: [29976], +12131: [29983], +12132: [29992], +12133: [30000], +12134: [30091], +12135: [30098], +12136: [30326], +12137: [30333], +12138: [30382], +12139: [30399], +12140: [30446], +12141: [30683], +12142: [30690], +12143: [30707], +12144: [31034], +12145: [31160], +12146: [31166], +12147: [31348], +12148: [31435], +12149: [31481], +12150: [31859], +12151: [31992], +12152: [32566], +12153: [32593], +12154: [32650], +12155: [32701], +12156: [32769], +12157: [32780], +12158: [32786], +12159: [32819], +12160: [32895], +12161: [32905], +12162: [33251], +12163: [33258], +12164: [33267], +12165: [33276], +12166: [33292], +12167: [33307], +12168: [33311], +12169: [33390], +12170: [33394], +12171: [33400], +12172: [34381], +12173: [34411], +12174: [34880], +12175: [34892], +12176: [34915], +12177: [35198], +12178: [35211], +12179: [35282], +12180: [35328], +12181: [35895], +12182: [35910], +12183: [35925], +12184: [35960], +12185: [35997], +12186: [36196], +12187: [36208], +12188: [36275], +12189: [36523], +12190: [36554], +12191: [36763], +12192: [36784], +12193: [36789], +12194: [37009], +12195: [37193], +12196: [37318], +12197: [37324], +12198: [37329], +12199: [38263], +12200: [38272], +12201: [38428], +12202: [38582], +12203: [38585], +12204: [38632], +12205: [38737], +12206: [38750], +12207: [38754], +12208: [38761], +12209: [38859], +12210: [38893], +12211: [38899], +12212: [38913], +12213: [39080], +12214: [39131], +12215: [39135], +12216: [39318], +12217: [39321], +12218: [39340], +12219: [39592], +12220: [39640], +12221: [39647], +12222: [39717], +12223: [39727], +12224: [39730], +12225: [39740], +12226: [39770], +12227: [40165], +12228: [40565], +12229: [40575], +12230: [40613], +12231: [40635], +12232: [40643], +12233: [40653], +12234: [40657], +12235: [40697], +12236: [40701], +12237: [40718], +12238: [40723], +12239: [40736], +12240: [40763], +12241: [40778], +12242: [40786], +12243: [40845], +12244: [40860], +12245: [40864], +12288: [32], +12342: [12306], +12344: [21313], +12345: [21316], +12346: [21317], +12364: [12363, 12441], +12366: [12365, 12441], +12368: [12367, 12441], +12370: [12369, 12441], +12372: [12371, 12441], +12374: [12373, 12441], +12376: [12375, 12441], +12378: [12377, 12441], +12380: [12379, 12441], +12382: [12381, 12441], +12384: [12383, 12441], +12386: [12385, 12441], +12389: [12388, 12441], +12391: [12390, 12441], +12393: [12392, 12441], +12400: [12399, 12441], +12401: [12399, 12442], +12403: [12402, 12441], +12404: [12402, 12442], +12406: [12405, 12441], +12407: [12405, 12442], +12409: [12408, 12441], +12410: [12408, 12442], +12412: [12411, 12441], +12413: [12411, 12442], +12436: [12358, 12441], +12443: [32, 12441], +12444: [32, 12442], +12446: [12445, 12441], +12447: [12424, 12426], +12460: [12459, 12441], +12462: [12461, 12441], +12464: [12463, 12441], +12466: [12465, 12441], +12468: [12467, 12441], +12470: [12469, 12441], +12472: [12471, 12441], +12474: [12473, 12441], +12476: [12475, 12441], +12478: [12477, 12441], +12480: [12479, 12441], +12482: [12481, 12441], +12485: [12484, 12441], +12487: [12486, 12441], +12489: [12488, 12441], +12496: [12495, 12441], +12497: [12495, 12442], +12499: [12498, 12441], +12500: [12498, 12442], +12502: [12501, 12441], +12503: [12501, 12442], +12505: [12504, 12441], +12506: [12504, 12442], +12508: [12507, 12441], +12509: [12507, 12442], +12532: [12454, 12441], +12535: [12527, 12441], +12536: [12528, 12441], +12537: [12529, 12441], +12538: [12530, 12441], +12542: [12541, 12441], +12543: [12467, 12488], +12593: [4352], +12594: [4353], +12595: [4522], +12596: [4354], +12597: [4524], +12598: [4525], +12599: [4355], +12600: [4356], +12601: [4357], +12602: [4528], +12603: [4529], +12604: [4530], +12605: [4531], +12606: [4532], +12607: [4533], +12608: [4378], +12609: [4358], +12610: [4359], +12611: [4360], +12612: [4385], +12613: [4361], +12614: [4362], +12615: [4363], +12616: [4364], +12617: [4365], +12618: [4366], +12619: [4367], +12620: [4368], +12621: [4369], +12622: [4370], +12623: [4449], +12624: [4450], +12625: [4451], +12626: [4452], +12627: [4453], +12628: [4454], +12629: [4455], +12630: [4456], +12631: [4457], +12632: [4458], +12633: [4459], +12634: [4460], +12635: [4461], +12636: [4462], +12637: [4463], +12638: [4464], +12639: [4465], +12640: [4466], +12641: [4467], +12642: [4468], +12643: [4469], +12644: [4448], +12645: [4372], +12646: [4373], +12647: [4551], +12648: [4552], +12649: [4556], +12650: [4558], +12651: [4563], +12652: [4567], +12653: [4569], +12654: [4380], +12655: [4573], +12656: [4575], +12657: [4381], +12658: [4382], +12659: [4384], +12660: [4386], +12661: [4387], +12662: [4391], +12663: [4393], +12664: [4395], +12665: [4396], +12666: [4397], +12667: [4398], +12668: [4399], +12669: [4402], +12670: [4406], +12671: [4416], +12672: [4423], +12673: [4428], +12674: [4593], +12675: [4594], +12676: [4439], +12677: [4440], +12678: [4441], +12679: [4484], +12680: [4485], +12681: [4488], +12682: [4497], +12683: [4498], +12684: [4500], +12685: [4510], +12686: [4513], +12690: [19968], +12691: [20108], +12692: [19977], +12693: [22235], +12694: [19978], +12695: [20013], +12696: [19979], +12697: [30002], +12698: [20057], +12699: [19993], +12700: [19969], +12701: [22825], +12702: [22320], +12703: [20154], +12800: [40, 4352, 41], +12801: [40, 4354, 41], +12802: [40, 4355, 41], +12803: [40, 4357, 41], +12804: [40, 4358, 41], +12805: [40, 4359, 41], +12806: [40, 4361, 41], +12807: [40, 4363, 41], +12808: [40, 4364, 41], +12809: [40, 4366, 41], +12810: [40, 4367, 41], +12811: [40, 4368, 41], +12812: [40, 4369, 41], +12813: [40, 4370, 41], +12814: [40, 4352, 4449, 41], +12815: [40, 4354, 4449, 41], +12816: [40, 4355, 4449, 41], +12817: [40, 4357, 4449, 41], +12818: [40, 4358, 4449, 41], +12819: [40, 4359, 4449, 41], +12820: [40, 4361, 4449, 41], +12821: [40, 4363, 4449, 41], +12822: [40, 4364, 4449, 41], +12823: [40, 4366, 4449, 41], +12824: [40, 4367, 4449, 41], +12825: [40, 4368, 4449, 41], +12826: [40, 4369, 4449, 41], +12827: [40, 4370, 4449, 41], +12828: [40, 4364, 4462, 41], +12832: [40, 19968, 41], +12833: [40, 20108, 41], +12834: [40, 19977, 41], +12835: [40, 22235, 41], +12836: [40, 20116, 41], +12837: [40, 20845, 41], +12838: [40, 19971, 41], +12839: [40, 20843, 41], +12840: [40, 20061, 41], +12841: [40, 21313, 41], +12842: [40, 26376, 41], +12843: [40, 28779, 41], +12844: [40, 27700, 41], +12845: [40, 26408, 41], +12846: [40, 37329, 41], +12847: [40, 22303, 41], +12848: [40, 26085, 41], +12849: [40, 26666, 41], +12850: [40, 26377, 41], +12851: [40, 31038, 41], +12852: [40, 21517, 41], +12853: [40, 29305, 41], +12854: [40, 36001, 41], +12855: [40, 31069, 41], +12856: [40, 21172, 41], +12857: [40, 20195, 41], +12858: [40, 21628, 41], +12859: [40, 23398, 41], +12860: [40, 30435, 41], +12861: [40, 20225, 41], +12862: [40, 36039, 41], +12863: [40, 21332, 41], +12864: [40, 31085, 41], +12865: [40, 20241, 41], +12866: [40, 33258, 41], +12867: [40, 33267, 41], +12881: [50, 49], +12882: [50, 50], +12883: [50, 51], +12884: [50, 52], +12885: [50, 53], +12886: [50, 54], +12887: [50, 55], +12888: [50, 56], +12889: [50, 57], +12890: [51, 48], +12891: [51, 49], +12892: [51, 50], +12893: [51, 51], +12894: [51, 52], +12895: [51, 53], +12896: [4352], +12897: [4354], +12898: [4355], +12899: [4357], +12900: [4358], +12901: [4359], +12902: [4361], +12903: [4363], +12904: [4364], +12905: [4366], +12906: [4367], +12907: [4368], +12908: [4369], +12909: [4370], +12910: [4352, 4449], +12911: [4354, 4449], +12912: [4355, 4449], +12913: [4357, 4449], +12914: [4358, 4449], +12915: [4359, 4449], +12916: [4361, 4449], +12917: [4363, 4449], +12918: [4364, 4449], +12919: [4366, 4449], +12920: [4367, 4449], +12921: [4368, 4449], +12922: [4369, 4449], +12923: [4370, 4449], +12928: [19968], +12929: [20108], +12930: [19977], +12931: [22235], +12932: [20116], +12933: [20845], +12934: [19971], +12935: [20843], +12936: [20061], +12937: [21313], +12938: [26376], +12939: [28779], +12940: [27700], +12941: [26408], +12942: [37329], +12943: [22303], +12944: [26085], +12945: [26666], +12946: [26377], +12947: [31038], +12948: [21517], +12949: [29305], +12950: [36001], +12951: [31069], +12952: [21172], +12953: [31192], +12954: [30007], +12955: [22899], +12956: [36969], +12957: [20778], +12958: [21360], +12959: [27880], +12960: [38917], +12961: [20241], +12962: [20889], +12963: [27491], +12964: [19978], +12965: [20013], +12966: [19979], +12967: [24038], +12968: [21491], +12969: [21307], +12970: [23447], +12971: [23398], +12972: [30435], +12973: [20225], +12974: [36039], +12975: [21332], +12976: [22812], +12977: [51, 54], +12978: [51, 55], +12979: [51, 56], +12980: [51, 57], +12981: [52, 48], +12982: [52, 49], +12983: [52, 50], +12984: [52, 51], +12985: [52, 52], +12986: [52, 53], +12987: [52, 54], +12988: [52, 55], +12989: [52, 56], +12990: [52, 57], +12991: [53, 48], +12992: [49, 26376], +12993: [50, 26376], +12994: [51, 26376], +12995: [52, 26376], +12996: [53, 26376], +12997: [54, 26376], +12998: [55, 26376], +12999: [56, 26376], +13000: [57, 26376], +13001: [49, 48, 26376], +13002: [49, 49, 26376], +13003: [49, 50, 26376], +13008: [12450], +13009: [12452], +13010: [12454], +13011: [12456], +13012: [12458], +13013: [12459], +13014: [12461], +13015: [12463], +13016: [12465], +13017: [12467], +13018: [12469], +13019: [12471], +13020: [12473], +13021: [12475], +13022: [12477], +13023: [12479], +13024: [12481], +13025: [12484], +13026: [12486], +13027: [12488], +13028: [12490], +13029: [12491], +13030: [12492], +13031: [12493], +13032: [12494], +13033: [12495], +13034: [12498], +13035: [12501], +13036: [12504], +13037: [12507], +13038: [12510], +13039: [12511], +13040: [12512], +13041: [12513], +13042: [12514], +13043: [12516], +13044: [12518], +13045: [12520], +13046: [12521], +13047: [12522], +13048: [12523], +13049: [12524], +13050: [12525], +13051: [12527], +13052: [12528], +13053: [12529], +13054: [12530], +13056: [12450, 12495, 12442, 12540, 12488], +13057: [12450, 12523, 12501, 12449], +13058: [12450, 12531, 12504, 12442, 12450], +13059: [12450, 12540, 12523], +13060: [12452, 12491, 12531, 12463, 12441], +13061: [12452, 12531, 12481], +13062: [12454, 12457, 12531], +13063: [12456, 12473, 12463, 12540, 12488, 12441], +13064: [12456, 12540, 12459, 12540], +13065: [12458, 12531, 12473], +13066: [12458, 12540, 12512], +13067: [12459, 12452, 12522], +13068: [12459, 12521, 12483, 12488], +13069: [12459, 12525, 12522, 12540], +13070: [12459, 12441, 12525, 12531], +13071: [12459, 12441, 12531, 12510], +13072: [12461, 12441, 12459, 12441], +13073: [12461, 12441, 12491, 12540], +13074: [12461, 12517, 12522, 12540], +13075: [12461, 12441, 12523, 12479, 12441, 12540], +13076: [12461, 12525], +13077: [12461, 12525, 12463, 12441, 12521, 12512], +13078: [12461, 12525, 12513, 12540, 12488, 12523], +13079: [12461, 12525, 12527, 12483, 12488], +13080: [12463, 12441, 12521, 12512], +13081: [12463, 12441, 12521, 12512, 12488, 12531], +13082: [12463, 12523, 12475, 12441, 12452, 12525], +13083: [12463, 12525, 12540, 12493], +13084: [12465, 12540, 12473], +13085: [12467, 12523, 12490], +13086: [12467, 12540, 12507, 12442], +13087: [12469, 12452, 12463, 12523], +13088: [12469, 12531, 12481, 12540, 12512], +13089: [12471, 12522, 12531, 12463, 12441], +13090: [12475, 12531, 12481], +13091: [12475, 12531, 12488], +13092: [12479, 12441, 12540, 12473], +13093: [12486, 12441, 12471], +13094: [12488, 12441, 12523], +13095: [12488, 12531], +13096: [12490, 12494], +13097: [12494, 12483, 12488], +13098: [12495, 12452, 12484], +13099: [12495, 12442, 12540, 12475, 12531, 12488], +13100: [12495, 12442, 12540, 12484], +13101: [12495, 12441, 12540, 12524, 12523], +13102: [12498, 12442, 12450, 12473, 12488, 12523], +13103: [12498, 12442, 12463, 12523], +13104: [12498, 12442, 12467], +13105: [12498, 12441, 12523], +13106: [12501, 12449, 12521, 12483, 12488, 12441], +13107: [12501, 12451, 12540, 12488], +13108: [12501, 12441, 12483, 12471, 12455, 12523], +13109: [12501, 12521, 12531], +13110: [12504, 12463, 12479, 12540, 12523], +13111: [12504, 12442, 12477], +13112: [12504, 12442, 12491, 12498], +13113: [12504, 12523, 12484], +13114: [12504, 12442, 12531, 12473], +13115: [12504, 12442, 12540, 12471, 12441], +13116: [12504, 12441, 12540, 12479], +13117: [12507, 12442, 12452, 12531, 12488], +13118: [12507, 12441, 12523, 12488], +13119: [12507, 12531], +13120: [12507, 12442, 12531, 12488, 12441], +13121: [12507, 12540, 12523], +13122: [12507, 12540, 12531], +13123: [12510, 12452, 12463, 12525], +13124: [12510, 12452, 12523], +13125: [12510, 12483, 12495], +13126: [12510, 12523, 12463], +13127: [12510, 12531, 12471, 12519, 12531], +13128: [12511, 12463, 12525, 12531], +13129: [12511, 12522], +13130: [12511, 12522, 12495, 12441, 12540, 12523], +13131: [12513, 12459, 12441], +13132: [12513, 12459, 12441, 12488, 12531], +13133: [12513, 12540, 12488, 12523], +13134: [12516, 12540, 12488, 12441], +13135: [12516, 12540, 12523], +13136: [12518, 12450, 12531], +13137: [12522, 12483, 12488, 12523], +13138: [12522, 12521], +13139: [12523, 12498, 12442, 12540], +13140: [12523, 12540, 12501, 12441, 12523], +13141: [12524, 12512], +13142: [12524, 12531, 12488, 12465, 12441, 12531], +13143: [12527, 12483, 12488], +13144: [48, 28857], +13145: [49, 28857], +13146: [50, 28857], +13147: [51, 28857], +13148: [52, 28857], +13149: [53, 28857], +13150: [54, 28857], +13151: [55, 28857], +13152: [56, 28857], +13153: [57, 28857], +13154: [49, 48, 28857], +13155: [49, 49, 28857], +13156: [49, 50, 28857], +13157: [49, 51, 28857], +13158: [49, 52, 28857], +13159: [49, 53, 28857], +13160: [49, 54, 28857], +13161: [49, 55, 28857], +13162: [49, 56, 28857], +13163: [49, 57, 28857], +13164: [50, 48, 28857], +13165: [50, 49, 28857], +13166: [50, 50, 28857], +13167: [50, 51, 28857], +13168: [50, 52, 28857], +13169: [104, 80, 97], +13170: [100, 97], +13171: [65, 85], +13172: [98, 97, 114], +13173: [111, 86], +13174: [112, 99], +13179: [24179, 25104], +13180: [26157, 21644], +13181: [22823, 27491], +13182: [26126, 27835], +13183: [26666, 24335, 20250, 31038], +13184: [112, 65], +13185: [110, 65], +13186: [956, 65], +13187: [109, 65], +13188: [107, 65], +13189: [75, 66], +13190: [77, 66], +13191: [71, 66], +13192: [99, 97, 108], +13193: [107, 99, 97, 108], +13194: [112, 70], +13195: [110, 70], +13196: [956, 70], +13197: [956, 103], +13198: [109, 103], +13199: [107, 103], +13200: [72, 122], +13201: [107, 72, 122], +13202: [77, 72, 122], +13203: [71, 72, 122], +13204: [84, 72, 122], +13205: [956, 108], +13206: [109, 108], +13207: [100, 108], +13208: [107, 108], +13209: [102, 109], +13210: [110, 109], +13211: [956, 109], +13212: [109, 109], +13213: [99, 109], +13214: [107, 109], +13215: [109, 109, 50], +13216: [99, 109, 50], +13217: [109, 50], +13218: [107, 109, 50], +13219: [109, 109, 51], +13220: [99, 109, 51], +13221: [109, 51], +13222: [107, 109, 51], +13223: [109, 8725, 115], +13224: [109, 8725, 115, 50], +13225: [80, 97], +13226: [107, 80, 97], +13227: [77, 80, 97], +13228: [71, 80, 97], +13229: [114, 97, 100], +13230: [114, 97, 100, 8725, 115], +13231: [114, 97, 100, 8725, 115, 50], +13232: [112, 115], +13233: [110, 115], +13234: [956, 115], +13235: [109, 115], +13236: [112, 86], +13237: [110, 86], +13238: [956, 86], +13239: [109, 86], +13240: [107, 86], +13241: [77, 86], +13242: [112, 87], +13243: [110, 87], +13244: [956, 87], +13245: [109, 87], +13246: [107, 87], +13247: [77, 87], +13248: [107, 937], +13249: [77, 937], +13250: [97, 46, 109, 46], +13251: [66, 113], +13252: [99, 99], +13253: [99, 100], +13254: [67, 8725, 107, 103], +13255: [67, 111, 46], +13256: [100, 66], +13257: [71, 121], +13258: [104, 97], +13259: [72, 80], +13260: [105, 110], +13261: [75, 75], +13262: [75, 77], +13263: [107, 116], +13264: [108, 109], +13265: [108, 110], +13266: [108, 111, 103], +13267: [108, 120], +13268: [109, 98], +13269: [109, 105, 108], +13270: [109, 111, 108], +13271: [80, 72], +13272: [112, 46, 109, 46], +13273: [80, 80, 77], +13274: [80, 82], +13275: [115, 114], +13276: [83, 118], +13277: [87, 98], +13280: [49, 26085], +13281: [50, 26085], +13282: [51, 26085], +13283: [52, 26085], +13284: [53, 26085], +13285: [54, 26085], +13286: [55, 26085], +13287: [56, 26085], +13288: [57, 26085], +13289: [49, 48, 26085], +13290: [49, 49, 26085], +13291: [49, 50, 26085], +13292: [49, 51, 26085], +13293: [49, 52, 26085], +13294: [49, 53, 26085], +13295: [49, 54, 26085], +13296: [49, 55, 26085], +13297: [49, 56, 26085], +13298: [49, 57, 26085], +13299: [50, 48, 26085], +13300: [50, 49, 26085], +13301: [50, 50, 26085], +13302: [50, 51, 26085], +13303: [50, 52, 26085], +13304: [50, 53, 26085], +13305: [50, 54, 26085], +13306: [50, 55, 26085], +13307: [50, 56, 26085], +13308: [50, 57, 26085], +13309: [51, 48, 26085], +13310: [51, 49, 26085], +63744: [35912], +63745: [26356], +63746: [36554], +63747: [36040], +63748: [28369], +63749: [20018], +63750: [21477], +63751: [40860], +63752: [40860], +63753: [22865], +63754: [37329], +63755: [21895], +63756: [22856], +63757: [25078], +63758: [30313], +63759: [32645], +63760: [34367], +63761: [34746], +63762: [35064], +63763: [37007], +63764: [27138], +63765: [27931], +63766: [28889], +63767: [29662], +63768: [33853], +63769: [37226], +63770: [39409], +63771: [20098], +63772: [21365], +63773: [27396], +63774: [29211], +63775: [34349], +63776: [40478], +63777: [23888], +63778: [28651], +63779: [34253], +63780: [35172], +63781: [25289], +63782: [33240], +63783: [34847], +63784: [24266], +63785: [26391], +63786: [28010], +63787: [29436], +63788: [37070], +63789: [20358], +63790: [20919], +63791: [21214], +63792: [25796], +63793: [27347], +63794: [29200], +63795: [30439], +63796: [32769], +63797: [34310], +63798: [34396], +63799: [36335], +63800: [38706], +63801: [39791], +63802: [40442], +63803: [30860], +63804: [31103], +63805: [32160], +63806: [33737], +63807: [37636], +63808: [40575], +63809: [35542], +63810: [22751], +63811: [24324], +63812: [31840], +63813: [32894], +63814: [29282], +63815: [30922], +63816: [36034], +63817: [38647], +63818: [22744], +63819: [23650], +63820: [27155], +63821: [28122], +63822: [28431], +63823: [32047], +63824: [32311], +63825: [38475], +63826: [21202], +63827: [32907], +63828: [20956], +63829: [20940], +63830: [31260], +63831: [32190], +63832: [33777], +63833: [38517], +63834: [35712], +63835: [25295], +63836: [27138], +63837: [35582], +63838: [20025], +63839: [23527], +63840: [24594], +63841: [29575], +63842: [30064], +63843: [21271], +63844: [30971], +63845: [20415], +63846: [24489], +63847: [19981], +63848: [27852], +63849: [25976], +63850: [32034], +63851: [21443], +63852: [22622], +63853: [30465], +63854: [33865], +63855: [35498], +63856: [27578], +63857: [36784], +63858: [27784], +63859: [25342], +63860: [33509], +63861: [25504], +63862: [30053], +63863: [20142], +63864: [20841], +63865: [20937], +63866: [26753], +63867: [31975], +63868: [33391], +63869: [35538], +63870: [37327], +63871: [21237], +63872: [21570], +63873: [22899], +63874: [24300], +63875: [26053], +63876: [28670], +63877: [31018], +63878: [38317], +63879: [39530], +63880: [40599], +63881: [40654], +63882: [21147], +63883: [26310], +63884: [27511], +63885: [36706], +63886: [24180], +63887: [24976], +63888: [25088], +63889: [25754], +63890: [28451], +63891: [29001], +63892: [29833], +63893: [31178], +63894: [32244], +63895: [32879], +63896: [36646], +63897: [34030], +63898: [36899], +63899: [37706], +63900: [21015], +63901: [21155], +63902: [21693], +63903: [28872], +63904: [35010], +63905: [35498], +63906: [24265], +63907: [24565], +63908: [25467], +63909: [27566], +63910: [31806], +63911: [29557], +63912: [20196], +63913: [22265], +63914: [23527], +63915: [23994], +63916: [24604], +63917: [29618], +63918: [29801], +63919: [32666], +63920: [32838], +63921: [37428], +63922: [38646], +63923: [38728], +63924: [38936], +63925: [20363], +63926: [31150], +63927: [37300], +63928: [38584], +63929: [24801], +63930: [20102], +63931: [20698], +63932: [23534], +63933: [23615], +63934: [26009], +63935: [27138], +63936: [29134], +63937: [30274], +63938: [34044], +63939: [36988], +63940: [40845], +63941: [26248], +63942: [38446], +63943: [21129], +63944: [26491], +63945: [26611], +63946: [27969], +63947: [28316], +63948: [29705], +63949: [30041], +63950: [30827], +63951: [32016], +63952: [39006], +63953: [20845], +63954: [25134], +63955: [38520], +63956: [20523], +63957: [23833], +63958: [28138], +63959: [36650], +63960: [24459], +63961: [24900], +63962: [26647], +63963: [29575], +63964: [38534], +63965: [21033], +63966: [21519], +63967: [23653], +63968: [26131], +63969: [26446], +63970: [26792], +63971: [27877], +63972: [29702], +63973: [30178], +63974: [32633], +63975: [35023], +63976: [35041], +63977: [37324], +63978: [38626], +63979: [21311], +63980: [28346], +63981: [21533], +63982: [29136], +63983: [29848], +63984: [34298], +63985: [38563], +63986: [40023], +63987: [40607], +63988: [26519], +63989: [28107], +63990: [33256], +63991: [31435], +63992: [31520], +63993: [31890], +63994: [29376], +63995: [28825], +63996: [35672], +63997: [20160], +63998: [33590], +63999: [21050], +64000: [20999], +64001: [24230], +64002: [25299], +64003: [31958], +64004: [23429], +64005: [27934], +64006: [26292], +64007: [36667], +64008: [34892], +64009: [38477], +64010: [35211], +64011: [24275], +64012: [20800], +64013: [21952], +64016: [22618], +64018: [26228], +64021: [20958], +64022: [29482], +64023: [30410], +64024: [31036], +64025: [31070], +64026: [31077], +64027: [31119], +64028: [38742], +64029: [31934], +64030: [32701], +64032: [34322], +64034: [35576], +64037: [36920], +64038: [37117], +64042: [39151], +64043: [39164], +64044: [39208], +64045: [40372], +64048: [20398], +64049: [20711], +64050: [20813], +64051: [21193], +64052: [21220], +64053: [21329], +64054: [21917], +64055: [22022], +64056: [22120], +64057: [22592], +64058: [22696], +64059: [23652], +64060: [23662], +64061: [24724], +64062: [24936], +64063: [24974], +64064: [25074], +64065: [25935], +64066: [26082], +64067: [26257], +64068: [26757], +64069: [28023], +64070: [28186], +64071: [28450], +64072: [29038], +64073: [29227], +64074: [29730], +64075: [30865], +64076: [31038], +64077: [31049], +64078: [31048], +64079: [31056], +64080: [31062], +64081: [31069], +64082: [31117], +64083: [31118], +64084: [31296], +64085: [31361], +64086: [31680], +64087: [32244], +64088: [32265], +64089: [32321], +64090: [32626], +64091: [32773], +64092: [33261], +64093: [33401], +64094: [33401], +64095: [33879], +64096: [35088], +64097: [35222], +64098: [35585], +64099: [35641], +64100: [36051], +64101: [36104], +64102: [36790], +64103: [36920], +64104: [38627], +64105: [38911], +64106: [38971], +64256: [102, 102], +64257: [102, 105], +64258: [102, 108], +64259: [102, 102, 105], +64260: [102, 102, 108], +64261: [115, 116], +64262: [115, 116], +64275: [1396, 1398], +64276: [1396, 1381], +64277: [1396, 1387], +64278: [1406, 1398], +64279: [1396, 1389], +64285: [1497, 1460], +64287: [1522, 1463], +64288: [1506], +64289: [1488], +64290: [1491], +64291: [1492], +64292: [1499], +64293: [1500], +64294: [1501], +64295: [1512], +64296: [1514], +64297: [43], +64298: [1513, 1473], +64299: [1513, 1474], +64300: [1513, 1468, 1473], +64301: [1513, 1468, 1474], +64302: [1488, 1463], +64303: [1488, 1464], +64304: [1488, 1468], +64305: [1489, 1468], +64306: [1490, 1468], +64307: [1491, 1468], +64308: [1492, 1468], +64309: [1493, 1468], +64310: [1494, 1468], +64312: [1496, 1468], +64313: [1497, 1468], +64314: [1498, 1468], +64315: [1499, 1468], +64316: [1500, 1468], +64318: [1502, 1468], +64320: [1504, 1468], +64321: [1505, 1468], +64323: [1507, 1468], +64324: [1508, 1468], +64326: [1510, 1468], +64327: [1511, 1468], +64328: [1512, 1468], +64329: [1513, 1468], +64330: [1514, 1468], +64331: [1493, 1465], +64332: [1489, 1471], +64333: [1499, 1471], +64334: [1508, 1471], +64335: [1488, 1500], +64336: [1649], +64337: [1649], +64338: [1659], +64339: [1659], +64340: [1659], +64341: [1659], +64342: [1662], +64343: [1662], +64344: [1662], +64345: [1662], +64346: [1664], +64347: [1664], +64348: [1664], +64349: [1664], +64350: [1658], +64351: [1658], +64352: [1658], +64353: [1658], +64354: [1663], +64355: [1663], +64356: [1663], +64357: [1663], +64358: [1657], +64359: [1657], +64360: [1657], +64361: [1657], +64362: [1700], +64363: [1700], +64364: [1700], +64365: [1700], +64366: [1702], +64367: [1702], +64368: [1702], +64369: [1702], +64370: [1668], +64371: [1668], +64372: [1668], +64373: [1668], +64374: [1667], +64375: [1667], +64376: [1667], +64377: [1667], +64378: [1670], +64379: [1670], +64380: [1670], +64381: [1670], +64382: [1671], +64383: [1671], +64384: [1671], +64385: [1671], +64386: [1677], +64387: [1677], +64388: [1676], +64389: [1676], +64390: [1678], +64391: [1678], +64392: [1672], +64393: [1672], +64394: [1688], +64395: [1688], +64396: [1681], +64397: [1681], +64398: [1705], +64399: [1705], +64400: [1705], +64401: [1705], +64402: [1711], +64403: [1711], +64404: [1711], +64405: [1711], +64406: [1715], +64407: [1715], +64408: [1715], +64409: [1715], +64410: [1713], +64411: [1713], +64412: [1713], +64413: [1713], +64414: [1722], +64415: [1722], +64416: [1723], +64417: [1723], +64418: [1723], +64419: [1723], +64420: [1749, 1620], +64421: [1749, 1620], +64422: [1729], +64423: [1729], +64424: [1729], +64425: [1729], +64426: [1726], +64427: [1726], +64428: [1726], +64429: [1726], +64430: [1746], +64431: [1746], +64432: [1746, 1620], +64433: [1746, 1620], +64467: [1709], +64468: [1709], +64469: [1709], +64470: [1709], +64471: [1735], +64472: [1735], +64473: [1734], +64474: [1734], +64475: [1736], +64476: [1736], +64477: [1735, 1652], +64478: [1739], +64479: [1739], +64480: [1733], +64481: [1733], +64482: [1737], +64483: [1737], +64484: [1744], +64485: [1744], +64486: [1744], +64487: [1744], +64488: [1609], +64489: [1609], +64490: [1610, 1620, 1575], +64491: [1610, 1620, 1575], +64492: [1610, 1620, 1749], +64493: [1610, 1620, 1749], +64494: [1610, 1620, 1608], +64495: [1610, 1620, 1608], +64496: [1610, 1620, 1735], +64497: [1610, 1620, 1735], +64498: [1610, 1620, 1734], +64499: [1610, 1620, 1734], +64500: [1610, 1620, 1736], +64501: [1610, 1620, 1736], +64502: [1610, 1620, 1744], +64503: [1610, 1620, 1744], +64504: [1610, 1620, 1744], +64505: [1610, 1620, 1609], +64506: [1610, 1620, 1609], +64507: [1610, 1620, 1609], +64508: [1740], +64509: [1740], +64510: [1740], +64511: [1740], +64512: [1610, 1620, 1580], +64513: [1610, 1620, 1581], +64514: [1610, 1620, 1605], +64515: [1610, 1620, 1609], +64516: [1610, 1620, 1610], +64517: [1576, 1580], +64518: [1576, 1581], +64519: [1576, 1582], +64520: [1576, 1605], +64521: [1576, 1609], +64522: [1576, 1610], +64523: [1578, 1580], +64524: [1578, 1581], +64525: [1578, 1582], +64526: [1578, 1605], +64527: [1578, 1609], +64528: [1578, 1610], +64529: [1579, 1580], +64530: [1579, 1605], +64531: [1579, 1609], +64532: [1579, 1610], +64533: [1580, 1581], +64534: [1580, 1605], +64535: [1581, 1580], +64536: [1581, 1605], +64537: [1582, 1580], +64538: [1582, 1581], +64539: [1582, 1605], +64540: [1587, 1580], +64541: [1587, 1581], +64542: [1587, 1582], +64543: [1587, 1605], +64544: [1589, 1581], +64545: [1589, 1605], +64546: [1590, 1580], +64547: [1590, 1581], +64548: [1590, 1582], +64549: [1590, 1605], +64550: [1591, 1581], +64551: [1591, 1605], +64552: [1592, 1605], +64553: [1593, 1580], +64554: [1593, 1605], +64555: [1594, 1580], +64556: [1594, 1605], +64557: [1601, 1580], +64558: [1601, 1581], +64559: [1601, 1582], +64560: [1601, 1605], +64561: [1601, 1609], +64562: [1601, 1610], +64563: [1602, 1581], +64564: [1602, 1605], +64565: [1602, 1609], +64566: [1602, 1610], +64567: [1603, 1575], +64568: [1603, 1580], +64569: [1603, 1581], +64570: [1603, 1582], +64571: [1603, 1604], +64572: [1603, 1605], +64573: [1603, 1609], +64574: [1603, 1610], +64575: [1604, 1580], +64576: [1604, 1581], +64577: [1604, 1582], +64578: [1604, 1605], +64579: [1604, 1609], +64580: [1604, 1610], +64581: [1605, 1580], +64582: [1605, 1581], +64583: [1605, 1582], +64584: [1605, 1605], +64585: [1605, 1609], +64586: [1605, 1610], +64587: [1606, 1580], +64588: [1606, 1581], +64589: [1606, 1582], +64590: [1606, 1605], +64591: [1606, 1609], +64592: [1606, 1610], +64593: [1607, 1580], +64594: [1607, 1605], +64595: [1607, 1609], +64596: [1607, 1610], +64597: [1610, 1580], +64598: [1610, 1581], +64599: [1610, 1582], +64600: [1610, 1605], +64601: [1610, 1609], +64602: [1610, 1610], +64603: [1584, 1648], +64604: [1585, 1648], +64605: [1609, 1648], +64606: [32, 1612, 1617], +64607: [32, 1613, 1617], +64608: [32, 1614, 1617], +64609: [32, 1615, 1617], +64610: [32, 1616, 1617], +64611: [32, 1617, 1648], +64612: [1610, 1620, 1585], +64613: [1610, 1620, 1586], +64614: [1610, 1620, 1605], +64615: [1610, 1620, 1606], +64616: [1610, 1620, 1609], +64617: [1610, 1620, 1610], +64618: [1576, 1585], +64619: [1576, 1586], +64620: [1576, 1605], +64621: [1576, 1606], +64622: [1576, 1609], +64623: [1576, 1610], +64624: [1578, 1585], +64625: [1578, 1586], +64626: [1578, 1605], +64627: [1578, 1606], +64628: [1578, 1609], +64629: [1578, 1610], +64630: [1579, 1585], +64631: [1579, 1586], +64632: [1579, 1605], +64633: [1579, 1606], +64634: [1579, 1609], +64635: [1579, 1610], +64636: [1601, 1609], +64637: [1601, 1610], +64638: [1602, 1609], +64639: [1602, 1610], +64640: [1603, 1575], +64641: [1603, 1604], +64642: [1603, 1605], +64643: [1603, 1609], +64644: [1603, 1610], +64645: [1604, 1605], +64646: [1604, 1609], +64647: [1604, 1610], +64648: [1605, 1575], +64649: [1605, 1605], +64650: [1606, 1585], +64651: [1606, 1586], +64652: [1606, 1605], +64653: [1606, 1606], +64654: [1606, 1609], +64655: [1606, 1610], +64656: [1609, 1648], +64657: [1610, 1585], +64658: [1610, 1586], +64659: [1610, 1605], +64660: [1610, 1606], +64661: [1610, 1609], +64662: [1610, 1610], +64663: [1610, 1620, 1580], +64664: [1610, 1620, 1581], +64665: [1610, 1620, 1582], +64666: [1610, 1620, 1605], +64667: [1610, 1620, 1607], +64668: [1576, 1580], +64669: [1576, 1581], +64670: [1576, 1582], +64671: [1576, 1605], +64672: [1576, 1607], +64673: [1578, 1580], +64674: [1578, 1581], +64675: [1578, 1582], +64676: [1578, 1605], +64677: [1578, 1607], +64678: [1579, 1605], +64679: [1580, 1581], +64680: [1580, 1605], +64681: [1581, 1580], +64682: [1581, 1605], +64683: [1582, 1580], +64684: [1582, 1605], +64685: [1587, 1580], +64686: [1587, 1581], +64687: [1587, 1582], +64688: [1587, 1605], +64689: [1589, 1581], +64690: [1589, 1582], +64691: [1589, 1605], +64692: [1590, 1580], +64693: [1590, 1581], +64694: [1590, 1582], +64695: [1590, 1605], +64696: [1591, 1581], +64697: [1592, 1605], +64698: [1593, 1580], +64699: [1593, 1605], +64700: [1594, 1580], +64701: [1594, 1605], +64702: [1601, 1580], +64703: [1601, 1581], +64704: [1601, 1582], +64705: [1601, 1605], +64706: [1602, 1581], +64707: [1602, 1605], +64708: [1603, 1580], +64709: [1603, 1581], +64710: [1603, 1582], +64711: [1603, 1604], +64712: [1603, 1605], +64713: [1604, 1580], +64714: [1604, 1581], +64715: [1604, 1582], +64716: [1604, 1605], +64717: [1604, 1607], +64718: [1605, 1580], +64719: [1605, 1581], +64720: [1605, 1582], +64721: [1605, 1605], +64722: [1606, 1580], +64723: [1606, 1581], +64724: [1606, 1582], +64725: [1606, 1605], +64726: [1606, 1607], +64727: [1607, 1580], +64728: [1607, 1605], +64729: [1607, 1648], +64730: [1610, 1580], +64731: [1610, 1581], +64732: [1610, 1582], +64733: [1610, 1605], +64734: [1610, 1607], +64735: [1610, 1620, 1605], +64736: [1610, 1620, 1607], +64737: [1576, 1605], +64738: [1576, 1607], +64739: [1578, 1605], +64740: [1578, 1607], +64741: [1579, 1605], +64742: [1579, 1607], +64743: [1587, 1605], +64744: [1587, 1607], +64745: [1588, 1605], +64746: [1588, 1607], +64747: [1603, 1604], +64748: [1603, 1605], +64749: [1604, 1605], +64750: [1606, 1605], +64751: [1606, 1607], +64752: [1610, 1605], +64753: [1610, 1607], +64754: [1600, 1614, 1617], +64755: [1600, 1615, 1617], +64756: [1600, 1616, 1617], +64757: [1591, 1609], +64758: [1591, 1610], +64759: [1593, 1609], +64760: [1593, 1610], +64761: [1594, 1609], +64762: [1594, 1610], +64763: [1587, 1609], +64764: [1587, 1610], +64765: [1588, 1609], +64766: [1588, 1610], +64767: [1581, 1609], +64768: [1581, 1610], +64769: [1580, 1609], +64770: [1580, 1610], +64771: [1582, 1609], +64772: [1582, 1610], +64773: [1589, 1609], +64774: [1589, 1610], +64775: [1590, 1609], +64776: [1590, 1610], +64777: [1588, 1580], +64778: [1588, 1581], +64779: [1588, 1582], +64780: [1588, 1605], +64781: [1588, 1585], +64782: [1587, 1585], +64783: [1589, 1585], +64784: [1590, 1585], +64785: [1591, 1609], +64786: [1591, 1610], +64787: [1593, 1609], +64788: [1593, 1610], +64789: [1594, 1609], +64790: [1594, 1610], +64791: [1587, 1609], +64792: [1587, 1610], +64793: [1588, 1609], +64794: [1588, 1610], +64795: [1581, 1609], +64796: [1581, 1610], +64797: [1580, 1609], +64798: [1580, 1610], +64799: [1582, 1609], +64800: [1582, 1610], +64801: [1589, 1609], +64802: [1589, 1610], +64803: [1590, 1609], +64804: [1590, 1610], +64805: [1588, 1580], +64806: [1588, 1581], +64807: [1588, 1582], +64808: [1588, 1605], +64809: [1588, 1585], +64810: [1587, 1585], +64811: [1589, 1585], +64812: [1590, 1585], +64813: [1588, 1580], +64814: [1588, 1581], +64815: [1588, 1582], +64816: [1588, 1605], +64817: [1587, 1607], +64818: [1588, 1607], +64819: [1591, 1605], +64820: [1587, 1580], +64821: [1587, 1581], +64822: [1587, 1582], +64823: [1588, 1580], +64824: [1588, 1581], +64825: [1588, 1582], +64826: [1591, 1605], +64827: [1592, 1605], +64828: [1575, 1611], +64829: [1575, 1611], +64848: [1578, 1580, 1605], +64849: [1578, 1581, 1580], +64850: [1578, 1581, 1580], +64851: [1578, 1581, 1605], +64852: [1578, 1582, 1605], +64853: [1578, 1605, 1580], +64854: [1578, 1605, 1581], +64855: [1578, 1605, 1582], +64856: [1580, 1605, 1581], +64857: [1580, 1605, 1581], +64858: [1581, 1605, 1610], +64859: [1581, 1605, 1609], +64860: [1587, 1581, 1580], +64861: [1587, 1580, 1581], +64862: [1587, 1580, 1609], +64863: [1587, 1605, 1581], +64864: [1587, 1605, 1581], +64865: [1587, 1605, 1580], +64866: [1587, 1605, 1605], +64867: [1587, 1605, 1605], +64868: [1589, 1581, 1581], +64869: [1589, 1581, 1581], +64870: [1589, 1605, 1605], +64871: [1588, 1581, 1605], +64872: [1588, 1581, 1605], +64873: [1588, 1580, 1610], +64874: [1588, 1605, 1582], +64875: [1588, 1605, 1582], +64876: [1588, 1605, 1605], +64877: [1588, 1605, 1605], +64878: [1590, 1581, 1609], +64879: [1590, 1582, 1605], +64880: [1590, 1582, 1605], +64881: [1591, 1605, 1581], +64882: [1591, 1605, 1581], +64883: [1591, 1605, 1605], +64884: [1591, 1605, 1610], +64885: [1593, 1580, 1605], +64886: [1593, 1605, 1605], +64887: [1593, 1605, 1605], +64888: [1593, 1605, 1609], +64889: [1594, 1605, 1605], +64890: [1594, 1605, 1610], +64891: [1594, 1605, 1609], +64892: [1601, 1582, 1605], +64893: [1601, 1582, 1605], +64894: [1602, 1605, 1581], +64895: [1602, 1605, 1605], +64896: [1604, 1581, 1605], +64897: [1604, 1581, 1610], +64898: [1604, 1581, 1609], +64899: [1604, 1580, 1580], +64900: [1604, 1580, 1580], +64901: [1604, 1582, 1605], +64902: [1604, 1582, 1605], +64903: [1604, 1605, 1581], +64904: [1604, 1605, 1581], +64905: [1605, 1581, 1580], +64906: [1605, 1581, 1605], +64907: [1605, 1581, 1610], +64908: [1605, 1580, 1581], +64909: [1605, 1580, 1605], +64910: [1605, 1582, 1580], +64911: [1605, 1582, 1605], +64914: [1605, 1580, 1582], +64915: [1607, 1605, 1580], +64916: [1607, 1605, 1605], +64917: [1606, 1581, 1605], +64918: [1606, 1581, 1609], +64919: [1606, 1580, 1605], +64920: [1606, 1580, 1605], +64921: [1606, 1580, 1609], +64922: [1606, 1605, 1610], +64923: [1606, 1605, 1609], +64924: [1610, 1605, 1605], +64925: [1610, 1605, 1605], +64926: [1576, 1582, 1610], +64927: [1578, 1580, 1610], +64928: [1578, 1580, 1609], +64929: [1578, 1582, 1610], +64930: [1578, 1582, 1609], +64931: [1578, 1605, 1610], +64932: [1578, 1605, 1609], +64933: [1580, 1605, 1610], +64934: [1580, 1581, 1609], +64935: [1580, 1605, 1609], +64936: [1587, 1582, 1609], +64937: [1589, 1581, 1610], +64938: [1588, 1581, 1610], +64939: [1590, 1581, 1610], +64940: [1604, 1580, 1610], +64941: [1604, 1605, 1610], +64942: [1610, 1581, 1610], +64943: [1610, 1580, 1610], +64944: [1610, 1605, 1610], +64945: [1605, 1605, 1610], +64946: [1602, 1605, 1610], +64947: [1606, 1581, 1610], +64948: [1602, 1605, 1581], +64949: [1604, 1581, 1605], +64950: [1593, 1605, 1610], +64951: [1603, 1605, 1610], +64952: [1606, 1580, 1581], +64953: [1605, 1582, 1610], +64954: [1604, 1580, 1605], +64955: [1603, 1605, 1605], +64956: [1604, 1580, 1605], +64957: [1606, 1580, 1581], +64958: [1580, 1581, 1610], +64959: [1581, 1580, 1610], +64960: [1605, 1580, 1610], +64961: [1601, 1605, 1610], +64962: [1576, 1581, 1610], +64963: [1603, 1605, 1605], +64964: [1593, 1580, 1605], +64965: [1589, 1605, 1605], +64966: [1587, 1582, 1610], +64967: [1606, 1580, 1610], +65008: [1589, 1604, 1746], +65009: [1602, 1604, 1746], +65010: [1575, 1604, 1604, 1607], +65011: [1575, 1603, 1576, 1585], +65012: [1605, 1581, 1605, 1583], +65013: [1589, 1604, 1593, 1605], +65014: [1585, 1587, 1608, 1604], +65015: [1593, 1604, 1610, 1607], +65016: [1608, 1587, 1604, 1605], +65017: [1589, 1604, 1609], +65018: [1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605], +65019: [1580, 1604, 32, 1580, 1604, 1575, 1604, 1607], +65020: [1585, 1740, 1575, 1604], +65072: [46, 46], +65073: [8212], +65074: [8211], +65075: [95], +65076: [95], +65077: [40], +65078: [41], +65079: [123], +65080: [125], +65081: [12308], +65082: [12309], +65083: [12304], +65084: [12305], +65085: [12298], +65086: [12299], +65087: [12296], +65088: [12297], +65089: [12300], +65090: [12301], +65091: [12302], +65092: [12303], +65097: [32, 773], +65098: [32, 773], +65099: [32, 773], +65100: [32, 773], +65101: [95], +65102: [95], +65103: [95], +65104: [44], +65105: [12289], +65106: [46], +65108: [59], +65109: [58], +65110: [63], +65111: [33], +65112: [8212], +65113: [40], +65114: [41], +65115: [123], +65116: [125], +65117: [12308], +65118: [12309], +65119: [35], +65120: [38], +65121: [42], +65122: [43], +65123: [45], +65124: [60], +65125: [62], +65126: [61], +65128: [92], +65129: [36], +65130: [37], +65131: [64], +65136: [32, 1611], +65137: [1600, 1611], +65138: [32, 1612], +65140: [32, 1613], +65142: [32, 1614], +65143: [1600, 1614], +65144: [32, 1615], +65145: [1600, 1615], +65146: [32, 1616], +65147: [1600, 1616], +65148: [32, 1617], +65149: [1600, 1617], +65150: [32, 1618], +65151: [1600, 1618], +65152: [1569], +65153: [1575, 1619], +65154: [1575, 1619], +65155: [1575, 1620], +65156: [1575, 1620], +65157: [1608, 1620], +65158: [1608, 1620], +65159: [1575, 1621], +65160: [1575, 1621], +65161: [1610, 1620], +65162: [1610, 1620], +65163: [1610, 1620], +65164: [1610, 1620], +65165: [1575], +65166: [1575], +65167: [1576], +65168: [1576], +65169: [1576], +65170: [1576], +65171: [1577], +65172: [1577], +65173: [1578], +65174: [1578], +65175: [1578], +65176: [1578], +65177: [1579], +65178: [1579], +65179: [1579], +65180: [1579], +65181: [1580], +65182: [1580], +65183: [1580], +65184: [1580], +65185: [1581], +65186: [1581], +65187: [1581], +65188: [1581], +65189: [1582], +65190: [1582], +65191: [1582], +65192: [1582], +65193: [1583], +65194: [1583], +65195: [1584], +65196: [1584], +65197: [1585], +65198: [1585], +65199: [1586], +65200: [1586], +65201: [1587], +65202: [1587], +65203: [1587], +65204: [1587], +65205: [1588], +65206: [1588], +65207: [1588], +65208: [1588], +65209: [1589], +65210: [1589], +65211: [1589], +65212: [1589], +65213: [1590], +65214: [1590], +65215: [1590], +65216: [1590], +65217: [1591], +65218: [1591], +65219: [1591], +65220: [1591], +65221: [1592], +65222: [1592], +65223: [1592], +65224: [1592], +65225: [1593], +65226: [1593], +65227: [1593], +65228: [1593], +65229: [1594], +65230: [1594], +65231: [1594], +65232: [1594], +65233: [1601], +65234: [1601], +65235: [1601], +65236: [1601], +65237: [1602], +65238: [1602], +65239: [1602], +65240: [1602], +65241: [1603], +65242: [1603], +65243: [1603], +65244: [1603], +65245: [1604], +65246: [1604], +65247: [1604], +65248: [1604], +65249: [1605], +65250: [1605], +65251: [1605], +65252: [1605], +65253: [1606], +65254: [1606], +65255: [1606], +65256: [1606], +65257: [1607], +65258: [1607], +65259: [1607], +65260: [1607], +65261: [1608], +65262: [1608], +65263: [1609], +65264: [1609], +65265: [1610], +65266: [1610], +65267: [1610], +65268: [1610], +65269: [1604, 1575, 1619], +65270: [1604, 1575, 1619], +65271: [1604, 1575, 1620], +65272: [1604, 1575, 1620], +65273: [1604, 1575, 1621], +65274: [1604, 1575, 1621], +65275: [1604, 1575], +65276: [1604, 1575], +65281: [33], +65282: [34], +65283: [35], +65284: [36], +65285: [37], +65286: [38], +65287: [39], +65288: [40], +65289: [41], +65290: [42], +65291: [43], +65292: [44], +65293: [45], +65294: [46], +65295: [47], +65296: [48], +65297: [49], +65298: [50], +65299: [51], +65300: [52], +65301: [53], +65302: [54], +65303: [55], +65304: [56], +65305: [57], +65306: [58], +65307: [59], +65308: [60], +65309: [61], +65310: [62], +65311: [63], +65312: [64], +65313: [65], +65314: [66], +65315: [67], +65316: [68], +65317: [69], +65318: [70], +65319: [71], +65320: [72], +65321: [73], +65322: [74], +65323: [75], +65324: [76], +65325: [77], +65326: [78], +65327: [79], +65328: [80], +65329: [81], +65330: [82], +65331: [83], +65332: [84], +65333: [85], +65334: [86], +65335: [87], +65336: [88], +65337: [89], +65338: [90], +65339: [91], +65340: [92], +65341: [93], +65342: [94], +65343: [95], +65344: [96], +65345: [97], +65346: [98], +65347: [99], +65348: [100], +65349: [101], +65350: [102], +65351: [103], +65352: [104], +65353: [105], +65354: [106], +65355: [107], +65356: [108], +65357: [109], +65358: [110], +65359: [111], +65360: [112], +65361: [113], +65362: [114], +65363: [115], +65364: [116], +65365: [117], +65366: [118], +65367: [119], +65368: [120], +65369: [121], +65370: [122], +65371: [123], +65372: [124], +65373: [125], +65374: [126], +65375: [10629], +65376: [10630], +65377: [12290], +65378: [12300], +65379: [12301], +65380: [12289], +65381: [12539], +65382: [12530], +65383: [12449], +65384: [12451], +65385: [12453], +65386: [12455], +65387: [12457], +65388: [12515], +65389: [12517], +65390: [12519], +65391: [12483], +65392: [12540], +65393: [12450], +65394: [12452], +65395: [12454], +65396: [12456], +65397: [12458], +65398: [12459], +65399: [12461], +65400: [12463], +65401: [12465], +65402: [12467], +65403: [12469], +65404: [12471], +65405: [12473], +65406: [12475], +65407: [12477], +65408: [12479], +65409: [12481], +65410: [12484], +65411: [12486], +65412: [12488], +65413: [12490], +65414: [12491], +65415: [12492], +65416: [12493], +65417: [12494], +65418: [12495], +65419: [12498], +65420: [12501], +65421: [12504], +65422: [12507], +65423: [12510], +65424: [12511], +65425: [12512], +65426: [12513], +65427: [12514], +65428: [12516], +65429: [12518], +65430: [12520], +65431: [12521], +65432: [12522], +65433: [12523], +65434: [12524], +65435: [12525], +65436: [12527], +65437: [12531], +65438: [12441], +65439: [12442], +65440: [4448], +65441: [4352], +65442: [4353], +65443: [4522], +65444: [4354], +65445: [4524], +65446: [4525], +65447: [4355], +65448: [4356], +65449: [4357], +65450: [4528], +65451: [4529], +65452: [4530], +65453: [4531], +65454: [4532], +65455: [4533], +65456: [4378], +65457: [4358], +65458: [4359], +65459: [4360], +65460: [4385], +65461: [4361], +65462: [4362], +65463: [4363], +65464: [4364], +65465: [4365], +65466: [4366], +65467: [4367], +65468: [4368], +65469: [4369], +65470: [4370], +65474: [4449], +65475: [4450], +65476: [4451], +65477: [4452], +65478: [4453], +65479: [4454], +65482: [4455], +65483: [4456], +65484: [4457], +65485: [4458], +65486: [4459], +65487: [4460], +65490: [4461], +65491: [4462], +65492: [4463], +65493: [4464], +65494: [4465], +65495: [4466], +65498: [4467], +65499: [4468], +65500: [4469], +65504: [162], +65505: [163], +65506: [172], +65507: [32, 772], +65508: [166], +65509: [165], +65510: [8361], +65512: [9474], +65513: [8592], +65514: [8593], +65515: [8594], +65516: [8595], +65517: [9632], +65518: [9675], +119134: [119127, 119141], +119135: [119128, 119141], +119136: [119128, 119141, 119150], +119137: [119128, 119141, 119151], +119138: [119128, 119141, 119152], +119139: [119128, 119141, 119153], +119140: [119128, 119141, 119154], +119227: [119225, 119141], +119228: [119226, 119141], +119229: [119225, 119141, 119150], +119230: [119226, 119141, 119150], +119231: [119225, 119141, 119151], +119232: [119226, 119141, 119151], +119808: [65], +119809: [66], +119810: [67], +119811: [68], +119812: [69], +119813: [70], +119814: [71], +119815: [72], +119816: [73], +119817: [74], +119818: [75], +119819: [76], +119820: [77], +119821: [78], +119822: [79], +119823: [80], +119824: [81], +119825: [82], +119826: [83], +119827: [84], +119828: [85], +119829: [86], +119830: [87], +119831: [88], +119832: [89], +119833: [90], +119834: [97], +119835: [98], +119836: [99], +119837: [100], +119838: [101], +119839: [102], +119840: [103], +119841: [104], +119842: [105], +119843: [106], +119844: [107], +119845: [108], +119846: [109], +119847: [110], +119848: [111], +119849: [112], +119850: [113], +119851: [114], +119852: [115], +119853: [116], +119854: [117], +119855: [118], +119856: [119], +119857: [120], +119858: [121], +119859: [122], +119860: [65], +119861: [66], +119862: [67], +119863: [68], +119864: [69], +119865: [70], +119866: [71], +119867: [72], +119868: [73], +119869: [74], +119870: [75], +119871: [76], +119872: [77], +119873: [78], +119874: [79], +119875: [80], +119876: [81], +119877: [82], +119878: [83], +119879: [84], +119880: [85], +119881: [86], +119882: [87], +119883: [88], +119884: [89], +119885: [90], +119886: [97], +119887: [98], +119888: [99], +119889: [100], +119890: [101], +119891: [102], +119892: [103], +119894: [105], +119895: [106], +119896: [107], +119897: [108], +119898: [109], +119899: [110], +119900: [111], +119901: [112], +119902: [113], +119903: [114], +119904: [115], +119905: [116], +119906: [117], +119907: [118], +119908: [119], +119909: [120], +119910: [121], +119911: [122], +119912: [65], +119913: [66], +119914: [67], +119915: [68], +119916: [69], +119917: [70], +119918: [71], +119919: [72], +119920: [73], +119921: [74], +119922: [75], +119923: [76], +119924: [77], +119925: [78], +119926: [79], +119927: [80], +119928: [81], +119929: [82], +119930: [83], +119931: [84], +119932: [85], +119933: [86], +119934: [87], +119935: [88], +119936: [89], +119937: [90], +119938: [97], +119939: [98], +119940: [99], +119941: [100], +119942: [101], +119943: [102], +119944: [103], +119945: [104], +119946: [105], +119947: [106], +119948: [107], +119949: [108], +119950: [109], +119951: [110], +119952: [111], +119953: [112], +119954: [113], +119955: [114], +119956: [115], +119957: [116], +119958: [117], +119959: [118], +119960: [119], +119961: [120], +119962: [121], +119963: [122], +119964: [65], +119966: [67], +119967: [68], +119970: [71], +119973: [74], +119974: [75], +119977: [78], +119978: [79], +119979: [80], +119980: [81], +119982: [83], +119983: [84], +119984: [85], +119985: [86], +119986: [87], +119987: [88], +119988: [89], +119989: [90], +119990: [97], +119991: [98], +119992: [99], +119993: [100], +119995: [102], +119997: [104], +119998: [105], +119999: [106], +120000: [107], +120002: [109], +120003: [110], +120005: [112], +120006: [113], +120007: [114], +120008: [115], +120009: [116], +120010: [117], +120011: [118], +120012: [119], +120013: [120], +120014: [121], +120015: [122], +120016: [65], +120017: [66], +120018: [67], +120019: [68], +120020: [69], +120021: [70], +120022: [71], +120023: [72], +120024: [73], +120025: [74], +120026: [75], +120027: [76], +120028: [77], +120029: [78], +120030: [79], +120031: [80], +120032: [81], +120033: [82], +120034: [83], +120035: [84], +120036: [85], +120037: [86], +120038: [87], +120039: [88], +120040: [89], +120041: [90], +120042: [97], +120043: [98], +120044: [99], +120045: [100], +120046: [101], +120047: [102], +120048: [103], +120049: [104], +120050: [105], +120051: [106], +120052: [107], +120053: [108], +120054: [109], +120055: [110], +120056: [111], +120057: [112], +120058: [113], +120059: [114], +120060: [115], +120061: [116], +120062: [117], +120063: [118], +120064: [119], +120065: [120], +120066: [121], +120067: [122], +120068: [65], +120069: [66], +120071: [68], +120072: [69], +120073: [70], +120074: [71], +120077: [74], +120078: [75], +120079: [76], +120080: [77], +120081: [78], +120082: [79], +120083: [80], +120084: [81], +120086: [83], +120087: [84], +120088: [85], +120089: [86], +120090: [87], +120091: [88], +120092: [89], +120094: [97], +120095: [98], +120096: [99], +120097: [100], +120098: [101], +120099: [102], +120100: [103], +120101: [104], +120102: [105], +120103: [106], +120104: [107], +120105: [108], +120106: [109], +120107: [110], +120108: [111], +120109: [112], +120110: [113], +120111: [114], +120112: [115], +120113: [116], +120114: [117], +120115: [118], +120116: [119], +120117: [120], +120118: [121], +120119: [122], +120120: [65], +120121: [66], +120123: [68], +120124: [69], +120125: [70], +120126: [71], +120128: [73], +120129: [74], +120130: [75], +120131: [76], +120132: [77], +120134: [79], +120138: [83], +120139: [84], +120140: [85], +120141: [86], +120142: [87], +120143: [88], +120144: [89], +120146: [97], +120147: [98], +120148: [99], +120149: [100], +120150: [101], +120151: [102], +120152: [103], +120153: [104], +120154: [105], +120155: [106], +120156: [107], +120157: [108], +120158: [109], +120159: [110], +120160: [111], +120161: [112], +120162: [113], +120163: [114], +120164: [115], +120165: [116], +120166: [117], +120167: [118], +120168: [119], +120169: [120], +120170: [121], +120171: [122], +120172: [65], +120173: [66], +120174: [67], +120175: [68], +120176: [69], +120177: [70], +120178: [71], +120179: [72], +120180: [73], +120181: [74], +120182: [75], +120183: [76], +120184: [77], +120185: [78], +120186: [79], +120187: [80], +120188: [81], +120189: [82], +120190: [83], +120191: [84], +120192: [85], +120193: [86], +120194: [87], +120195: [88], +120196: [89], +120197: [90], +120198: [97], +120199: [98], +120200: [99], +120201: [100], +120202: [101], +120203: [102], +120204: [103], +120205: [104], +120206: [105], +120207: [106], +120208: [107], +120209: [108], +120210: [109], +120211: [110], +120212: [111], +120213: [112], +120214: [113], +120215: [114], +120216: [115], +120217: [116], +120218: [117], +120219: [118], +120220: [119], +120221: [120], +120222: [121], +120223: [122], +120224: [65], +120225: [66], +120226: [67], +120227: [68], +120228: [69], +120229: [70], +120230: [71], +120231: [72], +120232: [73], +120233: [74], +120234: [75], +120235: [76], +120236: [77], +120237: [78], +120238: [79], +120239: [80], +120240: [81], +120241: [82], +120242: [83], +120243: [84], +120244: [85], +120245: [86], +120246: [87], +120247: [88], +120248: [89], +120249: [90], +120250: [97], +120251: [98], +120252: [99], +120253: [100], +120254: [101], +120255: [102], +120256: [103], +120257: [104], +120258: [105], +120259: [106], +120260: [107], +120261: [108], +120262: [109], +120263: [110], +120264: [111], +120265: [112], +120266: [113], +120267: [114], +120268: [115], +120269: [116], +120270: [117], +120271: [118], +120272: [119], +120273: [120], +120274: [121], +120275: [122], +120276: [65], +120277: [66], +120278: [67], +120279: [68], +120280: [69], +120281: [70], +120282: [71], +120283: [72], +120284: [73], +120285: [74], +120286: [75], +120287: [76], +120288: [77], +120289: [78], +120290: [79], +120291: [80], +120292: [81], +120293: [82], +120294: [83], +120295: [84], +120296: [85], +120297: [86], +120298: [87], +120299: [88], +120300: [89], +120301: [90], +120302: [97], +120303: [98], +120304: [99], +120305: [100], +120306: [101], +120307: [102], +120308: [103], +120309: [104], +120310: [105], +120311: [106], +120312: [107], +120313: [108], +120314: [109], +120315: [110], +120316: [111], +120317: [112], +120318: [113], +120319: [114], +120320: [115], +120321: [116], +120322: [117], +120323: [118], +120324: [119], +120325: [120], +120326: [121], +120327: [122], +120328: [65], +120329: [66], +120330: [67], +120331: [68], +120332: [69], +120333: [70], +120334: [71], +120335: [72], +120336: [73], +120337: [74], +120338: [75], +120339: [76], +120340: [77], +120341: [78], +120342: [79], +120343: [80], +120344: [81], +120345: [82], +120346: [83], +120347: [84], +120348: [85], +120349: [86], +120350: [87], +120351: [88], +120352: [89], +120353: [90], +120354: [97], +120355: [98], +120356: [99], +120357: [100], +120358: [101], +120359: [102], +120360: [103], +120361: [104], +120362: [105], +120363: [106], +120364: [107], +120365: [108], +120366: [109], +120367: [110], +120368: [111], +120369: [112], +120370: [113], +120371: [114], +120372: [115], +120373: [116], +120374: [117], +120375: [118], +120376: [119], +120377: [120], +120378: [121], +120379: [122], +120380: [65], +120381: [66], +120382: [67], +120383: [68], +120384: [69], +120385: [70], +120386: [71], +120387: [72], +120388: [73], +120389: [74], +120390: [75], +120391: [76], +120392: [77], +120393: [78], +120394: [79], +120395: [80], +120396: [81], +120397: [82], +120398: [83], +120399: [84], +120400: [85], +120401: [86], +120402: [87], +120403: [88], +120404: [89], +120405: [90], +120406: [97], +120407: [98], +120408: [99], +120409: [100], +120410: [101], +120411: [102], +120412: [103], +120413: [104], +120414: [105], +120415: [106], +120416: [107], +120417: [108], +120418: [109], +120419: [110], +120420: [111], +120421: [112], +120422: [113], +120423: [114], +120424: [115], +120425: [116], +120426: [117], +120427: [118], +120428: [119], +120429: [120], +120430: [121], +120431: [122], +120432: [65], +120433: [66], +120434: [67], +120435: [68], +120436: [69], +120437: [70], +120438: [71], +120439: [72], +120440: [73], +120441: [74], +120442: [75], +120443: [76], +120444: [77], +120445: [78], +120446: [79], +120447: [80], +120448: [81], +120449: [82], +120450: [83], +120451: [84], +120452: [85], +120453: [86], +120454: [87], +120455: [88], +120456: [89], +120457: [90], +120458: [97], +120459: [98], +120460: [99], +120461: [100], +120462: [101], +120463: [102], +120464: [103], +120465: [104], +120466: [105], +120467: [106], +120468: [107], +120469: [108], +120470: [109], +120471: [110], +120472: [111], +120473: [112], +120474: [113], +120475: [114], +120476: [115], +120477: [116], +120478: [117], +120479: [118], +120480: [119], +120481: [120], +120482: [121], +120483: [122], +120488: [913], +120489: [914], +120490: [915], +120491: [916], +120492: [917], +120493: [918], +120494: [919], +120495: [920], +120496: [921], +120497: [922], +120498: [923], +120499: [924], +120500: [925], +120501: [926], +120502: [927], +120503: [928], +120504: [929], +120505: [920], +120506: [931], +120507: [932], +120508: [933], +120509: [934], +120510: [935], +120511: [936], +120512: [937], +120513: [8711], +120514: [945], +120515: [946], +120516: [947], +120517: [948], +120518: [949], +120519: [950], +120520: [951], +120521: [952], +120522: [953], +120523: [954], +120524: [955], +120525: [956], +120526: [957], +120527: [958], +120528: [959], +120529: [960], +120530: [961], +120531: [962], +120532: [963], +120533: [964], +120534: [965], +120535: [966], +120536: [967], +120537: [968], +120538: [969], +120539: [8706], +120540: [949], +120541: [952], +120542: [954], +120543: [966], +120544: [961], +120545: [960], +120546: [913], +120547: [914], +120548: [915], +120549: [916], +120550: [917], +120551: [918], +120552: [919], +120553: [920], +120554: [921], +120555: [922], +120556: [923], +120557: [924], +120558: [925], +120559: [926], +120560: [927], +120561: [928], +120562: [929], +120563: [920], +120564: [931], +120565: [932], +120566: [933], +120567: [934], +120568: [935], +120569: [936], +120570: [937], +120571: [8711], +120572: [945], +120573: [946], +120574: [947], +120575: [948], +120576: [949], +120577: [950], +120578: [951], +120579: [952], +120580: [953], +120581: [954], +120582: [955], +120583: [956], +120584: [957], +120585: [958], +120586: [959], +120587: [960], +120588: [961], +120589: [962], +120590: [963], +120591: [964], +120592: [965], +120593: [966], +120594: [967], +120595: [968], +120596: [969], +120597: [8706], +120598: [949], +120599: [952], +120600: [954], +120601: [966], +120602: [961], +120603: [960], +120604: [913], +120605: [914], +120606: [915], +120607: [916], +120608: [917], +120609: [918], +120610: [919], +120611: [920], +120612: [921], +120613: [922], +120614: [923], +120615: [924], +120616: [925], +120617: [926], +120618: [927], +120619: [928], +120620: [929], +120621: [920], +120622: [931], +120623: [932], +120624: [933], +120625: [934], +120626: [935], +120627: [936], +120628: [937], +120629: [8711], +120630: [945], +120631: [946], +120632: [947], +120633: [948], +120634: [949], +120635: [950], +120636: [951], +120637: [952], +120638: [953], +120639: [954], +120640: [955], +120641: [956], +120642: [957], +120643: [958], +120644: [959], +120645: [960], +120646: [961], +120647: [962], +120648: [963], +120649: [964], +120650: [965], +120651: [966], +120652: [967], +120653: [968], +120654: [969], +120655: [8706], +120656: [949], +120657: [952], +120658: [954], +120659: [966], +120660: [961], +120661: [960], +120662: [913], +120663: [914], +120664: [915], +120665: [916], +120666: [917], +120667: [918], +120668: [919], +120669: [920], +120670: [921], +120671: [922], +120672: [923], +120673: [924], +120674: [925], +120675: [926], +120676: [927], +120677: [928], +120678: [929], +120679: [920], +120680: [931], +120681: [932], +120682: [933], +120683: [934], +120684: [935], +120685: [936], +120686: [937], +120687: [8711], +120688: [945], +120689: [946], +120690: [947], +120691: [948], +120692: [949], +120693: [950], +120694: [951], +120695: [952], +120696: [953], +120697: [954], +120698: [955], +120699: [956], +120700: [957], +120701: [958], +120702: [959], +120703: [960], +120704: [961], +120705: [962], +120706: [963], +120707: [964], +120708: [965], +120709: [966], +120710: [967], +120711: [968], +120712: [969], +120713: [8706], +120714: [949], +120715: [952], +120716: [954], +120717: [966], +120718: [961], +120719: [960], +120720: [913], +120721: [914], +120722: [915], +120723: [916], +120724: [917], +120725: [918], +120726: [919], +120727: [920], +120728: [921], +120729: [922], +120730: [923], +120731: [924], +120732: [925], +120733: [926], +120734: [927], +120735: [928], +120736: [929], +120737: [920], +120738: [931], +120739: [932], +120740: [933], +120741: [934], +120742: [935], +120743: [936], +120744: [937], +120745: [8711], +120746: [945], +120747: [946], +120748: [947], +120749: [948], +120750: [949], +120751: [950], +120752: [951], +120753: [952], +120754: [953], +120755: [954], +120756: [955], +120757: [956], +120758: [957], +120759: [958], +120760: [959], +120761: [960], +120762: [961], +120763: [962], +120764: [963], +120765: [964], +120766: [965], +120767: [966], +120768: [967], +120769: [968], +120770: [969], +120771: [8706], +120772: [949], +120773: [952], +120774: [954], +120775: [966], +120776: [961], +120777: [960], +120782: [48], +120783: [49], +120784: [50], +120785: [51], +120786: [52], +120787: [53], +120788: [54], +120789: [55], +120790: [56], +120791: [57], +120792: [48], +120793: [49], +120794: [50], +120795: [51], +120796: [52], +120797: [53], +120798: [54], +120799: [55], +120800: [56], +120801: [57], +120802: [48], +120803: [49], +120804: [50], +120805: [51], +120806: [52], +120807: [53], +120808: [54], +120809: [55], +120810: [56], +120811: [57], +120812: [48], +120813: [49], +120814: [50], +120815: [51], +120816: [52], +120817: [53], +120818: [54], +120819: [55], +120820: [56], +120821: [57], +120822: [48], +120823: [49], +120824: [50], +120825: [51], +120826: [52], +120827: [53], +120828: [54], +120829: [55], +120830: [56], +120831: [57], +194560: [20029], +194561: [20024], +194562: [20033], +194563: [131362], +194564: [20320], +194565: [20398], +194566: [20411], +194567: [20482], +194568: [20602], +194569: [20633], +194570: [20711], +194571: [20687], +194572: [13470], +194573: [132666], +194574: [20813], +194575: [20820], +194576: [20836], +194577: [20855], +194578: [132380], +194579: [13497], +194580: [20839], +194581: [20877], +194582: [132427], +194583: [20887], +194584: [20900], +194585: [20172], +194586: [20908], +194587: [20917], +194588: [168415], +194589: [20981], +194590: [20995], +194591: [13535], +194592: [21051], +194593: [21062], +194594: [21106], +194595: [21111], +194596: [13589], +194597: [21191], +194598: [21193], +194599: [21220], +194600: [21242], +194601: [21253], +194602: [21254], +194603: [21271], +194604: [21321], +194605: [21329], +194606: [21338], +194607: [21363], +194608: [21373], +194609: [21375], +194610: [21375], +194611: [21375], +194612: [133676], +194613: [28784], +194614: [21450], +194615: [21471], +194616: [133987], +194617: [21483], +194618: [21489], +194619: [21510], +194620: [21662], +194621: [21560], +194622: [21576], +194623: [21608], +194624: [21666], +194625: [21750], +194626: [21776], +194627: [21843], +194628: [21859], +194629: [21892], +194630: [21892], +194631: [21913], +194632: [21931], +194633: [21939], +194634: [21954], +194635: [22294], +194636: [22022], +194637: [22295], +194638: [22097], +194639: [22132], +194640: [20999], +194641: [22766], +194642: [22478], +194643: [22516], +194644: [22541], +194645: [22411], +194646: [22578], +194647: [22577], +194648: [22700], +194649: [136420], +194650: [22770], +194651: [22775], +194652: [22790], +194653: [22810], +194654: [22818], +194655: [22882], +194656: [136872], +194657: [136938], +194658: [23020], +194659: [23067], +194660: [23079], +194661: [23000], +194662: [23142], +194663: [14062], +194664: [136042], +194665: [23304], +194666: [23358], +194667: [23358], +194668: [137672], +194669: [23491], +194670: [23512], +194671: [23527], +194672: [23539], +194673: [138008], +194674: [23551], +194675: [23558], +194676: [24371], +194677: [23586], +194678: [14209], +194679: [23648], +194680: [23662], +194681: [23744], +194682: [23693], +194683: [138724], +194684: [23875], +194685: [138726], +194686: [23918], +194687: [23915], +194688: [23932], +194689: [24033], +194690: [24034], +194691: [14383], +194692: [24061], +194693: [24104], +194694: [24125], +194695: [24169], +194696: [14434], +194697: [139651], +194698: [14460], +194699: [24240], +194700: [24243], +194701: [24246], +194702: [24266], +194703: [172946], +194704: [24318], +194705: [140081], +194706: [140081], +194707: [33281], +194708: [24354], +194709: [24354], +194710: [14535], +194711: [144056], +194712: [156122], +194713: [24418], +194714: [24427], +194715: [14563], +194716: [24474], +194717: [24525], +194718: [24535], +194719: [24569], +194720: [24705], +194721: [14650], +194722: [14620], +194723: [24724], +194724: [141012], +194725: [24775], +194726: [24904], +194727: [24908], +194728: [24910], +194729: [24908], +194730: [24954], +194731: [24974], +194732: [25010], +194733: [24996], +194734: [25007], +194735: [25054], +194736: [25074], +194737: [25078], +194738: [25104], +194739: [25115], +194740: [25181], +194741: [25265], +194742: [25300], +194743: [25424], +194744: [142092], +194745: [25405], +194746: [25340], +194747: [25448], +194748: [25475], +194749: [25572], +194750: [142321], +194751: [25634], +194752: [25541], +194753: [25513], +194754: [14894], +194755: [25705], +194756: [25726], +194757: [25757], +194758: [25719], +194759: [14956], +194760: [25935], +194761: [25964], +194762: [143370], +194763: [26083], +194764: [26360], +194765: [26185], +194766: [15129], +194767: [26257], +194768: [15112], +194769: [15076], +194770: [20882], +194771: [20885], +194772: [26368], +194773: [26268], +194774: [32941], +194775: [17369], +194776: [26391], +194777: [26395], +194778: [26401], +194779: [26462], +194780: [26451], +194781: [144323], +194782: [15177], +194783: [26618], +194784: [26501], +194785: [26706], +194786: [26757], +194787: [144493], +194788: [26766], +194789: [26655], +194790: [26900], +194791: [15261], +194792: [26946], +194793: [27043], +194794: [27114], +194795: [27304], +194796: [145059], +194797: [27355], +194798: [15384], +194799: [27425], +194800: [145575], +194801: [27476], +194802: [15438], +194803: [27506], +194804: [27551], +194805: [27578], +194806: [27579], +194807: [146061], +194808: [138507], +194809: [146170], +194810: [27726], +194811: [146620], +194812: [27839], +194813: [27853], +194814: [27751], +194815: [27926], +194816: [27966], +194817: [28023], +194818: [27969], +194819: [28009], +194820: [28024], +194821: [28037], +194822: [146718], +194823: [27956], +194824: [28207], +194825: [28270], +194826: [15667], +194827: [28363], +194828: [28359], +194829: [147153], +194830: [28153], +194831: [28526], +194832: [147294], +194833: [147342], +194834: [28614], +194835: [28729], +194836: [28702], +194837: [28699], +194838: [15766], +194839: [28746], +194840: [28797], +194841: [28791], +194842: [28845], +194843: [132389], +194844: [28997], +194845: [148067], +194846: [29084], +194847: [17323], +194848: [29224], +194849: [29237], +194850: [29264], +194851: [149000], +194852: [29312], +194853: [29333], +194854: [149301], +194855: [149524], +194856: [29562], +194857: [29579], +194858: [16044], +194859: [29605], +194860: [16056], +194861: [16056], +194862: [29767], +194863: [29788], +194864: [29809], +194865: [29829], +194866: [29898], +194867: [16155], +194868: [29988], +194869: [150582], +194870: [30014], +194871: [150674], +194872: [30064], +194873: [139679], +194874: [30224], +194875: [151457], +194876: [151480], +194877: [151620], +194878: [16380], +194879: [16392], +194880: [30452], +194881: [151795], +194882: [151794], +194883: [151833], +194884: [151859], +194885: [30494], +194886: [30495], +194887: [30495], +194888: [30538], +194889: [16441], +194890: [30603], +194891: [16454], +194892: [16534], +194893: [152605], +194894: [30798], +194895: [30860], +194896: [30924], +194897: [16611], +194898: [153126], +194899: [31062], +194900: [153242], +194901: [153285], +194902: [31119], +194903: [31211], +194904: [16687], +194905: [31296], +194906: [31306], +194907: [31311], +194908: [153980], +194909: [154279], +194910: [154279], +194911: [31406], +194912: [16898], +194913: [154539], +194914: [31686], +194915: [31689], +194916: [16935], +194917: [154752], +194918: [31954], +194919: [17056], +194920: [31976], +194921: [31971], +194922: [32000], +194923: [155526], +194924: [32099], +194925: [17153], +194926: [32199], +194927: [32258], +194928: [32325], +194929: [17204], +194930: [156200], +194931: [156231], +194932: [17241], +194933: [156377], +194934: [32634], +194935: [156478], +194936: [32661], +194937: [32762], +194938: [32773], +194939: [156890], +194940: [156963], +194941: [32864], +194942: [157096], +194943: [32880], +194944: [144223], +194945: [17365], +194946: [32946], +194947: [33027], +194948: [17419], +194949: [33086], +194950: [23221], +194951: [157607], +194952: [157621], +194953: [144275], +194954: [144284], +194955: [33281], +194956: [33284], +194957: [36766], +194958: [17515], +194959: [33425], +194960: [33419], +194961: [33437], +194962: [21171], +194963: [33457], +194964: [33459], +194965: [33469], +194966: [33510], +194967: [158524], +194968: [33509], +194969: [33565], +194970: [33635], +194971: [33709], +194972: [33571], +194973: [33725], +194974: [33767], +194975: [33879], +194976: [33619], +194977: [33738], +194978: [33740], +194979: [33756], +194980: [158774], +194981: [159083], +194982: [158933], +194983: [17707], +194984: [34033], +194985: [34035], +194986: [34070], +194987: [160714], +194988: [34148], +194989: [159532], +194990: [17757], +194991: [17761], +194992: [159665], +194993: [159954], +194994: [17771], +194995: [34384], +194996: [34396], +194997: [34407], +194998: [34409], +194999: [34473], +195000: [34440], +195001: [34574], +195002: [34530], +195003: [34681], +195004: [34600], +195005: [34667], +195006: [34694], +195007: [19799], +195008: [34785], +195009: [34817], +195010: [17913], +195011: [34912], +195012: [34915], +195013: [161383], +195014: [35031], +195015: [35038], +195016: [17973], +195017: [35066], +195018: [13499], +195019: [161966], +195020: [162150], +195021: [18110], +195022: [18119], +195023: [35488], +195024: [35565], +195025: [35722], +195026: [35925], +195027: [162984], +195028: [36011], +195029: [36033], +195030: [36123], +195031: [36215], +195032: [163631], +195033: [133124], +195034: [36299], +195035: [36284], +195036: [36336], +195037: [133342], +195038: [36564], +195039: [36664], +195040: [165330], +195041: [165357], +195042: [37012], +195043: [37105], +195044: [37137], +195045: [165678], +195046: [37147], +195047: [37432], +195048: [37591], +195049: [37592], +195050: [37500], +195051: [37881], +195052: [37909], +195053: [166906], +195054: [38283], +195055: [18837], +195056: [38327], +195057: [167287], +195058: [18918], +195059: [38595], +195060: [23986], +195061: [38691], +195062: [168261], +195063: [168474], +195064: [19054], +195065: [19062], +195066: [38880], +195067: [168970], +195068: [19122], +195069: [169110], +195070: [38923], +195071: [38923], +195072: [38953], +195073: [169398], +195074: [39138], +195075: [19251], +195076: [39209], +195077: [39335], +195078: [39362], +195079: [39422], +195080: [19406], +195081: [170800], +195082: [39698], +195083: [40000], +195084: [40189], +195085: [19662], +195086: [19693], +195087: [40295], +195088: [172238], +195089: [19704], +195090: [172293], +195091: [172558], +195092: [172689], +195093: [40635], +195094: [19798], +195095: [40697], +195096: [40702], +195097: [40709], +195098: [40719], +195099: [40726], +195100: [40763], +195101: [173568], } From ericvrp at codespeak.net Wed Jul 6 20:26:19 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Jul 2005 20:26:19 +0200 (CEST) Subject: [pypy-svn] r14355 - in pypy/dist/pypy: rpython translator/llvm2 translator/llvm2/test Message-ID: <20050706182619.8DF5F27B3D@code1.codespeak.net> Author: ericvrp Date: Wed Jul 6 20:26:18 2005 New Revision: 14355 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: implemented time methods clock,time and sleep Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Wed Jul 6 20:26:18 2005 @@ -2,6 +2,7 @@ information table about external functions for annotation/ rtyping and backends """ import os +import time import types class ExtFuncInfo: @@ -48,10 +49,22 @@ def ll_os_dup(fd): return 999 +def ll_time_time(): + return time.time() + +def ll_time_clock(): + return time.clock() + +def ll_time_sleep(t): + time.sleep(t) + # external function declarations -declare(os.open , int , ll_os_open , False, 'C:open' ) -declare(os.read , str , ll_os_read , False, 'C:read' ) -declare(os.write , int , ll_os_write , False, 'C:write' ) -declare(os.close , None, ll_os_close , False, 'C:close' ) -declare(os.getcwd, str , ll_os_getcwd, False, 'C:getcwd') -declare(os.dup , int , ll_os_dup , True , 'C:dup' ) +declare(os.open , int , ll_os_open , True ) #this is not annotatable actually, but llvm has an issue +declare(os.read , str , ll_os_read , True ) +declare(os.write , int , ll_os_write , True ) +declare(os.close , lambda a: None, ll_os_close , True , 'C:close' ) +declare(os.getcwd , str , ll_os_getcwd , True ) +declare(os.dup , int , ll_os_dup , True , 'C:dup' ) +declare(time.time , float , ll_time_time , True ) +declare(time.clock, float , ll_time_clock, True ) +declare(time.sleep, lambda a: None, ll_time_sleep, True ) Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Wed Jul 6 20:26:18 2005 @@ -1,7 +1,34 @@ extdeclarations = """; External declarations + +; XXX these int's might need to be long's on 64 bit CPU's :( + +declare int %time(int*) ;void* actually +declare int %clock() +declare void %sleep(int) + ; End of external declarations """ extfunctions = """; External functions (will be inlined by LLVM) + +double %ll_time_time() { + %v0 = call int %time(int* null) + %v1 = cast int %v0 to double + ret double %v1 +} + +double %ll_time_clock() { + %v0 = call int %clock() + %v1 = cast int %v0 to double + %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC + ret double %v2 +} + +void %ll_time_sleep__Float(double %f) { + %i = cast double %f to int + call void %sleep(int %i) + ret void +} + ; End of external functions """ Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 6 20:26:18 2005 @@ -58,6 +58,33 @@ f = compile_function(fn, [], view=False) assert os.path.sameopenfile(f(), fn()) +def test_external_function_ll_time_time(): + import time + def fn(): + return time.time() + f = compile_function(fn, [], view=False) + assert abs(f()-fn()) < 1.0 + +def test_external_function_ll_time_clock(): + import time + def fn(): + return time.clock() + f = compile_function(fn, [], view=False) + assert abs(f()-fn()) < 1.0 + +def test_external_function_ll_time_sleep(): + import time + def fn(t): + time.sleep(t) + return 666 + f = compile_function(fn, [float], view=False) + start_time = time.time() + delay_time = 2.0 + d = f(delay_time) + duration = time.time() - start_time + assert duration >= delay_time - 0.5 + assert duration <= delay_time + 0.5 + def test_GC_malloc(): if not use_boehm_gc: py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") From arigo at codespeak.net Wed Jul 6 20:28:04 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 20:28:04 +0200 (CEST) Subject: [pypy-svn] r14356 - pypy/dist/pypy/objspace/std Message-ID: <20050706182804.3590027B3D@code1.codespeak.net> Author: arigo Date: Wed Jul 6 20:28:02 2005 New Revision: 14356 Modified: pypy/dist/pypy/objspace/std/longtype.py Log: Annotator-guiding assert. This shows a real bug, btw. XXX find a way to extract digits out of a long independently of its concrete W_XxxObject class! Modified: pypy/dist/pypy/objspace/std/longtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/longtype.py (original) +++ pypy/dist/pypy/objspace/std/longtype.py Wed Jul 6 20:28:02 2005 @@ -32,6 +32,8 @@ if space.is_true(space.is_(w_longtype, space.w_long)): return w_obj if space.is_true(space.isinstance(w_obj, space.w_long)): + assert isinstance(w_obj, W_LongObject) # XXX this could fail! + # XXX find a way to do that even if w_obj is not a W_LongObject w_value = w_obj elif space.is_true(space.isinstance(w_obj, space.w_int)): intval = space.int_w(w_obj) From arigo at codespeak.net Wed Jul 6 20:30:17 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 20:30:17 +0200 (CEST) Subject: [pypy-svn] r14357 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050706183017.C741327B3D@code1.codespeak.net> Author: arigo Date: Wed Jul 6 20:30:17 2005 New Revision: 14357 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longtype.py Log: Merged last revision. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longtype.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/longtype.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/longtype.py Wed Jul 6 20:30:17 2005 @@ -32,6 +32,8 @@ if space.is_true(space.is_(w_longtype, space.w_long)): return w_obj if space.is_true(space.isinstance(w_obj, space.w_long)): + assert isinstance(w_obj, W_LongObject) # XXX this could fail! + # XXX find a way to do that even if w_obj is not a W_LongObject w_value = w_obj elif space.is_true(space.isinstance(w_obj, space.w_int)): intval = space.int_w(w_obj) From arigo at codespeak.net Wed Jul 6 20:43:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 20:43:54 +0200 (CEST) Subject: [pypy-svn] r14358 - pypy/dist/pypy/objspace/std Message-ID: <20050706184354.EC02627B3D@code1.codespeak.net> Author: arigo Date: Wed Jul 6 20:43:53 2005 New Revision: 14358 Modified: pypy/dist/pypy/objspace/std/strutil.py Log: Grumble. More annotator-friendly hacks. Needs to be refactored according to idea hinted to in the previous check-in. Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Wed Jul 6 20:43:53 2005 @@ -129,9 +129,11 @@ digit = p.next_digit() if digit == -1: if p.sign == -1: - return space.neg(w_result) - else: - return w_result + w_result = space.neg(w_result) + # XXX grumble + from pypy.objspace.std.longobject import W_LongObject + assert isinstance(w_result, W_LongObject) + return w_result w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) def break_up_float(s): From arigo at codespeak.net Wed Jul 6 20:45:04 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Jul 2005 20:45:04 +0200 (CEST) Subject: [pypy-svn] r14359 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050706184504.1D6BB27B42@code1.codespeak.net> Author: arigo Date: Wed Jul 6 20:45:03 2005 New Revision: 14359 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py Log: Ported change from the trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py Wed Jul 6 20:45:03 2005 @@ -129,9 +129,11 @@ digit = p.next_digit() if digit == -1: if p.sign == -1: - return space.neg(w_result) - else: - return w_result + w_result = space.neg(w_result) + # XXX grumble + from pypy.objspace.std.longobject import W_LongObject + assert isinstance(w_result, W_LongObject) + return w_result w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) def break_up_float(s): From tismer at codespeak.net Wed Jul 6 20:45:19 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 6 Jul 2005 20:45:19 +0200 (CEST) Subject: [pypy-svn] r14360 - pypy/dist/pypy/objspace/std Message-ID: <20050706184519.F019227B43@code1.codespeak.net> Author: tismer Date: Wed Jul 6 20:45:18 2005 New Revision: 14360 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: things seem to work quite nicely. allmost everything was generalized. still tracking down the last bug with special cases. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 6 20:45:18 2005 @@ -3,29 +3,39 @@ from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.floatobject import W_FloatObject from pypy.objspace.std.noneobject import W_NoneObject -from pypy.rpython.rarithmetic import intmask, r_uint, LONG_MASK +from pypy.rpython.rarithmetic import intmask, r_uint, r_ushort, r_ulong from pypy.rpython.rarithmetic import LONG_BIT import math +# for now, we use r_uint as a digit. +# we may later switch to r_ushort, when it is supported by rtyper etc. + +Digit = r_uint # works: r_ushort +Twodigits = r_uint +Stwodigits = int + # the following describe a plain digit -SHIFT = int(LONG_BIT // 2) #- 1 +SHIFT = (Twodigits.BITS // 2) - 1 MASK = int((1 << SHIFT) - 1) +# find the correct type for carry/borrow +if Digit.BITS - SHIFT > 0: + Carryadd = Digit +else: + Carryadd = Twodigits +Carrymul = Twodigits + # masks for normal signed integer SIGN_BIT = LONG_BIT-1 SIGN_MASK = r_uint(1) << SIGN_BIT NONSIGN_MASK = ~SIGN_MASK -# masks for half-word access -SHORT_BIT = LONG_BIT // 2 -SHORT_MASK = int((1 << SHORT_BIT) - 1) - # XXX some operations below return one of their input arguments # without checking that it's really of type long (and not a subclass). class W_LongObject(W_Object): - """This is a reimplementation of longs using a list of r_uints.""" + """This is a reimplementation of longs using a list of digits.""" # All functions that still rely on the underlying Python's longs are marked # with YYYYYY from pypy.objspace.std.longtype import long_typedef as typedef @@ -41,7 +51,7 @@ def longval(self): #YYYYYY l = 0 for d in self.digits[::-1]: - l = l << LONG_BIT + l = l << SHIFT l += long(d) return l * self.sign @@ -51,7 +61,7 @@ def _normalize(self): if len(self.digits) == 0: self.sign = 0 - self.digits = [r_uint(0)] + self.digits = [Digit(0)] return i = len(self.digits) - 1 while i != 0 and self.digits[i] == 0: @@ -60,41 +70,17 @@ if len(self.digits) == 1 and self.digits[0] == 0: self.sign = 0 - def _getshort(self, index): - a = self.digits[index // 2] - if index % 2 == 0: - return a & SHORT_MASK - else: - return a >> SHORT_BIT - - def _setshort(self, index, short): - a = self.digits[index // 2] - assert isinstance(short, r_uint) - # note that this is possibly one bit more than a digit - assert short & SHORT_MASK == short - if index % 2 == 0: - self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short - else: - self.digits[index // 2] = (a & SHORT_MASK) + (short << SHORT_BIT) - registerimplementation(W_LongObject) # bool-to-long def delegate_Bool2Long(w_bool): - return W_LongObject(w_bool.space, [r_uint(w_bool.boolval)], + return W_LongObject(w_bool.space, [Digit(w_bool.boolval)], int(w_bool.boolval)) # int-to-long delegation def delegate_Int2Long(w_intobj): - if w_intobj.intval < 0: - sign = -1 - elif w_intobj.intval > 0: - sign = 1 - else: - sign = 0 - digits = [r_uint(abs(w_intobj.intval))] - return W_LongObject(w_intobj.space, digits, sign) + return long__Int(w_intobj.space, w_intobj) # long-to-float delegation def delegate_Long2Float(w_longobj): @@ -118,20 +104,37 @@ def long__Int(space, w_intobj): if w_intobj.intval < 0: sign = -1 + ival = -w_intobj.intval elif w_intobj.intval > 0: sign = 1 + ival = w_intobj.intval else: - sign = 0 - return W_LongObject(space, [r_uint(abs(w_intobj.intval))], sign) + return W_LongObject(space, [Digit(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 + # needed. + t = r_uint(ival) + ndigits = 0 + while t: + ndigits += 1 + t >>= SHIFT + v = W_LongObject(space, [Digit(0)] * ndigits, sign) + t = r_uint(ival) + p = 0 + while t: + v.digits[p] = Digit(t & MASK) + t >>= SHIFT + p += 1 + return v def int__Long(space, w_value): - if len(w_value.digits) == 1: - if w_value.digits[0] & SIGN_MASK == 0: - return space.newint(int(w_value.digits[0]) * w_value.sign) - elif w_value.sign == -1 and w_value.digits[0] & NONSIGN_MASK == 0: - return space.newint(intmask(w_value.digits[0])) - #subtypes of long are converted to long! - return long__Long(space, w_value) + try: + x = _AsLong(w_value) + except OverflowError: + return long__Long(space, w_value) + else: + return space.newint(x) def float__Long(space, w_longobj): try: @@ -144,23 +147,22 @@ return _FromDouble(space, w_floatobj.floatval) def int_w__Long(space, w_value): - if len(w_value.digits) == 1: - if w_value.digits[0] & SIGN_MASK == 0: - return int(w_value.digits[0]) * w_value.sign - elif w_value.sign == -1 and w_value.digits[0] & NONSIGN_MASK == 0: - return intmask(w_value.digits[0]) - raise OperationError(space.w_OverflowError, - space.wrap("long int too large to convert to int")) + try: + return _AsLong(w_value) + except OverflowError: + raise OperationError(space.w_OverflowError, space.wrap( + "long int too large to convert to int")) + def uint_w__Long(space, w_value): if w_value.sign == -1: raise OperationError(space.w_ValueError, space.wrap( "cannot convert negative integer to unsigned int")) x = r_uint(0) - i = len(w_value.digits) * 2 - 1 + i = len(w_value.digits) - 1 while i >= 0: prev = x - x = (x << SHIFT) + w_value._getshort(i) + x = (x << SHIFT) + w_value.digits[i] if (x >> SHIFT) != prev: raise OperationError(space.w_OverflowError, space.wrap( "long int too large to convert to unsigned int")) @@ -298,7 +300,7 @@ if lz.sign == 0: raise OperationError(space.w_ValueError, space.wrap("pow() 3rd argument cannot be 0")) - result = W_LongObject(space, [r_uint(1)], 1) + result = W_LongObject(space, [Digit(1)], 1) if lw.sign == 0: if lz is not None: result = mod__Long_Long(space, result, lz) @@ -311,9 +313,9 @@ #Treat the most significant digit specially to reduce multiplications while i < len(lw.digits) - 1: j = 0 - m = r_uint(1) + m = Digit(1) di = lw.digits[i] - while j < LONG_BIT: + while j < SHIFT: if di & m: result = mul__Long_Long(space, result, temp) temp = mul__Long_Long(space, temp, temp) @@ -323,9 +325,9 @@ m = m << 1 j += 1 i += 1 - m = r_uint(1) << (LONG_BIT - 1) - highest_set_bit = LONG_BIT - j = LONG_BIT - 1 + m = Digit(1) << (SHIFT - 1) + highest_set_bit = SHIFT + j = SHIFT - 1 di = lw.digits[i] while j >= 0: if di & m: @@ -333,9 +335,9 @@ break m = m >> 1 j -= 1 - assert highest_set_bit != LONG_BIT, "long not normalized" + assert highest_set_bit != SHIFT, "long not normalized" j = 0 - m = r_uint(1) + m = Digit(1) while j <= highest_set_bit: if di & m: result = mul__Long_Long(space, result, temp) @@ -369,7 +371,7 @@ 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, [r_uint(1)], 1)) + w_lpp = add__Long_Long(space, w_long, W_LongObject(space, [Digit(1)], 1)) return neg__Long(space, w_lpp) def lshift__Long_Long(space, w_long1, w_long2): @@ -379,35 +381,39 @@ elif w_long2.sign == 0: return w_long1 try: - b = int_w__Long(space, w_long2) + shiftby = int_w__Long(space, w_long2) except OverflowError: # b too big raise OperationError(space.w_OverflowError, space.wrap("shift count too large")) - wordshift = b // LONG_BIT - remshift = r_uint(b) % LONG_BIT - oldsize = len(w_long1.digits) + + a = w_long1 + # wordshift, remshift = divmod(shiftby, SHIFT) + wordshift = shiftby // SHIFT + remshift = shiftby - wordshift * SHIFT + + oldsize = len(a.digits) newsize = oldsize + wordshift - if remshift != 0: + if remshift: newsize += 1 - w_result = W_LongObject(space, [r_uint(0)] * newsize, w_long1.sign) - rightshift = LONG_BIT - remshift - LOWER_MASK = (r_uint(1) << r_uint(rightshift)) - 1 - UPPER_MASK = ~LOWER_MASK - accum = r_uint(0) + z = W_LongObject(space, [Digit(0)] * newsize, a.sign) + # not sure if we will initialize things in the future? + for i in range(wordshift): + z.digits[i] = 0 + accum = Twodigits(0) i = wordshift j = 0 while j < oldsize: - digit = w_long1.digits[j] - w_result.digits[i] = (accum | (digit << remshift)) - accum = (digit & UPPER_MASK) >> rightshift + accum |= Twodigits(a.digits[j]) << remshift + z.digits[i] = Digit(accum & MASK) + accum >>= SHIFT i += 1 j += 1 if remshift: - w_result.digits[i] = accum + z.digits[newsize-1] = Digit(accum) else: assert not accum - w_result._normalize() - return w_result + z._normalize() + return z def rshift__Long_Long(space, w_long1, w_long2): if w_long2.sign < 0: @@ -420,31 +426,32 @@ w_a2 = rshift__Long_Long(space, w_a1, w_long2) return invert__Long(space, w_a2) try: - b = int_w__Long(space, w_long2) + shiftby = int_w__Long(space, w_long2) except OverflowError: # b too big # XXX maybe just return 0L instead? raise OperationError(space.w_OverflowError, space.wrap("shift count too large")) - wordshift = b // LONG_BIT - remshift = r_uint(b) % LONG_BIT - oldsize = len(w_long1.digits) - newsize = oldsize - wordshift + + a = w_long1 + wordshift = shiftby // SHIFT + newsize = len(a.digits) - wordshift if newsize <= 0: - return W_LongObject(space, [r_uint(0)], 0) - w_result = W_LongObject(space, [r_uint(0)] * newsize, 1) - leftshift = LONG_BIT - remshift - LOWER_MASK = (r_uint(1) << r_uint(remshift)) - 1 - UPPER_MASK = ~LOWER_MASK - accum = r_uint(0) - i = newsize - 1 - j = oldsize - 1 - while i >= 0: - digit = w_long1.digits[j] - w_result.digits[i] = (accum | (digit >> remshift)) - accum = (digit & LOWER_MASK) << leftshift - i -= 1 - j -= 1 - w_result._normalize() - return w_result + return W_LongObject(space, [Digit(0)], 0) + + loshift = shiftby % SHIFT + hishift = SHIFT - loshift + lomask = (Digit(1) << hishift) - 1 + himask = MASK ^ lomask + z = W_LongObject(space, [Digit(0)] * newsize, a.sign) + i = 0 + j = wordshift + while i < newsize: + z.digits[i] = (a.digits[j] >> loshift) & lomask + if i+1 < newsize: + z.digits[i] |= (a.digits[j+1] << hishift) & himask + i += 1 + j += 1 + z._normalize() + return z def and__Long_Long(space, w_long1, w_long2): return _bitwise(w_long1, '&', w_long2) @@ -517,45 +524,45 @@ digits = [] i = 0 while l: - digits.append(r_uint(l & LONG_MASK)) - l = l >> LONG_BIT + digits.append(Digit(l & MASK)) + l = l >> SHIFT if sign == 0: - digits = [r_uint(0)] + digits = [Digit(0)] return digits, sign def _x_add(a, b): """ Add the absolute values of two long integers. """ - size_a = len(a.digits) * 2 - size_b = len(b.digits) * 2 + size_a = len(a.digits) + size_b = len(b.digits) # Ensure a is the larger of the two: if size_a < size_b: a, b = b, a size_a, size_b = size_b, size_a - z = W_LongObject(a.space, [r_uint(0)] * (len(a.digits) + 1), 1) + z = W_LongObject(a.space, [Digit(0)] * (len(a.digits) + 1), 1) i = 0 - carry = r_uint(0) + carry = Carryadd(0) while i < size_b: - carry += a._getshort(i) + b._getshort(i) - z._setshort(i, carry & MASK) + carry += a.digits[i] + b.digits[i] + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 while i < size_a: - carry += a._getshort(i) - z._setshort(i, carry & MASK) + carry += a.digits[i] + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 - z._setshort(i, carry) + z.digits[i] = carry z._normalize() return z def _x_sub(a, b): """ Subtract the absolute values of two integers. """ - size_a = len(a.digits) * 2 - size_b = len(b.digits) * 2 + size_a = len(a.digits) + size_b = len(b.digits) sign = 1 - borrow = 0 + borrow = Digit(0) # Ensure a is the larger of the two: if size_a < size_b: @@ -565,28 +572,27 @@ elif size_a == size_b: # Find highest digit where a and b differ: i = size_a - 1 - while i >= 0 and a._getshort(i) == b._getshort(i): + while i >= 0 and a.digits[i] == b.digits[i]: i -= 1 if i < 0: - return W_LongObject(a.space, [r_uint(0)], 0) - if a._getshort(i) < b._getshort(i): + return W_LongObject(a.space, [Digit(0)], 0) + if a.digits[i] < b.digits[i]: sign = -1 a, b = b, a size_a = size_b = i+1 - digitpairs = (size_a + 1) // 2 - z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + z = W_LongObject(a.space, [Digit(0)] * size_a, 1) i = 0 while i < size_b: # The following assumes unsigned arithmetic # works modulo 2**N for some N>SHIFT. - borrow = a._getshort(i) - b._getshort(i) - borrow - z._setshort(i, borrow & MASK) + borrow = a.digits[i] - b.digits[i] - borrow + z.digits[i] = borrow & MASK borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 while i < size_a: - borrow = a._getshort(i) - borrow - z._setshort(i, borrow & MASK) + borrow = a.digits[i] - borrow + z.digits[i] = borrow & MASK borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 @@ -599,24 +605,24 @@ #Multiply the absolute values of two longs def _x_mul(a, b): - size_a = len(a.digits) * 2 - size_b = len(b.digits) * 2 - z = W_LongObject(a.space, [r_uint(0)] * ((size_a + size_b) // 2), 1) + size_a = len(a.digits) + size_b = len(b.digits) + z = W_LongObject(a.space, [Digit(0)] * (size_a + size_b), 1) i = 0 while i < size_a: - carry = r_uint(0) - f = a._getshort(i) + carry = Carrymul(0) + f = Twodigits(a.digits[i]) j = 0 while j < size_b: - carry += z._getshort(i + j) + b._getshort(j) * f - z._setshort(i + j, carry & MASK) + carry += z.digits[i + j] + b.digits[j] * f + z.digits[i + j] = carry & MASK carry = carry >> SHIFT j += 1 while carry != 0: assert i + j < size_a + size_b - carry += z._getshort(i + j) - z._setshort(i + j, carry & MASK) - carry = carry >> SHIFT + carry += z.digits[i + j] + z.digits[i + j] = carry & MASK + carry >>= SHIFT j += 1 i += 1 z._normalize() @@ -627,15 +633,15 @@ Divide long pin by non-zero digit n, storing quotient in pout, and returning the remainder. It's OK for pin == pout on entry. """ - rem = r_uint(0) + rem = Twodigits(0) assert n > 0 and n <= MASK if not size: - size = len(pin.digits) * 2 + size = len(pin.digits) size -= 1 while size >= 0: - rem = (rem << SHIFT) + pin._getshort(size) + rem = (rem << SHIFT) + pin.digits[size] hi = rem // n - pout._setshort(size, hi) + pout.digits[size] = hi rem -= hi * n size -= 1 return rem @@ -648,7 +654,7 @@ """ assert n > 0 and n <= MASK size = len(a.digits) - z = W_LongObject(a.space, [r_uint(0)] * size, 1) + z = W_LongObject(a.space, [Digit(0)] * size, 1) rem = _inplace_divrem1(z, a, n) z._normalize() return z, rem @@ -656,19 +662,16 @@ def _muladd1(a, n, extra): """Multiply by a single digit and add a single digit, ignoring the sign. """ - digitpairs = len(a.digits) - size_a = digitpairs * 2 - if a._getshort(size_a-1) == 0: - size_a -= 1 - z = W_LongObject(a.space, [r_uint(0)] * (digitpairs+1), 1) - carry = extra + size_a = len(a.digits) + z = W_LongObject(a.space, [Digit(0)] * (size_a+1), 1) + carry = Carrymul(extra) i = 0 while i < size_a: - carry += a._getshort(i) * n - z._setshort(i, carry & MASK) + carry += Twodigits(a.digits[i]) * n + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 - z._setshort(i, carry) + z.digits[i] = carry z._normalize() return z @@ -681,14 +684,17 @@ # be used recursively to implement longs of any size. class r_suint(object): - # we do not inherit from r_uint, because we only + # we do not inherit from Digit, because we only # support a few operations for our purpose + BITS = Twodigits.BITS + MASK = Twodigits.MASK + def __init__(self, value=0): if isinstance(value, r_suint): self.value = value.value self.sign = value.sign else: - self.value = r_uint(value) + self.value = Twodigits(value) self.sign = -(value < 0) def longval(self): @@ -728,7 +734,7 @@ def __irshift__(self, n): self.value >>= n if self.sign: - self.value += r_uint(LONG_MASK) << (LONG_BIT - n) + self.value += self.MASK << (self.BITS - n) return self def __rshift__(self, n): @@ -750,85 +756,89 @@ return self.value & mask def __eq__(self, other): - if not isinstance(other,r_suint): + if not isinstance(other, r_suint): other = r_suint(other) return self.sign == other.sign and self.value == other.value + def __ne__(self, other): + return not self == other + def _x_divrem(v1, w1): - size_w = len(w1.digits) * 2 - # hack for the moment: - # find where w1 is really nonzero - if w1._getshort(size_w-1) == 0: - size_w -= 1 - d = (MASK+1) // (w1._getshort(size_w-1) + 1) - v = _muladd1(v1, d, r_uint(0)) - w = _muladd1(w1, d, r_uint(0)) - size_v = len(v.digits) * 2 - if v._getshort(size_v-1) == 0: - size_v -= 1 - size_w = len(w.digits) * 2 - if w._getshort(size_w-1) == 0: - size_w -= 1 + size_w = len(w1.digits) + d = (MASK+1) // (w1.digits[size_w-1] + 1) + v = _muladd1(v1, d, Digit(0)) + w = _muladd1(w1, d, Digit(0)) + size_v = len(v.digits) + size_w = len(w.digits) assert size_v >= size_w and size_w > 1 # Assert checks by div() size_a = size_v - size_w + 1 - digitpairs = (size_a + 1) // 2 - a = W_LongObject(v.space, [r_uint(0)] * digitpairs, 1) + a = W_LongObject(v.space, [Digit(0)] * size_a, 1) j = size_v k = size_a - 1 while k >= 0: if j >= size_v: - vj = r_uint(0) + vj = Digit(0) else: - vj = v._getshort(j) + vj = v.digits[j] carry = r_suint(0) # note: this must hold two digits and a sign! - if vj == w._getshort(size_w-1): - q = r_uint(MASK) + if vj == w.digits[size_w-1]: + q = Twodigits(MASK) else: - q = ((vj << SHIFT) + v._getshort(j-1)) // w._getshort(size_w-1) + q = ((Twodigits(vj) << SHIFT) + v.digits[j-1]) // w.digits[size_w-1] # notabene! # this check needs a signed two digits result # or we get an overflow. - while (w._getshort(size_w-2) * q > + while (w.digits[size_w-2] * q > (( r_suint(vj << SHIFT) # this one dominates - + v._getshort(j-1) - - long(q) * long(w._getshort(size_w-1)) + + v.digits[j-1] + - long(q) * long(w.digits[size_w-1]) ) << SHIFT) - + v._getshort(j-2)): + + v.digits[j-2]): q -= 1 i = 0 while i < size_w and i+k < size_v: - z = w._getshort(i) * q + z = w.digits[i] * q zz = z >> SHIFT - carry += v._getshort(i+k) + (zz << SHIFT) + carry += v.digits[i+k] + (zz << SHIFT) carry -= z if hasattr(carry, 'value'): - v._setshort(i+k, r_uint(carry.value & MASK)) + v.digits[i+k] = Digit(carry.value & MASK) else: - v._setshort(i+k, r_uint(carry & MASK)) + v.digits[i+k] = Digit(carry & MASK) carry >>= SHIFT carry -= zz i += 1 if i+k < size_v: - carry += v._getshort(i+k) - v._setshort(i+k, r_uint(0)) + carry += v.digits[i+k] + v.digits[i+k] = Digit(0) if carry == 0: - a._setshort(k, q & MASK) + a.digits[k] = q & MASK + assert not q >> SHIFT else: - ##!!assert carry == -1 - a._setshort(k, (q-1) & MASK) + #assert carry == -1 + if carry != -1: + print 70*"*" + print "CARRY", carry + print "comparison:", carry == -1 + print hex(v1.longval()) + print hex(w1.longval()) + print 70*"*" + q -= 1 + a.digits[k] = q-1 & MASK + assert not q >> SHIFT carry = r_suint(0) i = 0 while i < size_w and i+k < size_v: - carry += v._getshort(i+k) + w._getshort(i) - v._setshort(i+k, r_uint(carry.value) & MASK) + carry += v.digits[i+k] + w.digits[i] + v.digits[i+k] = Digit(carry.value) & MASK carry >>= SHIFT i += 1 j -= 1 @@ -841,12 +851,8 @@ def _divrem(a, b): """ Long division with remainder, top-level routine """ - size_a = len(a.digits) * 2 - size_b = len(b.digits) * 2 - if a._getshort(size_a-1) == 0: - size_a -= 1 - if b._getshort(size_b-1) == 0: - size_b -= 1 + size_a = len(a.digits) + size_b = len(b.digits) if b.sign == 0: raise OperationError(a.space.w_ZeroDivisionError, @@ -854,13 +860,13 @@ if (size_a < size_b or (size_a == size_b and - a._getshort(size_a-1) < b._getshort(size_b-1))): + a.digits[size_a-1] < b.digits[size_b-1])): # |a| < |b| - z = W_LongObject(a.space, [r_uint(0)], 0) + z = W_LongObject(a.space, [Digit(0)], 0) rem = a return z, rem if size_b == 1: - z, urem = _divrem1(a, b._getshort(0)) + z, urem = _divrem1(a, b.digits[0]) rem = W_LongObject(a.space, [urem], int(urem != 0)) else: z, rem = _x_divrem(a, b) @@ -892,16 +898,14 @@ multiplier = float(1 << SHIFT) if v.sign == 0: return 0.0, 0 - i = len(v.digits) * 2 - 1 - if v._getshort(i) == 0: - i -= 1 + i = len(v.digits) - 1 sign = v.sign - x = float(v._getshort(i)) + x = float(v.digits[i]) nbitsneeded = NBITS_WANTED - 1 # Invariant: i Python digits remain unaccounted for. while i > 0 and nbitsneeded > 0: i -= 1 - x = x * multiplier + float(v._getshort(i)) + x = x * multiplier + float(v.digits[i]) nbitsneeded -= SHIFT # There are i digits we didn't shift in. Pretending they're all # zeroes, the true value is x * 2**(i*SHIFT). @@ -915,12 +919,12 @@ ##def ldexp(x, exp): ## assert type(x) is float ## lb1 = LONG_BIT - 1 -## multiplier = float(r_uint(1) << lb1) +## multiplier = float(Digit(1) << lb1) ## while exp >= lb1: ## x *= multiplier ## exp -= lb1 ## if exp: -## x *= float(r_uint(1) << exp) +## x *= float(Digit(1) << exp) ## return x # note that math.ldexp checks for overflows, @@ -973,14 +977,13 @@ dval = -dval frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 if expo <= 0: - return W_LongObject(space, [r_uint(0)], 0) + return W_LongObject(space, [Digit(0)], 0) ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result - digitpairs = (ndig + 1) // 2 - v = W_LongObject(space, [r_uint(0)] * digitpairs, 1) + v = W_LongObject(space, [Digit(0)] * ndig, 1) frac = math.ldexp(frac, (expo-1) % SHIFT + 1) for i in range(ndig-1, -1, -1): bits = int(frac) - v._setshort(i, r_uint(bits)) + v.digits[i] = Digit(bits) frac -= float(bits) frac = math.ldexp(frac, SHIFT) if neg: @@ -1007,7 +1010,7 @@ div, mod = _divrem(v, w) if mod.sign * w.sign == -1: mod = add__Long_Long(v.space, mod, w) - one = W_LongObject(v.space, [r_uint(1)], 1) + one = W_LongObject(v.space, [Digit(1)], 1) div = sub__Long_Long(v.space, div, one) return div, mod @@ -1018,9 +1021,7 @@ Return a string object. If base is 8 or 16, add the proper prefix '0' or '0x'. """ - size_a = len(a.digits) * 2 - if a._getshort(size_a-1) == 0: - size_a -= 1 + size_a = len(a.digits) assert base >= 2 and base <= 36 @@ -1046,7 +1047,7 @@ s[p] = '0' elif (base & (base - 1)) == 0: # JRH: special case for power-of-2 bases - accum = r_uint(0) + accum = Twodigits(0) accumbits = 0 # # of bits in accum basebits = 1 # # of bits in base-1 i = base @@ -1057,7 +1058,7 @@ basebits += 1 for i in range(size_a): - accum |= a._getshort(i) << accumbits + accum |= Twodigits(a.digits[i]) << accumbits accumbits += SHIFT assert accumbits >= basebits while 1: @@ -1084,25 +1085,24 @@ size = size_a pin = a # just for similarity to C source which uses the array # powbase <- largest power of base that fits in a digit. - powbase = base # powbase == base ** power + powbase = Digit(base) # powbase == base ** power power = 1 while 1: - newpow = powbase * r_uint(base) + newpow = powbase * Digit(base) if newpow >> SHIFT: # doesn't fit in a digit break powbase = newpow power += 1 # Get a scratch area for repeated division. - digitpairs = (size + 1) // 2 - scratch = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + scratch = W_LongObject(a.space, [Digit(0)] * size, 1) # Repeatedly divide by powbase. while 1: ntostore = power rem = _inplace_divrem1(scratch, pin, powbase, size) pin = scratch # no need to use a again - if pin._getshort(size - 1) == 0: + if pin.digits[size - 1] == 0: size -= 1 # Break rem into digits. @@ -1159,14 +1159,14 @@ if a.sign < 0: a = invert__Long(a.space, a) - maska = r_uint(MASK) + maska = Digit(MASK) else: - maska = r_uint(0) + maska = Digit(0) if b.sign < 0: b = invert__Long(b.space, b) - maskb = r_uint(MASK) + maskb = Digit(MASK) else: - maskb = r_uint(0) + maskb = Digit(0) negz = 0 if op == '^': @@ -1195,12 +1195,8 @@ # iff one of these cases applies, and mask will be non-0 for operands # whose length should be ignored. - size_a = len(a.digits) * 2 - if a._getshort(size_a - 1) == 0: - size_a -= 1 - size_b = len(b.digits) * 2 - if b._getshort(size_b - 1) == 0: - size_b -= 1 + size_a = len(a.digits) + size_b = len(b.digits) if op == '&': if maska: size_z = size_b @@ -1212,26 +1208,51 @@ else: size_z = max(size_a, size_b) - digitpairs = (size_z + 1) // 2 - z = W_LongObject(a.space, [r_uint(0)] * digitpairs, 1) + z = W_LongObject(a.space, [Digit(0)] * size_z, 1) for i in range(size_z): if i < size_a: - diga = a._getshort(i) ^ maska + diga = a.digits[i] ^ maska else: diga = maska if i < size_b: - digb = b._getshort(i) ^ maskb + digb = b.digits[i] ^ maskb else: digb = maskb if op == '&': - z._setshort(i, diga & digb) + z.digits[i] = diga & digb elif op == '|': - z._setshort(i, diga | digb) + z.digits[i] = diga | digb elif op == '^': - z._setshort(i, diga ^ digb) + z.digits[i] = diga ^ digb z._normalize() if negz == 0: return z return invert__Long(z.space, z) + +def _AsLong(v): + """ + Get an integer from a long int object. + Returns -1 and sets an error condition if overflow occurs. + """ + # This version by Tim Peters + i = len(v.digits) - 1 + sign = v.sign + if not sign: + return 0 + x = r_uint(0) + while i >= 0: + prev = x + x = (x << SHIFT) + v.digits[i] + if (x >> SHIFT) != prev: + raise OverflowError + i -= 1 + + # Haven't lost any bits, but if the sign bit is set we're in + # trouble *unless* this is the min negative number. So, + # trouble iff sign bit set && (positive || some bit set other + # than the sign bit). + if int(x) < 0 and (sign > 0 or (x << 1) != 0): + raise OverflowError + return intmask(int(x) * sign) From rxe at codespeak.net Wed Jul 6 22:09:43 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 6 Jul 2005 22:09:43 +0200 (CEST) Subject: [pypy-svn] r14361 - in pypy/dist/pypy: rpython translator/llvm2 translator/llvm2/test Message-ID: <20050706200943.303C527B3D@code1.codespeak.net> Author: rxe Date: Wed Jul 6 22:09:40 2005 New Revision: 14361 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (ericvrp, rxe) an initial stab at external functions in llvm. Added external func node which can translate simple cases of calling external functions. Provides some functionality for special cases. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Wed Jul 6 22:09:40 2005 @@ -14,7 +14,7 @@ self.backend_functiontemplate = backend_functiontemplate table = {} -def declare(func, annotation, ll_function, ll_annotable=True, backend_functiontemplate=None): +def declare(func, annotation, ll_function, ll_annotable=False, backend_functiontemplate=None): # annotation can be a function computing the annotation # or a simple python type from which an annotation will be constructed global table @@ -58,13 +58,15 @@ def ll_time_sleep(t): time.sleep(t) +nonefactory = lambda a: None + # external function declarations -declare(os.open , int , ll_os_open , True ) #this is not annotatable actually, but llvm has an issue -declare(os.read , str , ll_os_read , True ) -declare(os.write , int , ll_os_write , True ) -declare(os.close , lambda a: None, ll_os_close , True , 'C:close' ) -declare(os.getcwd , str , ll_os_getcwd , True ) -declare(os.dup , int , ll_os_dup , True , 'C:dup' ) -declare(time.time , float , ll_time_time , True ) -declare(time.clock, float , ll_time_clock, True ) -declare(time.sleep, lambda a: None, ll_time_sleep, True ) +declare(os.open , int , ll_os_open) +declare(os.read , str , ll_os_read) +declare(os.write , int , ll_os_write) +declare(os.close , nonefactory, ll_os_close) +declare(os.getcwd , str , ll_os_getcwd) +declare(os.dup , int , ll_os_dup) +declare(time.time , float , ll_time_time) +declare(time.clock, float , ll_time_clock) +declare(time.sleep, nonefactory, ll_time_sleep) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Wed Jul 6 22:09:40 2005 @@ -1,5 +1,5 @@ from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode +from pypy.translator.llvm2.funcnode import ExternalFuncNode, FuncNode, FuncTypeNode from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode @@ -86,10 +86,8 @@ type_ = lltype.typeOf(value) node = None if isinstance(type_, lltype.FuncType): - - if value._callable \ - and not hasattr(value, 'graph'): - log('EXTERNAL FUNCTION' + str(dir(value))) + if ((not hasattr(value, "graph")) or value.graph is None) and value._callable: + node = ExternalFuncNode(self, value) else: node = FuncNode(self, value) @@ -126,6 +124,7 @@ assert isinstance(ct, lltype.Ptr), "Preperation of non primitive and non pointer" value = const_or_var.value._obj + self.addpending(const_or_var, self.create_constant_node(value)) else: log.prepare(const_or_var, type(const_or_var)) Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Wed Jul 6 22:09:40 2005 @@ -1,4 +1,5 @@ -extdeclarations = """; External declarations +extdeclarations = """; External declarations + ; XXX these int's might need to be long's on 64 bit CPU's :( @@ -7,6 +8,7 @@ declare void %sleep(int) ; End of external declarations + """ extfunctions = """; External functions (will be inlined by LLVM) @@ -24,7 +26,7 @@ ret double %v2 } -void %ll_time_sleep__Float(double %f) { +void %ll_time_sleep(double %f) { %i = cast double %f to int call void %sleep(int %i) ret void Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Wed Jul 6 22:09:40 2005 @@ -32,8 +32,7 @@ decl = "%s type %s (%s)*" % (self.ref, returntype, ", ".join(inputargtypes)) codewriter.funcdef(self.ref, returntype, inputargtypes) - - + class FuncNode(LLVMNode): _issetup = False @@ -61,12 +60,16 @@ assert self.graph, "cannot traverse" traverse(visit, self.graph) self._issetup = True + # ______________________________________________________________________ # main entry points from genllvm def writedecl(self, codewriter): codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): + + # XXX Code checks for when the rpython extfunctable has set the annotable + # flag to True????? _callable = self.value._callable for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? if _callable is extfuncinfo.ll_function: @@ -153,6 +156,88 @@ else: codewriter.ret_void() + +class ExternalFuncNode(LLVMNode): + + fnmapping = { + "%ll_os_dup": "%dup", + "%ll_os_open": "%open", + "%ll_os_close": "%close", + #"%": ("int" "%open", "sbyte*", "int"), + #"%ll_os_write": ("int" "%write", "int", "sbyte*", "int"), + } + + ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep".split() + + def __init__(self, db, value): + self.db = db + self.value = value + self.ref = "%" + value._name + + def setup(self): + self._issetup = True + + def getdecl(self): + T = self.value._TYPE + args = [self.db.repr_arg_type(a) for a in T.ARGS] + decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), + self.ref, + ", ".join(args)) + return decl + + def getcdecl(self): + #XXX Mapping + T = self.value._TYPE + args = [self.db.repr_arg_type(a) for a in T.ARGS] + decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), + self.fnmapping[self.ref], + ", ".join(args)) + return decl + + # ______________________________________________________________________ + # main entry points from genllvm + def writedecl(self, codewriter): + codewriter.declare(self.getdecl()) + + if self.ref not in self.ignoreset: + codewriter.declare(self.getcdecl()) + + def writeimpl(self, codewriter): + if self.ref in self.ignoreset: + return + + T = self.value._TYPE + args = ["%s %%a%s" % (self.db.repr_arg_type(a), c) + for c, a in enumerate(T.ARGS)] + + decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), + self.ref, + ", ".join(args)) + + codewriter.openfunc(decl) + + # go thru and map argsXXX + argrefs = ["%%a%s" % c for c in range(len(T.ARGS))] + argtypes = [self.db.repr_arg_type(a) for a in T.ARGS] + + # get return type (mapped perhaps) + resulttype = self.db.repr_arg_type(T.RESULT) + + # get function name + fnname = self.fnmapping[self.ref] + + # call + + # map resulttype ??? XXX + if resulttype != "void": + codewriter.call("%res", resulttype, fnname, argrefs, argtypes) + codewriter.ret(resulttype, "%res") + else: + codewriter.call_void(fnname, argrefs, argtypes) + codewriter.ret_void() + + codewriter.closefunc() + class OpWriter(object): binary_operations = {'int_mul': 'mul', 'int_add': 'add', Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 6 22:09:40 2005 @@ -41,9 +41,21 @@ import os def fn(): return os.dup(0) - f = compile_function(fn, [], view=False) + f = compile_function(fn, []) assert os.path.sameopenfile(f(), fn()) +def test_external_file_fns(): + import os + def external_file_fns(intname, flags): + name = str(intname) + fd = os.open(name, flags) + #os.write(fd, name) + os.close(fd) + return fd + + f = compile_function(external_file_fns, [int, int]) + assert isinstance(f(1209319, 64), int) + def DONTtest_external_function_ll_os_getcmd(): import os def fn(): From rxe at codespeak.net Thu Jul 7 11:23:24 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 7 Jul 2005 11:23:24 +0200 (CEST) Subject: [pypy-svn] r14372 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707092324.7A0A627B3C@code1.codespeak.net> Author: rxe Date: Thu Jul 7 11:23:23 2005 New Revision: 14372 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Add some more operations and add a test to do some simple string rpython operations. Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 7 11:23:23 2005 @@ -161,13 +161,12 @@ fnmapping = { "%ll_os_dup": "%dup", - "%ll_os_open": "%open", "%ll_os_close": "%close", - #"%": ("int" "%open", "sbyte*", "int"), - #"%ll_os_write": ("int" "%write", "int", "sbyte*", "int"), + "%ll_os_open": "%open", } - ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep".split() + ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep " \ + "%ll_os_read %ll_os_write".split() def __init__(self, db, value): self.db = db @@ -226,10 +225,9 @@ # get function name fnname = self.fnmapping[self.ref] - # call - - # map resulttype ??? XXX + # call if resulttype != "void": + # map resulttype ??? XXX codewriter.call("%res", resulttype, fnname, argrefs, argtypes) codewriter.ret(resulttype, "%res") else: @@ -263,6 +261,13 @@ 'uint_ge': 'setge', 'uint_gt': 'setgt', + 'char_lt': 'setlt', + 'char_le': 'setle', + 'char_eq': 'seteq', + 'char_ne': 'setne', + 'char_ge': 'setge', + 'char_gt': 'setgt', + 'float_mul': 'mul', 'float_add': 'add', 'float_sub': 'sub', @@ -295,6 +300,14 @@ "0", self.db.repr_arg(op.args[0]), ) + + def bool_not(self, op): + self.codewriter.binaryop("xor", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "true") + def binaryop(self, op): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Thu Jul 7 11:23:23 2005 @@ -379,6 +379,20 @@ return ord(str(i)) f = compile_function(string_simple, [int], view=False) assert f(0) + +def test_string_simple_ops(): + 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 Xtest_string_getitem1(): l = "Hello, World" From arigo at codespeak.net Thu Jul 7 12:39:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 12:39:53 +0200 (CEST) Subject: [pypy-svn] r14374 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050707103953.4FD3027B3F@code1.codespeak.net> Author: arigo Date: Thu Jul 7 12:39:48 2005 New Revision: 14374 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/test/test_genc.py pypy/dist/pypy/translator/c/wrapper.py Log: - fixed a corner case where genc's gen_wrapper() would create more low-level helpers that would never be specialized. Test included. - fixed PyObject-to-Char conversion Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jul 7 12:39:48 2005 @@ -426,6 +426,7 @@ v_chars = llops.genop('getsubstruct', [v_result, cchars], resulttype=Ptr(STR.chars)) llops.gencapicall('PyString_ToLLCharArray', [v, v_chars]) + v_result = llops.convertvar(v_result, string_repr, r_to) return v_result class __extend__(pairtype(StringRepr, PyObjRepr)): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 7 12:39:48 2005 @@ -87,26 +87,27 @@ perform_normalizations(self.annotator) # new blocks can be created as a result of specialize_block(), so # we need to be careful about the loop here. - already_seen = {} + self.already_seen = {} - def specialize_more_blocks(): - while True: - # look for blocks not specialized yet - pending = [block for block in self.annotator.annotated - if block not in already_seen] - if not pending: - break - # specialize all blocks in the 'pending' list - for block in pending: - self.specialize_block(block) - already_seen[block] = True - # make sure all reprs so far have had their setup() called - self.call_all_setups() - - specialize_more_blocks() + self.specialize_more_blocks() self.exceptiondata.make_helpers(self) - specialize_more_blocks() # for the helpers just made + self.specialize_more_blocks() # for the helpers just made + + def specialize_more_blocks(self): + while True: + # look for blocks not specialized yet + pending = [block for block in self.annotator.annotated + if block not in self.already_seen] + if not pending: + break + # specialize all blocks in the 'pending' list + for block in pending: + self.specialize_block(block) + self.already_seen[block] = True + # make sure all reprs so far have had their setup() called + self.call_all_setups() + # re-raise the first TyperError caught if self.typererror: exc, value, tb = self.typererror self.typererror = None Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Thu Jul 7 12:39:48 2005 @@ -227,3 +227,22 @@ assert res == str(lst) mallocs, frees = module.malloc_counters() assert mallocs == frees + +def test_rstr(): + def fn(i): + return "hello"[i] + t = Translator(fn) + t.annotate([int]) + t.specialize() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(fn)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + res = f1(1) + assert res == 'e' + mallocs, frees = module.malloc_counters() + assert mallocs == frees Modified: pypy/dist/pypy/translator/c/wrapper.py ============================================================================== --- pypy/dist/pypy/translator/c/wrapper.py (original) +++ pypy/dist/pypy/translator/c/wrapper.py Thu Jul 7 12:39:48 2005 @@ -27,7 +27,7 @@ FUNCTYPE = typeOf(f).TO assert len(FUNCTYPE.ARGS) == nb_positional_args + vararg - newops = LowLevelOpList(None) + newops = LowLevelOpList(translator.rtyper) # "def wrapper(self, args, kwds)" vself = Variable('self') @@ -113,6 +113,11 @@ block.closeblock(Link([vresult], wgraph.returnblock)) checkgraph(wgraph) + if translator.rtyper is not None: + # the above convertvar()s may have created and annotated new helpers + # that need to be specialized now + translator.rtyper.specialize_more_blocks() + return functionptr(FuncType([PyObjPtr, PyObjPtr, PyObjPtr], From arigo at codespeak.net Thu Jul 7 12:40:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 12:40:15 +0200 (CEST) Subject: [pypy-svn] r14375 - pypy/dist/pypy/translator/goal Message-ID: <20050707104015.B4E8A27B3F@code1.codespeak.net> Author: arigo Date: Thu Jul 7 12:40:13 2005 New Revision: 14375 Modified: pypy/dist/pypy/translator/goal/query.py Log: print c --> return c. Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jul 7 12:40:13 2005 @@ -46,7 +46,7 @@ except Found: print prettycallable((None, f)) c += 1 - print c + return c class typerep(object): From arigo at codespeak.net Thu Jul 7 13:10:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 13:10:24 +0200 (CEST) Subject: [pypy-svn] r14376 - in pypy/dist/pypy/rpython: . test Message-ID: <20050707111024.D391227B3F@code1.codespeak.net> Author: arigo Date: Thu Jul 7 13:10:22 2005 New Revision: 14376 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: Fixed the low-level implementations of the external functions. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 7 13:10:22 2005 @@ -25,29 +25,35 @@ return bookkeeper.getbookkeeper().valueoftype(typ) table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable, backend_functiontemplate) -# low-level helpers representing the external functions -def ll_os_open(fname, mode): - return os.open(''.join(fname.chars), mode) +# utility conversion functions +def to_rstr(s): + from pypy.rpython import rstr + p = rstr.malloc(rstr.STR, len(s)) + for i in range(len(s)): + p.chars[i] = s[i] + return p + +def from_rstr(rs): + return ''.join(rs.chars) + +# dummy low-level implementations for the external functions +def ll_os_open(fname, flag, mode): + return os.open(from_rstr(fname), flag, mode) def ll_os_read(fd, n): - return os.read(fd, n) + return to_rstr(os.read(fd, n)) def ll_os_write(fd, astring): - return os.write(fd, astring) - + return os.write(fd, from_rstr(astring)) + def ll_os_close(fd): os.close(fd) def ll_os_getcwd(): - cwd = os.getcwd() - from pypy.rpython import rstr - p = rstr.malloc(rstr.STR, len(cwd)) - for i in range(len(cwd)): - p.chars[i] = cwd[i] - return p + return to_rstr(os.getcwd()) def ll_os_dup(fd): - return 999 + return os.dup(fd) def ll_time_time(): return time.time() @@ -58,7 +64,8 @@ def ll_time_sleep(t): time.sleep(t) -nonefactory = lambda a: None + +nonefactory = lambda *args: None # external function declarations declare(os.open , int , ll_os_open) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Thu Jul 7 13:10:22 2005 @@ -88,10 +88,10 @@ def fn(fd): return os.dup(fd) res = interpret(fn, [0]) - #try: - # os.close(res) - #except OSError: - # pass + try: + os.close(res) + except OSError: + pass count = 0 from pypy.rpython import extfunctable for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn): @@ -104,7 +104,7 @@ tmpdir = str(udir.udir.join("os_open_test")) import os def wr_open(fname): - return os.open(fname, os.O_WRONLY|os.O_CREAT) + return os.open(fname, os.O_WRONLY|os.O_CREAT, 0777) def f(): return wr_open(tmpdir) res = interpret(f, []) From quest at codespeak.net Thu Jul 7 15:05:26 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Thu, 7 Jul 2005 15:05:26 +0200 (CEST) Subject: [pypy-svn] r14377 - pypy/dist/pypy/annotation Message-ID: <20050707130526.98C8527B3C@code1.codespeak.net> Author: quest Date: Thu Jul 7 15:05:25 2005 New Revision: 14377 Modified: pypy/dist/pypy/annotation/policy.py Log: More legible error messages from annotation of specialize and override. Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Thu Jul 7 15:05:25 2005 @@ -38,7 +38,12 @@ try: specialize = getattr(pol, 'specialize__%s' % tag) except AttributeError: - raise AttributeError, "%s specialize tag found in user program but not defined in annotation policy %s" % (tag, pol) + raise AttributeError("%s specialize tag found in callable %r " + "(file %s:%d) but not defined in annotation " + "policy %s" % (tag, func.func_name, + func.func_code.co_filename, + func.func_code.co_firstlineno, + pol)) return specialize(bookkeeper, mod, spaceop, func, args, mono) @@ -49,7 +54,12 @@ try: override = getattr(pol, 'override__%s' % override_tag) except AttributeError: - raise AttributeError, "'override:%s' found in user program but not defined in annotation policy %s" % (override_tag, pol) + raise AttributeError("'override:%s' found in callable %r " + "(file %s:%d) but not defined in annotation " + "policy %s" % (override_tag, func.func_name, + func.func_code.co_filename, + func.func_code.co_firstlineno , + pol)) inputcells = bookkeeper.get_inputcells(func, args) r = override(*inputcells) From quest at codespeak.net Thu Jul 7 15:17:30 2005 From: quest at codespeak.net (quest at codespeak.net) Date: Thu, 7 Jul 2005 15:17:30 +0200 (CEST) Subject: [pypy-svn] r14379 - in pypy/dist/pypy/tool: . test Message-ID: <20050707131730.3FDFC27B40@code1.codespeak.net> Author: quest Date: Thu Jul 7 15:17:29 2005 New Revision: 14379 Added: pypy/dist/pypy/tool/run_translation.py pypy/dist/pypy/tool/test/slowtest_run_translation.py Log: Basic tool for testing translation goals. This is an intermediate checkin; checking result from test remains to be done (see pypy/translator/goal/translate_pypy.py:find_someobjects). Added: pypy/dist/pypy/tool/run_translation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/run_translation.py Thu Jul 7 15:17:29 2005 @@ -0,0 +1,62 @@ +import os +import sys +from py.path import svnwc + +transl_test = """ +import sys +module = __import__('pypy.translator.goal.%s', None, None, ['target']) +entry_point, arg_s = module.target() + +from pypy.translator.translator import Translator +from pypy.translator.goal.query import polluted + +t = Translator(entry_point) +a = t.annotate(arg_s) +a.simplify() + +print polluted(t) +""" + +def prepare(repository, wcdir, revision): + """ + Checks out the named revision into wcdir and returns an object + with metadata that can be fed to execute and cleanup. + """ + class ExecutionData: + def __init__(self, wcdir): + self.wcdir = wcdir + + # Make sure the base dir exists + if os.path.exists(wcdir): + raise RuntimeError("working directory already exists") + + # Checkout revision + wc = svnwc(wcdir) + wc.checkout(repository, rev=revision) + return ExecutionData(wcdir) + +def execute(goal, execdata): + """ + Tests annotation of supplied goal. Goal should be a string with an + importable name from pypy.translator.goal. + """ + if not os.path.exists(execdata.wcdir): + raise RuntimeError("Run prepare to get a working directory") + # Make sure imports are from checked out source + test_file_name = os.tmpnam() + test_file = open(test_file_name, "w") + test_file.write(transl_test % (goal,)) + test_file.close() + os.system("PYTHONPATH=%s python %s" % (execdata.wcdir, test_file_name)) + os.remove(test_file_name) + +def cleanup(execdata): + """ + Removes working directory named by execdata. + """ + for root, dirs, files in os.walk(execdata.wcdir, topdown=False): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + os.rmdir(execdata.wcdir) Added: pypy/dist/pypy/tool/test/slowtest_run_translation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/test/slowtest_run_translation.py Thu Jul 7 15:17:29 2005 @@ -0,0 +1,19 @@ +import os +from pypy.tool.run_translation import * + +repository = "http://codespeak.net/svn/pypy/dist" +tmpdir = os.tmpnam() +testfile = os.path.join(tmpdir, "pypy", "translator", "gencl.py") +testrev = 14373 + +class TestRunTranslation: + def test_prepare_cleanup(self): + execdata = prepare(repository, tmpdir, testrev) + assert os.path.exists(testfile) + cleanup(execdata) + assert not os.path.exists(tmpdir) + + def test_execute(self): + execdata = prepare(repository, tmpdir, testrev) + execute("targetpypymain", execdata) + From ericvrp at codespeak.net Thu Jul 7 15:48:21 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 15:48:21 +0200 (CEST) Subject: [pypy-svn] r14381 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707134821.22CB727B3C@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 15:48:19 2005 New Revision: 14381 Added: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py pypy/dist/pypy/translator/llvm2/test/test_gc.py Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (hpk, ericvrp): Added os.open,os.close test that uses some dirty charater to string conversions because PBC string are not working yet. Added ll_file_open llvm implementation that convert structstrings to sbyte*. Refactored tests into three seperate files. Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 15:48:19 2005 @@ -6,12 +6,37 @@ declare int %time(int*) ;void* actually declare int %clock() declare void %sleep(int) +declare int %open(sbyte*, int) +declare sbyte* %strncpy(sbyte*, sbyte*, int) + +%st.rpy_string.0 = type {int, {int, [0 x sbyte]}} ; End of external declarations """ -extfunctions = """; External functions (will be inlined by LLVM) +extfunctions = """; Helper function to convert LLVM <-> C types + +sbyte* %cast(%st.rpy_string.0* %structstring) { + %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr + %length = add int %reallength, 1 + %ulength = cast int %length to uint + %dest = malloc sbyte, uint %ulength ;XXX should actually call GC_malloc when available! + + %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 + %source1 = cast [0 x sbyte]* %source1ptr to sbyte* + %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) + + %zeropos1 = cast sbyte* %dest to int + %zeropos2 = add int %zeropos1, %reallength + %zerodest = cast int %zeropos2 to sbyte* + store sbyte 0, sbyte* %zerodest + + ret sbyte* %dest ;XXX alloca freed at end of function. this will crash! +} + +; Wrapper functions that call external (C) functions double %ll_time_time() { %v0 = call int %time(int* null) @@ -22,7 +47,8 @@ double %ll_time_clock() { %v0 = call int %clock() %v1 = cast int %v0 to double - %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC + ; XXX how to get at the proper division constant per platform? + %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC accrdoing to single unix spec ret double %v2 } @@ -32,5 +58,12 @@ ret void } +int %ll_os_open(%st.rpy_string.0* %structstring, int %mode) { + %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) + %fd = call int %open(sbyte* %dest, int %mode) + free sbyte* %dest + ret int %fd +} + ; End of external functions """ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 7 15:48:19 2005 @@ -162,11 +162,11 @@ fnmapping = { "%ll_os_dup": "%dup", "%ll_os_close": "%close", - "%ll_os_open": "%open", + #"%ll_os_open": "%open", } ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep " \ - "%ll_os_read %ll_os_write".split() + "%ll_os_read %ll_os_write %ll_os_open".split() def __init__(self, db, value): self.db = db Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 7 15:48:19 2005 @@ -12,14 +12,15 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void -from pypy.translator.backendoptimization import rename_extfunc_calls +#from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.extfunction import extdeclarations, extfunctions +from pypy.translator.translator import Translator function_count = {} def genllvm(translator): remove_void(translator) - rename_extfunc_calls(translator) + #rename_extfunc_calls(translator) func = translator.entrypoint db = Database(translator) @@ -88,4 +89,21 @@ except py.error.ENOENT: return False return True - + +def compile_module(function, annotate, view=False): + t = Translator(function) + a = t.annotate(annotate) + t.specialize() + a.simplify() + if view: + t.view() + return genllvm(t) + +def compile_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + return getattr(mod, function.func_name + "_wrapper") + +def compile_module_function(function, annotate, view=False): + mod = compile_module(function, annotate, view) + f = getattr(mod, function.func_name + "_wrapper") + return mod, f Added: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 7 15:48:19 2005 @@ -0,0 +1,66 @@ +from __future__ import division + +import sys +import py + +from pypy.tool.udir import udir +from pypy.translator.llvm2.genllvm import compile_function + +py.log.setconsumer("extfunc", py.log.STDOUT) +py.log.setconsumer("extfunc database prepare", None) + +def test_external_function_ll_os_dup(): + import os + def fn(): + return os.dup(0) + f = compile_function(fn, []) + assert os.path.sameopenfile(f(), fn()) + +def test_external_function_ll_time_time(): + import time + def fn(): + return time.time() + f = compile_function(fn, [], view=False) + assert abs(f()-fn()) < 10.0 + +def test_external_function_ll_time_clock(): + import time + def fn(): + return time.clock() + f = compile_function(fn, [], view=False) + assert abs(f()-fn()) < 10.0 + +def test_external_function_ll_time_sleep(): + import time + def fn(t): + time.sleep(t) + return 666 + f = compile_function(fn, [float], view=False) + start_time = time.time() + delay_time = 2.0 + d = f(delay_time) + duration = time.time() - start_time + assert duration >= delay_time - 0.5 + assert duration <= delay_time + 0.5 + +class TestOSLevelFunctions: + def setup_method(self, method): + path = udir.join("e") + self.path = path + self.pathints = map(ord, path) + +def test_os_file_ops_open_close(): + # the test is overly complicated because + # we don't have prebuilt string constants yet + import os + def openclose(a,b,c,d,e,f): + s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + fd = os.open(s, os.O_CREAT) + os.close(fd) + return fd + + path = '/tmp/b' + f = compile_function(openclose, [int] * len(path)) + os.unlink(path) + result = f(*map(ord, path)) + assert os.path.exists(path) Added: pypy/dist/pypy/translator/llvm2/test/test_gc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_gc.py Thu Jul 7 15:48:19 2005 @@ -0,0 +1,31 @@ +import sys +import py + +from pypy.translator.llvm2.genllvm import use_boehm_gc +from pypy.translator.llvm2.genllvm import compile_module_function + +py.log.setconsumer("test_gc", py.log.STDOUT) +py.log.setconsumer("test_gc database prepare", None) + +def test_GC_malloc(): + if not use_boehm_gc: + py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") + return + def tuple_getitem(n): + x = 666 + i = 0 + while i < n: + l = (1,2,i,4,5,6,7,8,9,10,11) + x += l[2] + i += 1 + return x + mod,f = compile_module_function(tuple_getitem, [int]) + n = 5000 + result = tuple_getitem(n) + assert f(n) == result + get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") + heap_size_start = get_heap_size() + for i in range(0,25): + assert f(n) == result + heap_size_inc = get_heap_size() - heap_size_start + assert heap_size_inc < 500000 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Thu Jul 7 15:48:19 2005 @@ -3,130 +3,19 @@ import sys import py -from pypy.translator.translator import Translator -from pypy.translator.llvm2.genllvm import genllvm -from pypy.translator.llvm2.genllvm import use_boehm_gc -from pypy.translator.llvm2.test import llvmsnippet -from pypy.objspace.flow.model import Constant, Variable - -from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rarithmetic import r_uint +from pypy.translator.llvm2.genllvm import compile_function py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) - -## def setup_module(mod): -## mod.llvm_found = is_on_path("llvm-as") - -def compile_module(function, annotate, view=False): - t = Translator(function) - a = t.annotate(annotate) - t.specialize() - a.simplify() - if view: - t.view() - return genllvm(t) - -def compile_function(function, annotate, view=False): - mod = compile_module(function, annotate, view) - return getattr(mod, function.func_name + "_wrapper") - -def compile_module_function(function, annotate, view=False): - mod = compile_module(function, annotate, view) - f = getattr(mod, function.func_name + "_wrapper") - return mod, f - -def test_external_function_ll_os_dup(): - import os - def fn(): - return os.dup(0) - f = compile_function(fn, []) - assert os.path.sameopenfile(f(), fn()) - -def test_external_file_fns(): - import os - def external_file_fns(intname, flags): - name = str(intname) - fd = os.open(name, flags) - #os.write(fd, name) - os.close(fd) - return fd - - f = compile_function(external_file_fns, [int, int]) - assert isinstance(f(1209319, 64), int) - -def DONTtest_external_function_ll_os_getcmd(): - import os - def fn(): - return os.getcwd() - f = compile_function(fn, [], view=True) - assert os.getcwd() == 'bla' - -def DONTtest_external_function_ll_os_open(): - import os - def fn(): - return os.open(0) - f = compile_function(fn, [], view=False) - assert os.path.sameopenfile(f(), fn()) - -def test_external_function_ll_time_time(): - import time - def fn(): - return time.time() - f = compile_function(fn, [], view=False) - assert abs(f()-fn()) < 1.0 - -def test_external_function_ll_time_clock(): - import time - def fn(): - return time.clock() - f = compile_function(fn, [], view=False) - assert abs(f()-fn()) < 1.0 - -def test_external_function_ll_time_sleep(): - import time - def fn(t): - time.sleep(t) - return 666 - f = compile_function(fn, [float], view=False) - start_time = time.time() - delay_time = 2.0 - d = f(delay_time) - duration = time.time() - start_time - assert duration >= delay_time - 0.5 - assert duration <= delay_time + 0.5 - -def test_GC_malloc(): - if not use_boehm_gc: - py.test.skip("test_GC_malloc skipped because Boehm collector library was not found") - return - def tuple_getitem(n): - x = 666 - i = 0 - while i < n: - l = (1,2,i,4,5,6,7,8,9,10,11) - x += l[2] - i += 1 - return x - mod,f = compile_module_function(tuple_getitem, [int]) - n = 5000 - result = tuple_getitem(n) - assert f(n) == result - get_heap_size = getattr(mod, "GC_get_heap_size_wrapper") - heap_size_start = get_heap_size() - for i in range(0,25): - assert f(n) == result - heap_size_inc = get_heap_size() - heap_size_start - assert heap_size_inc < 500000 - def test_return1(): def simple1(): return 1 f = compile_function(simple1, []) assert f() == 1 -def Xtest_simple_function_pointer(): +def DONTtest_simple_function_pointer(): def f1(x): return x + 1 def f2(x): @@ -316,7 +205,7 @@ assert f(-1) == 3 assert f(0) == 5 -def Xtest_simple_chars(): +def DONTtest_simple_chars(): def char_constant2(s): s = s + s + s return len(s + '.') @@ -394,14 +283,14 @@ assert f(5) == ord('5') + 2 -def Xtest_string_getitem1(): +def DONTtest_string_getitem1(): l = "Hello, World" def string_getitem1(i): return l[i] - f = compile_function(string_getitem1, [int], view=False) + f = compile_function(string_getitem1, [int], view=True) assert f(0) == ord("H") -def DONOT_test_string_getitem2(): +def DONTtest_string_getitem2(): def string_test(i): l = "Hello, World" return l[i] @@ -411,7 +300,7 @@ class TestException(Exception): pass -def DONOTtest_exception(): +def DONTtest_exception(): def raise_(i): if i: raise TestException() From arigo at codespeak.net Thu Jul 7 15:56:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 15:56:11 +0200 (CEST) Subject: [pypy-svn] r14383 - pypy/extradoc/sprintinfo Message-ID: <20050707135611.7632E27B3F@code1.codespeak.net> Author: arigo Date: Thu Jul 7 15:56:09 2005 New Revision: 14383 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: Removed things done. Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Thu Jul 7 15:56:09 2005 @@ -57,37 +57,6 @@ Translation tasks ------------------ -* currently remaining rtyper topics: - - - found to be missing (ale, arigo):: - - Builtins - -------- - - DONE: (arre, bert) implement int(string) and int(string, 16) - DONE: rclass: (easy) issubtype (use issubclass to generate - an example that has issubtype in the annotated flow graph) - - (strange)(delegating to backend?) sys.getrefcount - DONE: (medium) applevel sys module should not refer to - interplevel sys.getdefaultencoding - (generate c_api calls) os.path.exists - (generate c_api calls) os.path.isdir - - Overridden functions in PyPy - ---------------------------- - - (easy) override:ignore - (easy) override:instantiate - (hard, probably needs to be implemented at C/CPython level): - override:wrap_exception_cls - override:fake_object - override:cpy_compile - -* (partially DONE) convert each file that does - 'from ... import *' to use explicit imports (e.g. - from pypy.rpython import lltype and then use lltype.*) - * fix floats:: - translator/c/float_include.h should catch floating-point signals with a technique similar to CPython's. @@ -98,28 +67,9 @@ Move to Python 2.4.1 ----------------------- -subcoach: Armin -Arre, Anders +* revert 'bisect' module to the 2.3 version (or 2.5) -experiment in a branch with using Python 2.4 semantics -and the standard library - -* (DONE) use lib-python/2.4.1 instead of 2.3.4, review all - modified tests and library modules (good progress, we still need to - review ca. 1 modified test files) - -* (DONE) Merge 2.4.1 branch (blocked by parser/compiler being able - to process 2.4.1 files on top of CPython 2.3.4, Armin looks - into that) - -* DONE: semantic differences: comparison of recursive - data structures, more? - -* new required C-level modules: - - DONE: 'sets' - - (DONE except for one test) implement 'collections' module - - (probably) revert 'bisect' module to the 2.3 version (or 2.5) - - (probably) revert 'heapq' module to the 2.3 version (2.5) +* revert 'heapq' module to the 2.3 version (2.5) * check that test results page still works (and fix) after we merged 2.4.1 branch @@ -135,13 +85,6 @@ * (Christian, cfbolz) (medium) finish objspace/std/longobject.py. - (MOSTLY DONE) div implementation (christian, jacob) -* (Samuele, Eric) (hard, doc in - pypy/documentation/ext-functions-draft.txt) find a way - to generate c_api calls (including automated - conversions from ll-strings to c-like strings) - -> conceptually discussed, needs to be written - down and posted to pypy-dev (samuele/holger) - * fix Windows-related issues * '%'-formatting rounding errors ( '%.3f' % (2.999999,)) @@ -150,11 +93,6 @@ functions, etc. (Laura): there now is a program that generates the docstrings into the appropriate places but it needs prettification. -* (DONE) GC discussion in the middle of the sprint - (kickoff Carl Friedrich with Armin/Samuele) - -* DONE: (should start sunday) _sre module reimplementation kickoff - Rewriting important C functionality in Python -------------------------------------------------- @@ -190,22 +128,10 @@ LLVM Backend ------------------- -- (DONE, eric, bert) make llvm work on osx - -- (DONE) arrays work (special case of variable sized structs) - -- (PROGRESS, cfbolz, hpk) implement variable sized structs - -- DONE: (Eric, Bert) added some void-helpers to Structs - - (PROGRESS) make prebuilt values work -- DONE: support function pointers - - implement exceptions -- (DONE, bert, eric) try to integrate Boehm GC - after 9am at Lauras place: Niklaus, Adrien, Arre, Christian, Ludovic, (Samuele and Eric for a bit), From arigo at codespeak.net Thu Jul 7 16:06:07 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 16:06:07 +0200 (CEST) Subject: [pypy-svn] r14384 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050707140607.95C2827B3C@code1.codespeak.net> Author: arigo Date: Thu Jul 7 16:06:04 2005 New Revision: 14384 Added: pypy/dist/pypy/translator/c/extfunc.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Draft implementation of time.clock() in genc in the new external function call model. Added: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Jul 7 16:06:04 2005 @@ -0,0 +1,33 @@ +import py +from pypy.rpython import extfunctable, lltype + + +class CHandWrittenWrapperFunctionCodeGenerator: + + def __init__(self, funcobj): + self.funcobj = funcobj + self.c_code = ll_externaltable[funcobj._callable] + + def argnames(self): + argcount = len(lltype.typeOf(self.funcobj).ARGS) + return ['a%d' % i for i in range(argcount)] + + def allconstantvalues(self): + return [] + + def cfunction_declarations(self): + return [] + + def cfunction_body(self): + source = py.code.Source(self.c_code).strip() + return list(source) + + +# map {ll_xyz_helper: bit of C code} + +ll_externaltable = { + + extfunctable.ll_time_clock: """ + return ((double)clock()) / CLOCKS_PER_SEC; + """, +} Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Thu Jul 7 16:06:04 2005 @@ -5,6 +5,8 @@ from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.external import CExternalFunctionCodeGenerator +from pypy.translator.c.extfunc import ll_externaltable +from pypy.translator.c.extfunc import CHandWrittenWrapperFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType @@ -437,7 +439,7 @@ lengths.append(9999) start = 0 while start < len(localnames): - # pack the local declarations over a few lines as possible + # pack the local declarations over as few lines as possible total = lengths[start] + 8 end = start+1 while total + lengths[end] < 77: @@ -470,17 +472,23 @@ yield '}' -def select_function_code_generator(fnptr, db): - if hasattr(fnptr, 'graph'): - cpython_exc = getattr(fnptr, 'exception_policy', None) == "CPython" - return FunctionCodeGenerator(fnptr.graph, db, cpython_exc) - elif getattr(fnptr, 'external', None) == 'C': - if getattr(fnptr, 'includes', None): +def select_function_code_generator(fnobj, db): + if fnobj._callable in ll_externaltable: + # 'fnobj' is one of the ll_xyz() functions special-cased in + # pypy.rpython.extfunctable. The corresponding C wrappers are written + # in extfunc.py. + return CHandWrittenWrapperFunctionCodeGenerator(fnobj) + elif hasattr(fnobj, 'graph'): + cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython" + return FunctionCodeGenerator(fnobj.graph, db, cpython_exc) + elif getattr(fnobj, 'external', None) == 'C': + # deprecated case + if getattr(fnobj, 'includes', None): return None # assume no wrapper needed else: - return CExternalFunctionCodeGenerator(fnptr, db) + return CExternalFunctionCodeGenerator(fnobj, db) else: - raise ValueError, "don't know how to generate code for %r" % (fnptr,) + raise ValueError, "don't know how to generate code for %r" % (fnobj,) class OpaqueNode(ContainerNode): Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Thu Jul 7 16:06:04 2005 @@ -190,7 +190,6 @@ t = Translator(does_stuff) t.annotate([]) t.specialize() - #t.view() db = LowLevelDatabase(t) entrypoint = db.get(pyobjectptr(does_stuff)) From tismer at codespeak.net Thu Jul 7 16:11:28 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 7 Jul 2005 16:11:28 +0200 (CEST) Subject: [pypy-svn] r14385 - pypy/dist/pypy/objspace/std Message-ID: <20050707141128.DFFEF27B3C@code1.codespeak.net> Author: tismer Date: Thu Jul 7 16:11:27 2005 New Revision: 14385 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: implemented hash() missing: reimplement pow() problem: certain division errors are a moving target. solution: single step in parallel with the C implementation (today) Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu Jul 7 16:11:27 2005 @@ -11,7 +11,7 @@ # for now, we use r_uint as a digit. # we may later switch to r_ushort, when it is supported by rtyper etc. -Digit = r_uint # works: r_ushort +Digit = r_uint # already works: r_ushort Twodigits = r_uint Stwodigits = int @@ -26,10 +26,28 @@ Carryadd = Twodigits Carrymul = Twodigits -# masks for normal signed integer -SIGN_BIT = LONG_BIT-1 -SIGN_MASK = r_uint(1) << SIGN_BIT -NONSIGN_MASK = ~SIGN_MASK +# Debugging digit array access. +# +# 0 == no check at all +# 1 == check correct type +# 2 == check for extra (ab)used bits +CHECK_DIGITS = 1 + +if CHECK_DIGITS: + class DigitArray(list): + if CHECK_DIGITS == 1: + def __setitem__(self, idx, value): + assert type(value) is Digit + list.__setitem__(self, idx, value) + elif CHECK_DIGITS == 2: + def __setitem__(self, idx, value): + assert type(value) is Digit + assert value <= MASK + list.__setitem__(self, idx, value) + else: + raise Exception, 'CHECK_DIGITS == %d not supported' % CHECK_DIGITS +else: + DigitArray = list # XXX some operations below return one of their input arguments # without checking that it's really of type long (and not a subclass). @@ -44,7 +62,7 @@ W_Object.__init__(w_self, space) if isinstance(digits, long): #YYYYYY digits, sign = args_from_long(digits) - w_self.digits = digits + w_self.digits = DigitArray(digits) w_self.sign = sign assert len(w_self.digits) @@ -221,10 +239,8 @@ i -= 1 return space.newbool(False) -def hash__Long(space,w_value): #YYYYYY - ## %reimplement% - # real Implementation should be taken from _Py_HashDouble in object.c - return space.wrap(hash(w_value.longval())) +def hash__Long(space, w_value): + return space.wrap(_hash(w_value)) # coerce def coerce__Long_Long(space, w_long1, w_long2): @@ -398,7 +414,7 @@ z = W_LongObject(space, [Digit(0)] * newsize, a.sign) # not sure if we will initialize things in the future? for i in range(wordshift): - z.digits[i] = 0 + z.digits[i] = Digit(0) accum = Twodigits(0) i = wordshift j = 0 @@ -765,7 +781,7 @@ def _x_divrem(v1, w1): size_w = len(w1.digits) - d = (MASK+1) // (w1.digits[size_w-1] + 1) + d = Digit(Twodigits(MASK+1) // (w1.digits[size_w-1] + 1)) v = _muladd1(v1, d, Digit(0)) w = _muladd1(w1, d, Digit(0)) size_v = len(v.digits) @@ -1256,3 +1272,21 @@ if int(x) < 0 and (sign > 0 or (x << 1) != 0): raise OverflowError return intmask(int(x) * sign) + +def _hash(v): + # This is designed so that Python ints and longs with the + # same value hash to the same value, otherwise comparisons + # of mapping keys will turn out weird + i = len(v.digits) - 1 + sign = v.sign + x = 0 + LONG_BIT_SHIFT = LONG_BIT - SHIFT + while i >= 0: + # Force a native long #-bits (32 or 64) circular shift + x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK) + x += v.digits[i] + i -= 1 + x = intmask(x * sign) + if x == -1: + x = -2 + return x From mwh at codespeak.net Thu Jul 7 16:15:20 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Jul 2005 16:15:20 +0200 (CEST) Subject: [pypy-svn] r14386 - pypy/extradoc/sprintinfo Message-ID: <20050707141520.CCAC127B3C@code1.codespeak.net> Author: mwh Date: Thu Jul 7 16:15:20 2005 New Revision: 14386 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: remove non-task (see my post to pypy-dev for more). Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Thu Jul 7 16:15:20 2005 @@ -58,8 +58,6 @@ ------------------ * fix floats:: - - translator/c/float_include.h should catch floating-point signals - with a technique similar to CPython's. - objspace/std/floatobject.py needs some clean-ups: look for XXX, for %reimplement% and for all try:except: blocks. From tismer at codespeak.net Thu Jul 7 16:19:32 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 7 Jul 2005 16:19:32 +0200 (CEST) Subject: [pypy-svn] r14387 - pypy/dist/pypy/objspace/std Message-ID: <20050707141932.E427427B3C@code1.codespeak.net> Author: tismer Date: Thu Jul 7 16:19:32 2005 New Revision: 14387 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: implementation complete! still hunting bugs. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu Jul 7 16:19:32 2005 @@ -302,15 +302,15 @@ div, mod = _l_divmod(w_long1, w_long2) return space.newtuple([div, mod]) -# helper for pow() #YYYYYY: still needs longval if second argument is negative +# helper for pow() def _impl_long_long_pow(space, lv, lw, lz=None): if lw.sign < 0: if lz is not None: raise OperationError(space.w_TypeError, space.wrap("pow() 2nd argument " "cannot be negative when 3rd argument specified")) - return space.pow(space.newfloat(float(lv.longval())), - space.newfloat(float(lw.longval())), + return space.pow(space.newfloat(_AsDouble(lv)), + space.newfloat(_AsDouble(lw)), space.w_None) if lz is not None: if lz.sign == 0: @@ -326,7 +326,7 @@ else: temp = lv i = 0 - #Treat the most significant digit specially to reduce multiplications + # Treat the most significant digit specially to reduce multiplications while i < len(lw.digits) - 1: j = 0 m = Digit(1) From ericvrp at codespeak.net Thu Jul 7 17:02:09 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 17:02:09 +0200 (CEST) Subject: [pypy-svn] r14388 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707150209.E905E27B3C@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 17:02:08 2005 New Revision: 14388 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: os.write working in llvm Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 17:02:08 2005 @@ -6,7 +6,9 @@ declare int %time(int*) ;void* actually declare int %clock() declare void %sleep(int) -declare int %open(sbyte*, int) +declare int %open(sbyte*, int, int) +declare int %write(int, sbyte*, int) +declare int %read(int, sbyte*, int) declare sbyte* %strncpy(sbyte*, sbyte*, int) %st.rpy_string.0 = type {int, {int, [0 x sbyte]}} @@ -22,7 +24,7 @@ %reallength = load int* %reallengthptr %length = add int %reallength, 1 %ulength = cast int %length to uint - %dest = malloc sbyte, uint %ulength ;XXX should actually call GC_malloc when available! + %dest = malloc sbyte, uint %ulength %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 %source1 = cast [0 x sbyte]* %source1ptr to sbyte* @@ -58,12 +60,28 @@ ret void } -int %ll_os_open(%st.rpy_string.0* %structstring, int %mode) { - %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) - %fd = call int %open(sbyte* %dest, int %mode) +int %ll_os_open(%st.rpy_string.0* %structstring, int %pythonmode) { + %flags = cast int %pythonmode to int + %mode = cast int 384 to int ;S_IRUSR=256, S_IWUSR=128 + %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) + %fd = call int %open(sbyte* %dest, int %flags, int %mode) free sbyte* %dest ret int %fd } +int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) { + %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr + %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) + %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) + free sbyte* %dest + ret int %byteswritten +} + +%st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) { + ;TODO: read(fd, buffersize) -> string + ret %st.rpy_string.0* null +} + ; End of external functions """ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 7 17:02:08 2005 @@ -159,15 +159,11 @@ class ExternalFuncNode(LLVMNode): - fnmapping = { + fnmapping = { #functions that have one-to-one C equivalents "%ll_os_dup": "%dup", "%ll_os_close": "%close", - #"%ll_os_open": "%open", } - ignoreset = "%ll_time_time %ll_time_clock %ll_time_sleep " \ - "%ll_os_read %ll_os_write %ll_os_open".split() - def __init__(self, db, value): self.db = db self.value = value @@ -198,11 +194,11 @@ def writedecl(self, codewriter): codewriter.declare(self.getdecl()) - if self.ref not in self.ignoreset: + if self.ref in self.fnmapping: codewriter.declare(self.getcdecl()) def writeimpl(self, codewriter): - if self.ref in self.ignoreset: + if self.ref not in self.fnmapping: return T = self.value._TYPE Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 7 17:02:08 2005 @@ -55,12 +55,32 @@ import os def openclose(a,b,c,d,e,f): s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT) + fd = os.open(s, os.O_CREAT|os.O_RDWR) os.close(fd) return fd path = '/tmp/b' + if os.path.exists(path): + os.unlink(path) f = compile_function(openclose, [int] * len(path)) - os.unlink(path) result = f(*map(ord, path)) assert os.path.exists(path) + +def test_os_file_ops_open_write_close(): + # the test is overly complicated because + # we don't have prebuilt string constants yet + import os + def openwriteclose(a,b,c,d,e,f): + s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + fd = os.open(s, os.O_CREAT|os.O_RDWR) + byteswritten = os.write(fd, s) + os.close(fd) + return byteswritten + + path = '/tmp/b' + if os.path.exists(path): + os.unlink(path) + f = compile_function(openwriteclose, [int] * len(path)) + result = f(*map(ord, path)) + assert os.path.exists(path) and open(path).read() == path + From arigo at codespeak.net Thu Jul 7 17:34:10 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 17:34:10 +0200 (CEST) Subject: [pypy-svn] r14389 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050707153410.B5B2727B3C@code1.codespeak.net> Author: arigo Date: Thu Jul 7 17:34:07 2005 New Revision: 14389 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/pytokenize.py pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Log: Hack to support the '@' token on top of Python 2.3. Some notes about the pyparser: I realize that it was a quick hack, but we should keep in mind that at some point we need something more clearly independent of CPython's interp-level standard library 'symbol' and 'token' modules. I suppose that it should also be refactored to isolate in non-global instances the tokens and symbols to use, in the same way as the grammar is isolated. Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Thu Jul 7 17:34:07 2005 @@ -2,7 +2,7 @@ it obeys the TokenSource interface defined for the grammar analyser in grammar.py """ -import symbol, sys +import sys from codeop import PyCF_DONT_IMPLY_DEDENT from pypy.interpreter.pyparser.grammar import TokenSource, Token Modified: pypy/dist/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pytokenize.py Thu Jul 7 17:34:07 2005 @@ -52,7 +52,8 @@ '/': 11, '0': 4, '1': 5, '2': 5, '3': 5, '4': 5, '5': 5, '6': 5, '7': 5, '8': 5, '9': 5, ':': 13, - ';': 13, '<': 9, '=': 12, '>': 8, 'A': 1, + ';': 13, '<': 9, '=': 12, '>': 8, + '@': 13, 'A': 1, 'B': 1, 'C': 1, 'D': 1, 'E': 1, 'F': 1, 'G': 1, 'H': 1, 'I': 1, 'J': 1, 'K': 1, 'L': 1, 'M': 1, Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Thu Jul 7 17:34:07 2005 @@ -2,6 +2,11 @@ import symbol import token +# XXX hack: make sure '@' is in the token list +if not hasattr(token, 'AT'): + token.AT = token.N_TOKENS + 2 # see pythonlexer.py for why '+2' + token.tok_name[token.AT] = 'AT' + TOKEN_MAP = { "STRING" : token.STRING, "NUMBER" : token.NUMBER, @@ -60,6 +65,7 @@ "~" : token.TILDE, "|" : token.VBAR, "|=" : token.VBAREQUAL, + "@": token.AT, } NT_OFFSET = token.NT_OFFSET From arigo at codespeak.net Thu Jul 7 18:08:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 18:08:42 +0200 (CEST) Subject: [pypy-svn] r14392 - in pypy/dist/pypy: rpython translator/c Message-ID: <20050707160842.8219027B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 18:08:37 2005 New Revision: 14392 Added: pypy/dist/pypy/translator/c/fixedname.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/g_exception.h pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py Log: Removed fixednames. Replaced with translator/c/fixedname.py, which explicitely asks for the name of each type, function and global object that is needed by the hand-written C include files. The generated C code will contain typedef's and #define's to map from the generated names back to the names expected by this hand-written code. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 7 18:08:37 2005 @@ -50,7 +50,6 @@ r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r self.exceptiondata = ExceptionData(self) - self.fixednames = self.fixednames.copy() def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -547,6 +546,3 @@ from pypy.rpython import rlist, rstr, rtuple, rdict from pypy.rpython import rclass, rbuiltin, rpbc, rspecialcase from pypy.rpython import rptr - -RPythonTyper.fixednames = {} -RPythonTyper.fixednames[rstr.STR] = True Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Thu Jul 7 18:08:37 2005 @@ -1,7 +1,6 @@ from pypy.rpython.lltype import Primitive, Ptr, typeOf from pypy.rpython.lltype import Struct, Array, FuncType, PyObject, Void from pypy.rpython.lltype import ContainerType, pyobjectptr, OpaqueType, GcStruct -from pypy.rpython.rmodel import getfunctionptr from pypy.objspace.flow.model import Constant from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue @@ -21,16 +20,6 @@ self.containernodes = {} self.containerlist = [] self.namespace = CNameManager() - if translator is not None and translator.rtyper is not None: - rtyper = translator.rtyper - for lltype, nameorflag in rtyper.fixednames.iteritems(): - if nameorflag is True: - self.namespace.make_reserved_names(lltype._name) - #else: - # self.namespace.make_reserved_names(nameorflag) - self.fixednames = rtyper.fixednames - else: - self.fixednames = {} self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) def gettypedefnode(self, T, varlength=1): @@ -170,44 +159,3 @@ return exceptiondata.lltype_of_exception_value else: return Ptr(PyObject) - - def pre_include_code_lines(self): - # generate some #defines that go before the #include to control - # what g_exception.h does - if self.translator is not None and self.translator.rtyper is not None: - exceptiondata = self.translator.rtyper.getexceptiondata() - - TYPE = exceptiondata.lltype_of_exception_type - assert isinstance(TYPE, Ptr) - typename = self.gettype(TYPE) - yield '#define RPYTHON_EXCEPTION_VTABLE %s' % cdecl(typename, '') - - TYPE = exceptiondata.lltype_of_exception_value - assert isinstance(TYPE, Ptr) - typename = self.gettype(TYPE) - yield '#define RPYTHON_EXCEPTION %s' % cdecl(typename, '') - - fnptr = getfunctionptr(self.translator, - exceptiondata.ll_exception_match) - fnname = self.get(fnptr) - yield '#define RPYTHON_EXCEPTION_MATCH %s' % (fnname,) - - fnptr = getfunctionptr(self.translator, - exceptiondata.ll_type_of_exc_inst) - fnname = self.get(fnptr) - yield '#define RPYTHON_TYPE_OF_EXC_INST %s' % (fnname,) - - fnptr = getfunctionptr(self.translator, - exceptiondata.ll_pyexcclass2exc) - fnname = self.get(fnptr) - yield '#define RPYTHON_PYEXCCLASS2EXC %s' % (fnname,) - - for pyexccls in exceptiondata.standardexceptions: - exc_llvalue = exceptiondata.ll_pyexcclass2exc( - pyobjectptr(pyexccls)) - # strange naming here because the macro name must be - # a substring of PyExc_%s - yield '#define Exc_%s\t%s' % ( - pyexccls.__name__, self.get(exc_llvalue)) - - self.complete() # because of the get() and gettype() above Added: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/fixedname.py Thu Jul 7 18:08:37 2005 @@ -0,0 +1,67 @@ +import types +from pypy.rpython.lltype import Ptr, pyobjectptr, LowLevelType +from pypy.translator.c.support import cdecl +from pypy.rpython.rmodel import getfunctionptr +from pypy.rpython.rstr import STR + + +def predeclare_common_types(rtyper): + # Common types + yield ('RPyString', Ptr(STR)) + + +def predeclare_exception_data(rtyper): + # Exception-related types and constants + exceptiondata = rtyper.getexceptiondata() + + yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) + yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) + + yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) + yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) + yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) + + for pyexccls in exceptiondata.standardexceptions: + exc_llvalue = exceptiondata.ll_pyexcclass2exc(pyobjectptr(pyexccls)) + # strange naming here because the macro name must be + # a substring of PyExc_%s + yield ('Exc_%s' % pyexccls.__name__, exc_llvalue) + + +def predeclare_all(rtyper): + for fn in [predeclare_common_types, + predeclare_exception_data + ]: + for t in fn(rtyper): + yield t + +# ____________________________________________________________ + +def pre_include_code_lines(db, rtyper): + # generate some #defines that go before the #include to provide + # predeclared well-known names for constant objects, functions and + # types. These names are then used by the #included files, like + # g_exception.h. + + def predeclare(c_name, lowlevelobj): + llname = db.get(lowlevelobj) + assert '\n' not in llname + return '#define\t%s\t%s' % (c_name, llname) + + def predeclarefn(c_name, ll_func): + return predeclare(c_name, getfunctionptr(db.translator, ll_func)) + + def predeclaretype(c_typename, lowleveltype): + assert isinstance(lowleveltype, Ptr) + typename = db.gettype(lowleveltype) + return 'typedef %s;' % cdecl(typename, c_typename) + + for c_name, obj in predeclare_all(rtyper): + if isinstance(obj, LowLevelType): + yield predeclaretype(c_name, obj) + elif isinstance(obj, types.FunctionType): + yield predeclarefn(c_name, obj) + else: + yield predeclare(c_name, obj) + + db.complete() # because of the get() and gettype() above Modified: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- pypy/dist/pypy/translator/c/g_exception.h (original) +++ pypy/dist/pypy/translator/c/g_exception.h Thu Jul 7 18:08:37 2005 @@ -6,7 +6,7 @@ /******************************************************************/ -#ifdef RPYTHON_EXCEPTION_VTABLE /* RPython version of exceptions */ +#ifdef RPYTHON_EXCEPTION_MATCH /* RPython version of exceptions */ /******************************************************************/ static RPYTHON_EXCEPTION_VTABLE rpython_exc_type = NULL; @@ -96,5 +96,5 @@ PyErr_SetString(Py##exc, msg) /* pun */ /******************************************************************/ -#endif /* RPYTHON_EXCEPTION_VTABLE */ +#endif /* RPYTHON_EXCEPTION_MATCH */ /******************************************************************/ Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu Jul 7 18:08:37 2005 @@ -2,6 +2,7 @@ import os, py from pypy.translator.c.node import PyObjectNode from pypy.translator.c.database import LowLevelDatabase +from pypy.translator.c.fixedname import pre_include_code_lines from pypy.translator.gensupp import uniquemodulename from pypy.translator.tool.buildpyxmodule import make_module_from_c from pypy.rpython.lltype import pyobjectptr @@ -50,8 +51,7 @@ # ____________________________________________________________ -def gen_readable_parts_of_main_c_file(f, database): - lines = list(database.pre_include_code_lines()) +def gen_readable_parts_of_main_c_file(f, database, preimplementationlines=[]): # # All declarations # @@ -77,7 +77,7 @@ print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' print >> f - for line in lines: + for line in preimplementationlines: print >> f, line print >> f, '#include "g_include.h"' print >> f @@ -117,11 +117,17 @@ for include in includes: print >> f, '#include <%s>' % (include,) + if database.translator is None or database.translator.rtyper is None: + preimplementationlines = [] + else: + preimplementationlines = list( + pre_include_code_lines(database, database.translator.rtyper)) + # # 1) All declarations # 2) Implementation of functions and global structures and arrays # - gen_readable_parts_of_main_c_file(f, database) + gen_readable_parts_of_main_c_file(f, database, preimplementationlines) # # Debugging info Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Thu Jul 7 18:08:37 2005 @@ -40,10 +40,7 @@ else: basename = db.gettypedefnode(STRUCT).name basename = '%s_len%d' % (basename, varlength) - if STRUCT in db.fixednames: - self.name = basename - else: - self.name = db.namespace.uniquename(basename) + self.name = db.namespace.uniquename(basename) self.dependencies = {} self.fields = [] self.prefix = somelettersfrom(STRUCT._name) + '_' From ericvrp at codespeak.net Thu Jul 7 18:23:23 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 18:23:23 +0200 (CEST) Subject: [pypy-svn] r14393 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707162323.ACE4E27B3F@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 18:23:21 2005 New Revision: 14393 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: Refactoring so we call the correct GC Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Thu Jul 7 18:23:21 2005 @@ -1,7 +1,6 @@ import py from itertools import count from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.genllvm import use_boehm_gc log = log.codewriter show_line_numbers = False # True @@ -94,18 +93,12 @@ "%(fromvar)s to %(targettype)s" % locals()) def malloc(self, targetvar, type_, size=1, atomic=False): - if use_boehm_gc: - cnt = count() - if atomic: - atomicString = '_atomic' - else: - atomicString = '' - self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, uint %(size)s" % locals()) - self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) - self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%GC_malloc%(atomicString)s(uint %%malloc.SizeU.%(cnt)d)" % locals()) - self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) - else: - self.indent("%(targetvar)s = malloc %(type_)s, uint %(size)s" % locals()) + cnt = count() + postfix = ('', '_atomic')[atomic] + self.indent("%%malloc.Size.%(cnt)d = getelementptr %(type_)s* null, uint %(size)s" % locals()) + self.indent("%%malloc.SizeU.%(cnt)d = cast %(type_)s* %%malloc.Size.%(cnt)d to uint" % locals()) + self.indent("%%malloc.Ptr.%(cnt)d = call sbyte* %%gc_malloc%(postfix)s(uint %%malloc.SizeU.%(cnt)d)" % locals()) + self.indent("%(targetvar)s = cast sbyte* %%malloc.Ptr.%(cnt)d to %(type_)s*" % locals()) def getelementptr(self, targetvar, type, typevar, *indices): res = "%(targetvar)s = getelementptr %(type)s %(typevar)s, int 0, " % locals() Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 18:23:21 2005 @@ -3,6 +3,8 @@ ; XXX these int's might need to be long's on 64 bit CPU's :( +declare sbyte* %gc_malloc(uint) +declare sbyte* %gc_malloc_atomic(uint) declare int %time(int*) ;void* actually declare int %clock() declare void %sleep(int) @@ -17,6 +19,37 @@ """ +gc_boehm = """; Using Boehm GC + +declare sbyte* %GC_malloc(uint) +declare sbyte* %GC_malloc_atomic(uint) + +sbyte* %gc_malloc(uint %n) { + %ptr = call sbyte* %GC_malloc(uint %n) + ret sbyte* %ptr +} + +sbyte* %gc_malloc_atomic(uint %n) { + %ptr = call sbyte* %GC_malloc_atomic(uint %n) + ret sbyte* %ptr +} + +""" + +gc_disabled = """; Using no GC + +sbyte* %gc_malloc(uint %n) { + %ptr = malloc sbyte, uint %n + ret sbyte* %ptr +} + +sbyte* %gc_malloc_atomic(uint %n) { + %ptr = malloc sbyte, uint %n + ret sbyte* %ptr +} + +""" + extfunctions = """; Helper function to convert LLVM <-> C types sbyte* %cast(%st.rpy_string.0* %structstring) { @@ -24,18 +57,18 @@ %reallength = load int* %reallengthptr %length = add int %reallength, 1 %ulength = cast int %length to uint - %dest = malloc sbyte, uint %ulength - + %dest = call sbyte* %gc_malloc_atomic(uint %ulength) + %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 %source1 = cast [0 x sbyte]* %source1ptr to sbyte* %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) - + %zeropos1 = cast sbyte* %dest to int %zeropos2 = add int %zeropos1, %reallength %zerodest = cast int %zeropos2 to sbyte* store sbyte 0, sbyte* %zerodest - ret sbyte* %dest ;XXX alloca freed at end of function. this will crash! + ret sbyte* %dest } ; Wrapper functions that call external (C) functions @@ -65,7 +98,6 @@ %mode = cast int 384 to int ;S_IRUSR=256, S_IWUSR=128 %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) %fd = call int %open(sbyte* %dest, int %flags, int %mode) - free sbyte* %dest ret int %fd } @@ -74,7 +106,6 @@ %reallength = load int* %reallengthptr %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) - free sbyte* %dest ret int %byteswritten } Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 7 18:23:21 2005 @@ -13,7 +13,7 @@ from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls -from pypy.translator.llvm2.extfunction import extdeclarations, extfunctions +from pypy.translator.llvm2.extfunction import extdeclarations, extfunctions, gc_boehm, gc_disabled from pypy.translator.translator import Translator function_count = {} @@ -45,17 +45,17 @@ nl(); comment("Function Prototypes") ; nl() for extdecl in extdeclarations.split('\n'): codewriter.append(extdecl) - if use_boehm_gc: - codewriter.declare('sbyte* %GC_malloc(uint)') - codewriter.declare('sbyte* %GC_malloc_atomic(uint)') - codewriter.declare('sbyte* %GC_realloc(sbyte*, uint)') for typ_decl in db.getobjects(): typ_decl.writedecl(codewriter) #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() - for extfunc in extfunctions.split('\n'): + if use_boehm_gc: + gc_funcs = gc_boehm + else: + gc_funcs = gc_disabled + for extfunc in (gc_funcs + extfunctions).split('\n'): codewriter.append(extfunc) for typ_decl in db.getobjects(): typ_decl.writeimpl(codewriter) Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 7 18:23:21 2005 @@ -84,3 +84,26 @@ result = f(*map(ord, path)) assert os.path.exists(path) and open(path).read() == path +def DONTtest_os_file_ops_open_write_read_close(): + # the test is overly complicated because + # we don't have prebuilt string constants yet + import os + def openwriteclose_openreadclose(a,b,c,d,e,f): + s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) + + fd = os.open(s, os.O_CREAT|os.O_RDWR) + byteswritten = os.write(fd, s) + os.close(fd) + + fd = os.open(s, os.os.O_RD) + r = os.read(fd, n=1000) + os.close(fd) + + return r + + path = '/tmp/b' + if os.path.exists(path): + os.unlink(path) + f = compile_function(openwriteclose_openreadclose, [int] * len(path)) + result = f(*map(ord, path)) + assert os.path.exists(path) and open(path).read() is path and result is path From rxe at codespeak.net Thu Jul 7 18:57:55 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 7 Jul 2005 18:57:55 +0200 (CEST) Subject: [pypy-svn] r14394 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707165755.CCFE227B39@code1.codespeak.net> Author: rxe Date: Thu Jul 7 18:57:54 2005 New Revision: 14394 Added: pypy/dist/pypy/translator/llvm2/test/test_lltype.py Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py pypy/dist/pypy/translator/llvm2/test/test_gc.py Log: * add new (and sane like) tests for lltypes * refactor out genllvm function and add flag to avoid external functions being included * add some basic support for unichars * fix some typos in logging Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Thu Jul 7 18:57:54 2005 @@ -13,6 +13,9 @@ lltype.Unsigned: "uint", lltype.Bool: "bool", lltype.Float: "double", + # XXX Preliminary support for unicode, makes sense to + # make this more configurable + lltype.UniChar: "uint", lltype.Void: "void"} class NormalizingDict(object): Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 7 18:57:54 2005 @@ -13,75 +13,101 @@ from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls -from pypy.translator.llvm2.extfunction import extdeclarations, extfunctions, gc_boehm, gc_disabled +from pypy.translator.llvm2.extfunction import extdeclarations, \ + extfunctions, gc_boehm, gc_disabled + from pypy.translator.translator import Translator function_count = {} -def genllvm(translator): - remove_void(translator) - #rename_extfunc_calls(translator) - func = translator.entrypoint - - db = Database(translator) - ptr = getfunctionptr(translator, func) - c = inputconst(lltype.typeOf(ptr), ptr) - db.prepare_repr_arg(c) - assert c in db.obj2node - db.setup_all() - entrynode = db.obj2node[c] - codewriter = CodeWriter() - comment = codewriter.comment - nl = codewriter.newline - - nl(); comment("Type Declarations"); nl() - for typ_decl in db.getobjects(): - typ_decl.writedatatypedecl(codewriter) - - nl(); comment("Global Data") ; nl() - for typ_decl in db.getobjects(): - typ_decl.writeglobalconstants(codewriter) - - nl(); comment("Function Prototypes") ; nl() - for extdecl in extdeclarations.split('\n'): - codewriter.append(extdecl) - for typ_decl in db.getobjects(): - typ_decl.writedecl(codewriter) - - #import pdb ; pdb.set_trace() - nl(); comment("Function Implementation") - codewriter.startimpl() - if use_boehm_gc: - gc_funcs = gc_boehm - else: - gc_funcs = gc_disabled - for extfunc in (gc_funcs + extfunctions).split('\n'): - codewriter.append(extfunc) - for typ_decl in db.getobjects(): - typ_decl.writeimpl(codewriter) - - comment("End of file") ; nl() - - if func.func_name in function_count: - postfix = '_%d' % function_count[func.func_name] - function_count[func.func_name] += 1 - else: - postfix = '' - function_count[func.func_name] = 1 - - targetdir = udir - llvmsource = targetdir.join(func.func_name+postfix).new(ext='.ll') - content = str(codewriter) - llvmsource.write(content) - log.source(content) - - if not llvm_is_on_path(): - py.test.skip("llvm not found") # XXX not good to call py.test.skip here - - pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+postfix+'.pyx') - write_pyx_wrapper(entrynode, pyxsource) - - return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) +class GenLLVM(object): + + def __init__(self, translator, embedexterns=True): + self.db = Database(translator) + self.translator = translator + self.embedexterns = embedexterns + # transformations + remove_void(translator) + #rename_extfunc_calls(translator) + translator.checkgraphs() + + def compile(self, func=None): + if func is None: + func = self.translator.entrypoint + self.entrypoint = func + + ptr = getfunctionptr(self.translator, func) + c = inputconst(lltype.typeOf(ptr), ptr) + self.db.prepare_repr_arg(c) + assert c in self.db.obj2node + self.db.setup_all() + self.entrynode = self.db.obj2node[c] + codewriter = CodeWriter() + comment = codewriter.comment + nl = codewriter.newline + + nl(); comment("Type Declarations"); nl() + for typ_decl in self.db.getobjects(): + typ_decl.writedatatypedecl(codewriter) + + nl(); comment("Global Data") ; nl() + for typ_decl in self.db.getobjects(): + typ_decl.writeglobalconstants(codewriter) + + nl(); comment("Function Prototypes") ; nl() + if self.embedexterns: + for extdecl in extdeclarations.split('\n'): + codewriter.append(extdecl) + for typ_decl in self.db.getobjects(): + typ_decl.writedecl(codewriter) + + #import pdb ; pdb.set_trace() + nl(); comment("Function Implementation") + codewriter.startimpl() + if self.embedexterns: + for extfunc in extfunctions.split('\n'): + codewriter.append(extfunc) + + if use_boehm_gc: + gc_funcs = gc_boehm + else: + gc_funcs = gc_disabled + for extfunc in gc_funcs.split('\n'): + codewriter.append(extfunc) + + for typ_decl in self.db.getobjects(): + typ_decl.writeimpl(codewriter) + + comment("End of file") ; nl() + self.content = str(codewriter) + return self.content + + def create_module(self): + # hack to prevent running the same function twice in a test + func = self.entrypoint + if func.func_name in function_count: + postfix = '_%d' % function_count[func.func_name] + function_count[func.func_name] += 1 + else: + postfix = '' + function_count[func.func_name] = 1 + + targetdir = udir + llvmsource = targetdir.join(func.func_name+postfix).new(ext='.ll') + llvmsource.write(self.content) + + if not llvm_is_on_path(): + py.test.skip("llvm not found") # XXX not good to call py.test.skip here + + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+postfix+'.pyx') + write_pyx_wrapper(self.entrynode, pyxsource) + + return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) + +def genllvm(translator, embedexterns=True): + gen = GenLLVM(translator, embedexterns=embedexterns) + log.source(gen.compile()) + return gen.create_module() def llvm_is_on_path(): try: @@ -90,20 +116,20 @@ return False return True -def compile_module(function, annotate, view=False): +def compile_module(function, annotate, view=False, embedexterns=True): t = Translator(function) a = t.annotate(annotate) t.specialize() a.simplify() if view: t.view() - return genllvm(t) + return genllvm(t, embedexterns=embedexterns) -def compile_function(function, annotate, view=False): - mod = compile_module(function, annotate, view) +def compile_function(function, annotate, view=False, embedexterns=True): + mod = compile_module(function, annotate, view, embedexterns=embedexterns) return getattr(mod, function.func_name + "_wrapper") -def compile_module_function(function, annotate, view=False): - mod = compile_module(function, annotate, view) +def compile_module_function(function, annotate, view=False, embedexterns=True): + mod = compile_module(function, annotate, view, embedexterns=embedexterns) f = getattr(mod, function.func_name + "_wrapper") return mod, f Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 7 18:57:54 2005 @@ -6,8 +6,8 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.genllvm import compile_function -py.log.setconsumer("extfunc", py.log.STDOUT) -py.log.setconsumer("extfunc database prepare", None) +py.log.setconsumer("genllvm", py.log.STDOUT) +py.log.setconsumer("genllvm database prepare", None) def test_external_function_ll_os_dup(): import os Modified: pypy/dist/pypy/translator/llvm2/test/test_gc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_gc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_gc.py Thu Jul 7 18:57:54 2005 @@ -4,8 +4,8 @@ from pypy.translator.llvm2.genllvm import use_boehm_gc from pypy.translator.llvm2.genllvm import compile_module_function -py.log.setconsumer("test_gc", py.log.STDOUT) -py.log.setconsumer("test_gc database prepare", None) +py.log.setconsumer("genllvm", py.log.STDOUT) +py.log.setconsumer("genllvm database prepare", None) def test_GC_malloc(): if not use_boehm_gc: Added: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Thu Jul 7 18:57:54 2005 @@ -0,0 +1,60 @@ +import py + +from pypy.rpython import lltype + +from pypy.translator.llvm2.genllvm import compile_function +from pypy.translator.llvm2 import database, codewriter + +py.log.setconsumer("genllvm", py.log.STDOUT) +py.log.setconsumer("genllvm database prepare", None) + +P = lltype.GcStruct("s", + ('signed', lltype.Signed), + ('unsigned', lltype.Unsigned), + ('float', lltype.Float), + ('char', lltype.Char), + ('bool', lltype.Bool), + ('unichar', lltype.UniChar) + ) + +def test_struct1(): + # struct of primitives + def simple1(): + s = lltype.malloc(P) + return s.signed# + s.unsigned + s.float + s.char + s.bool + s.unichar + fn = compile_function(simple1, [], embedexterns=False) + assert fn() == 0 + +# def test_struct2(): +# S = lltype.Struct("s", ('v', lltype.Signed)) +# S2 = lltype.GcStruct("s2", ('a', S), ('b', S)) +# def simple2(): +# s = lltype.malloc(S2) +# s.a.v = 6 +# s.b.v = 12 +# return s.a.v + s.b.v +# fn = compile_function(simple2, [], embedexterns=False, view=True) +# assert fn() == 18 + +# def test_simple_struct(): +# S0 = lltype.GcStruct("s0", ('a', lltype.Signed), ('b', lltype.Signed)) +# c0 = lltype.malloc(S0) +# c0.a, c0.b = 1, 2 +# def simple_struct(): +# return c0.a + c0.b +# f = compile_function(simple_struct, [], embedexterns=False, view=True) +# assert f() == 3 + +# def test_simple_struct2(): +# S0 = lltype.GcStruct("s0", ('a', lltype.Char), ('b', lltype.Signed)) +# def build(): +# s0 = lltype.malloc(S0) +# s0.a = "l" +# s0.b = 2 +# return s0 +# c0 = build() +# def simple_struct2(): +# return c0.a + c0.b +# f = compile_function(simple_struct, [], embedexterns=False, view=True) +# assert f() == 3 + From ericvrp at codespeak.net Thu Jul 7 19:04:49 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 19:04:49 +0200 (CEST) Subject: [pypy-svn] r14395 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050707170449.1F06B27B39@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 19:04:48 2005 New Revision: 14395 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: os.read working now in LLVM Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 19:04:48 2005 @@ -110,8 +110,19 @@ } %st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) { - ;TODO: read(fd, buffersize) -> string - ret %st.rpy_string.0* null + ;This is a bit simplistic! It really allocated a large enough buffer to hold all the data in. + %str = call %st.rpy_string.0* %new.st.var.rpy_string.0(int %buffersize) + + ;load the actual data + %destptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 1 + %dest = cast [0 x sbyte]* %destptr to sbyte* + %bytesread = call int %read(int %fd, sbyte* %dest, int %buffersize) + + ;set str.length to number of bytes read + %reallengthptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 0 + store int %bytesread, int* %reallengthptr + + ret %st.rpy_string.0* %str } ; End of external functions Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 7 19:04:48 2005 @@ -82,9 +82,10 @@ os.unlink(path) f = compile_function(openwriteclose, [int] * len(path)) result = f(*map(ord, path)) - assert os.path.exists(path) and open(path).read() == path + assert os.path.exists(path) + assert open(path).read() == path -def DONTtest_os_file_ops_open_write_read_close(): +def test_os_file_ops_open_write_read_close(): # the test is overly complicated because # we don't have prebuilt string constants yet import os @@ -92,18 +93,21 @@ s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) fd = os.open(s, os.O_CREAT|os.O_RDWR) - byteswritten = os.write(fd, s) + byteswritten = os.write(fd, s+s+s) os.close(fd) - fd = os.open(s, os.os.O_RD) - r = os.read(fd, n=1000) + fd = os.open(s, os.O_RDWR) + maxread = 1000 + r = os.read(fd, maxread) os.close(fd) - return r + return len(r) path = '/tmp/b' if os.path.exists(path): os.unlink(path) f = compile_function(openwriteclose_openreadclose, [int] * len(path)) result = f(*map(ord, path)) - assert os.path.exists(path) and open(path).read() is path and result is path + assert os.path.exists(path) + assert open(path).read() == path * 3 + assert result is len(path) * 3 From arigo at codespeak.net Thu Jul 7 19:18:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 19:18:03 +0200 (CEST) Subject: [pypy-svn] r14396 - in pypy/dist/pypy: annotation rpython rpython/test translator Message-ID: <20050707171803.5063F27B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 19:17:56 2005 New Revision: 14396 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_exception.py pypy/dist/pypy/translator/unsimplify.py Log: Add support for instance variables in standard exception classes. Implemented OSError.errno. This required some bugfixes in insert_link_conversion(). Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu Jul 7 19:17:56 2005 @@ -265,6 +265,7 @@ BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init +BUILTIN_ANALYZERS[OSError.__init__.im_func] = exception_init # this one is needed otherwise when annotating assert in a test we may try to annotate # py.test AssertionError.__init__ . BUILTIN_ANALYZERS[AssertionError.__init__.im_func] = exception_init Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Thu Jul 7 19:17:56 2005 @@ -5,6 +5,7 @@ from __future__ import generators from types import FunctionType from pypy.annotation.model import SomeImpossibleValue, SomePBC, tracking_unionof +from pypy.annotation.model import SomeInteger # The main purpose of a ClassDef is to collect information about class/instance @@ -167,6 +168,12 @@ value.class_ = cls # remember that this is really a method self.add_source_for_attribute(name, sources.get(name, cls), self) + # forced attributes + if cls in FORCE_ATTRIBUTES_INTO_CLASSES: + for name, s_value in FORCE_ATTRIBUTES_INTO_CLASSES[cls].items(): + self.generalize_attr(name, s_value) + self.find_attribute(name).readonly = False + def add_source_for_attribute(self, attr, source, clsdef=None): """Adds information about a constant source for an attribute. """ @@ -375,3 +382,9 @@ def isclassdef(x): return isinstance(x, ClassDef) + +# ____________________________________________________________ + +FORCE_ATTRIBUTES_INTO_CLASSES = { + OSError: {'errno': SomeInteger()}, + } Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Thu Jul 7 19:17:56 2005 @@ -69,9 +69,9 @@ example = rclass.ll_cast_to_object(example) example.typeptr = r_inst.rclass.getvtable() table[cls] = example - else: - assert cls.__module__ != 'exceptions', ( - "built-in exceptions should not grow attributes") + #else: + # assert cls.__module__ != 'exceptions', ( + # "built-in exceptions should not grow attributes") r_inst = rclass.getinstancerepr(rtyper, None) r_inst.setup() default_excinst = malloc(self.lltype_of_exception_value.TO, Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Thu Jul 7 19:17:56 2005 @@ -155,6 +155,19 @@ return i1 return i2 +def rtype_Exception__init__(hop): + pass + +def rtype_OSError__init__(hop): + if hop.nb_args == 2: + raise TyperError("OSError() should not be called with " + "a single argument") + if hop.nb_args >= 3: + v_self = hop.args_v[0] + r_self = hop.args_r[0] + v_errno = hop.inputarg(lltype.Signed, arg=1) + r_self.setfield(v_self, 'errno', v_errno, hop.llops) + def rtype_math_floor(hop): vlist = hop.inputargs(lltype.Float) return hop.genop('float_floor', vlist, resulttype=lltype.Float) @@ -176,6 +189,8 @@ BUILTIN_TYPER[original] = value BUILTIN_TYPER[math.floor] = rtype_math_floor BUILTIN_TYPER[math.fmod] = rtype_math_fmod +BUILTIN_TYPER[Exception.__init__.im_func] = rtype_Exception__init__ +BUILTIN_TYPER[OSError.__init__.im_func] = rtype_OSError__init__ # annotation of low-level types def rtype_malloc(hop): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Jul 7 19:17:56 2005 @@ -450,10 +450,8 @@ assert hop.nb_args == 1, ("arguments passed to __init__, " "but no __init__!") else: - if initfunc == Exception.__init__.im_func: - return v_instance # ignore __init__ and arguments completely s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass) - s_init = annmodel.SomePBC({initfunc: True}) + s_init = self.rtyper.annotator.bookkeeper.immutablevalue(initfunc) hop2 = hop.copy() hop2.r_s_popfirstarg() # discard the class pointer argument hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 7 19:17:56 2005 @@ -211,33 +211,43 @@ a, using_repr=self.exceptiondata.r_exception_value) inputargs_reprs = self.setup_block_entry(link.target) + newops = LowLevelOpList(self) + newlinkargs = {} for i in range(len(link.args)): a1 = link.args[i] r_a2 = inputargs_reprs[i] if isinstance(a1, Constant): link.args[i] = self.typedconstant(a1, using_repr=r_a2) continue # the Constant was typed, done - r_a1 = self.bindingrepr(a1) + if a1 is link.last_exception: + r_a1 = self.exceptiondata.r_exception_type + elif a1 is link.last_exc_value: + r_a1 = self.exceptiondata.r_exception_value + else: + r_a1 = self.bindingrepr(a1) if r_a1 == r_a2: continue # no conversion needed - newops = LowLevelOpList(self) try: - a1 = newops.convertvar(a1, r_a1, r_a2) + new_a1 = newops.convertvar(a1, r_a1, r_a2) except TyperError, e: self.gottypererror(e, block, link, newops) + if new_a1 != a1: + newlinkargs[i] = new_a1 - if newops and not can_insert_here: + if newops: + if can_insert_here: + block.operations.extend(newops) + else: # cannot insert conversion operations around a single # link, unless it is the only exit of this block. # create a new block along the link... - newblock = insert_empty_block(self.annotator.translator, - link) - # ...and do the conversions there. - self.insert_link_conversions(newblock) - break # done with this link - else: - block.operations.extend(newops) - link.args[i] = a1 + block = insert_empty_block(self.annotator.translator, + link, + # ...and store the conversions there. + newops=newops) + link = block.exits[0] + for i, new_a1 in newlinkargs.items(): + link.args[i] = new_a1 def highlevelops(self, block, llops): # enumerate the HighLevelOps in a block. Modified: pypy/dist/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_exception.py (original) +++ pypy/dist/pypy/rpython/test/test_exception.py Thu Jul 7 19:17:56 2005 @@ -1,6 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.test.test_llinterp import interpret class MyException(Exception): @@ -50,3 +51,15 @@ strgerr_inst = data.ll_pyexcclass2exc(pyobjectptr(MyStrangeException)) assert strgerr_inst.typeptr == t.rtyper.class_reprs[None].getvtable() + + +def test_exception_with_arg(): + def g(n): + raise OSError(n, "?") + def f(n): + try: + g(n) + except OSError, e: + return e.errno + res = interpret(f, [42]) + assert res == 42 Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Thu Jul 7 19:17:56 2005 @@ -12,13 +12,14 @@ newvar.concretetype = v.concretetype return newvar -def insert_empty_block(translator, link): +def insert_empty_block(translator, link, newops=[]): """Insert and return a new block along the given link.""" vars = uniqueitems([v for v in link.args if isinstance(v, Variable)]) mapping = {} for v in vars: mapping[v] = copyvar(translator, v) newblock = Block(vars) + newblock.operations.extend(newops) newblock.closeblock(Link(link.args, link.target)) newblock.renamevariables(mapping) link.args[:] = vars From arigo at codespeak.net Thu Jul 7 19:47:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 19:47:15 +0200 (CEST) Subject: [pypy-svn] r14397 - pypy/dist/pypy/translator/c Message-ID: <20050707174715.6F93327B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 19:47:11 2005 New Revision: 14397 Added: pypy/dist/pypy/translator/c/extfunc_include.h (contents, props changed) Removed: pypy/dist/pypy/translator/c/extfunc.py Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/node.py Log: Calling external functions seems to go in the good direction. Replaced extfunc.py with a C include file, extfunc_include.h. Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Thu Jul 7 19:47:11 2005 @@ -19,6 +19,7 @@ self.structdeflist = [] self.containernodes = {} self.containerlist = [] + self.externalfuncs = {} self.namespace = CNameManager() self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) Deleted: /pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- /pypy/dist/pypy/translator/c/extfunc.py Thu Jul 7 19:47:11 2005 +++ (empty file) @@ -1,33 +0,0 @@ -import py -from pypy.rpython import extfunctable, lltype - - -class CHandWrittenWrapperFunctionCodeGenerator: - - def __init__(self, funcobj): - self.funcobj = funcobj - self.c_code = ll_externaltable[funcobj._callable] - - def argnames(self): - argcount = len(lltype.typeOf(self.funcobj).ARGS) - return ['a%d' % i for i in range(argcount)] - - def allconstantvalues(self): - return [] - - def cfunction_declarations(self): - return [] - - def cfunction_body(self): - source = py.code.Source(self.c_code).strip() - return list(source) - - -# map {ll_xyz_helper: bit of C code} - -ll_externaltable = { - - extfunctable.ll_time_clock: """ - return ((double)clock()) / CLOCKS_PER_SEC; - """, -} Added: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 19:47:11 2005 @@ -0,0 +1,13 @@ +/************************************************************/ + /*** C header subsection: external functions ***/ + +#include + +/* The functions below are mapped to functions from pypy.rpython.extfunctable + by the pypy.translator.c.fixedname.EXTERNALS dictionary. */ + + +double LL_time_clock(void) +{ + return ((double) clock()) / CLOCKS_PER_SEC; +} Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Thu Jul 7 19:47:11 2005 @@ -1,16 +1,30 @@ import types -from pypy.rpython.lltype import Ptr, pyobjectptr, LowLevelType +from pypy.rpython.lltype import Ptr, pyobjectptr, LowLevelType, _ptr, typeOf from pypy.translator.c.support import cdecl from pypy.rpython.rmodel import getfunctionptr from pypy.rpython.rstr import STR +from pypy.rpython import extfunctable -def predeclare_common_types(rtyper): +# table of functions hand-written in extfunc_include.h +EXTERNALS = { + extfunctable.ll_time_clock: 'LL_time_clock', + } + + +def predeclare_common_types(db, rtyper): # Common types yield ('RPyString', Ptr(STR)) -def predeclare_exception_data(rtyper): +def predeclare_extfuncs(db, rtyper): + for func, funcobj in db.externalfuncs.items(): + c_name = EXTERNALS[func] + funcptr = _ptr(Ptr(typeOf(funcobj)), funcobj) # hum + yield c_name, funcptr + + +def predeclare_exception_data(db, rtyper): # Exception-related types and constants exceptiondata = rtyper.getexceptiondata() @@ -28,11 +42,12 @@ yield ('Exc_%s' % pyexccls.__name__, exc_llvalue) -def predeclare_all(rtyper): +def predeclare_all(db, rtyper): for fn in [predeclare_common_types, - predeclare_exception_data + predeclare_exception_data, + predeclare_extfuncs, ]: - for t in fn(rtyper): + for t in fn(db, rtyper): yield t # ____________________________________________________________ @@ -56,7 +71,7 @@ typename = db.gettype(lowleveltype) return 'typedef %s;' % cdecl(typename, c_typename) - for c_name, obj in predeclare_all(rtyper): + for c_name, obj in predeclare_all(db, rtyper): if isinstance(obj, LowLevelType): yield predeclaretype(c_name, obj) elif isinstance(obj, types.FunctionType): Modified: pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/g_include.h Thu Jul 7 19:47:11 2005 @@ -21,3 +21,4 @@ #include "float_include.h" #include "ll_include.h" #include "pyobj_include.h" +#include "extfunc_include.h" Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Thu Jul 7 19:47:11 2005 @@ -5,10 +5,9 @@ from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.external import CExternalFunctionCodeGenerator -from pypy.translator.c.extfunc import ll_externaltable -from pypy.translator.c.extfunc import CHandWrittenWrapperFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType +from pypy.translator.c import fixedname def needs_refcount(T): @@ -470,11 +469,12 @@ def select_function_code_generator(fnobj, db): - if fnobj._callable in ll_externaltable: + if fnobj._callable in fixedname.EXTERNALS: # 'fnobj' is one of the ll_xyz() functions special-cased in # pypy.rpython.extfunctable. The corresponding C wrappers are written - # in extfunc.py. - return CHandWrittenWrapperFunctionCodeGenerator(fnobj) + # by hand in extfunc_include.h, and declared in fixedname.EXTERNALS. + db.externalfuncs[fnobj._callable] = fnobj + return None elif hasattr(fnobj, 'graph'): cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython" return FunctionCodeGenerator(fnobj.graph, db, cpython_exc) From arigo at codespeak.net Thu Jul 7 19:57:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 19:57:26 +0200 (CEST) Subject: [pypy-svn] r14402 - pypy/dist/pypy/translator/c/test Message-ID: <20050707175726.910F927B3C@code1.codespeak.net> Author: arigo Date: Thu Jul 7 19:57:23 2005 New Revision: 14402 Added: pypy/dist/pypy/translator/c/test/test_fixedname.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/test/test_database.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Removed a test that no longer applies and reorganized other tests. Modified: pypy/dist/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_database.py (original) +++ pypy/dist/pypy/translator/c/test/test_database.py Thu Jul 7 19:57:23 2005 @@ -196,24 +196,6 @@ db.complete() dump_on_stdout(db) -def test_fixedname(): - def f(): - return "foo" - t = Translator(f) - t.annotate([]) - t.specialize() - - db = LowLevelDatabase(t) - S = GcStruct('rpy_string', ('x', Signed)) - s = malloc(S) - s.x = 42 - db.get(s) - Sname = db.gettype(S) - db.get(pyobjectptr(f)) - from pypy.rpython import rstr - assert db.gettype(rstr.STR) == "struct rpy_string @" - assert Sname != "struct rpy_string @" - def test_malloc(): S = GcStruct('testing', ('x', Signed), ('y', Signed)) def ll_f(x): Added: pypy/dist/pypy/translator/c/test/test_fixedname.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_fixedname.py Thu Jul 7 19:57:23 2005 @@ -0,0 +1,14 @@ +import autopath +from pypy.translator.c.test.test_genc import compile + + +def test_time_clock(): + import time + def does_stuff(): + return time.clock() + f1 = compile(does_stuff, []) + t0 = time.clock() + t1 = f1() + assert type(t1) is float + t2 = time.clock() + assert t0 <= t1 <= t2 Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Thu Jul 7 19:57:23 2005 @@ -24,6 +24,22 @@ include_dirs = [os.path.dirname(autopath.this_dir)]) return m +def compile(fn, argtypes): + t = Translator(fn) + t.annotate(argtypes) + t.specialize() + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(fn)) + db.complete() + module = compile_db(db) + 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 + return checking_fn + def test_untyped_func(): def f(x): @@ -71,21 +87,9 @@ l = [x] l.append(x+1) return l[0] * l[-1] - t = Translator(f) - t.annotate([int]) - t.specialize() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(f)) - db.complete() - #t.view() - module = compile_db(db) - - f1 = getattr(module, entrypoint) + f1 = compile(f, [int]) assert f1(5) == 30 assert f1(x=5) == 30 - mallocs, frees = module.malloc_counters() - assert mallocs == frees def test_rptr(): @@ -100,25 +104,13 @@ return p.x else: return -42 - t = Translator(f) - t.annotate([int]) - t.specialize() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(f)) - db.complete() - #t.view() - module = compile_db(db) - - f1 = getattr(module, entrypoint) + f1 = compile(f, [int]) assert f1(5) == 10 assert f1(i=5) == 10 assert f1(1) == 2 assert f1(0) == -42 assert f1(-1) == -42 assert f1(-5) == -42 - mallocs, frees = module.malloc_counters() - assert mallocs == frees def test_rptr_array(): @@ -127,21 +119,9 @@ p = malloc(A, i) p[1] = x return p[1] - t = Translator(f) - t.annotate([int, annmodel.SomePtr(Ptr(PyObject))]) - t.specialize() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(f)) - db.complete() - #t.view() - module = compile_db(db) - - f1 = getattr(module, entrypoint) + f1 = compile(f, [int, annmodel.SomePtr(Ptr(PyObject))]) assert f1(5, 123) == 123 assert f1(12, "hello") == "hello" - mallocs, frees = module.malloc_counters() - assert mallocs == frees def test_runtime_type_info(): @@ -183,65 +163,19 @@ mallocs, frees = module.malloc_counters() assert mallocs == frees -def test_time_clock(): - import time - def does_stuff(): - return time.clock() - t = Translator(does_stuff) - t.annotate([]) - t.specialize() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(does_stuff)) - db.complete() - - module = compile_db(db) - - f1 = getattr(module, entrypoint) - t0 = time.clock() - t1 = f1() - assert type(t1) is float - t2 = time.clock() - assert t0 <= t1 <= t2 - mallocs, frees = module.malloc_counters() - assert mallocs == frees def test_str(): def call_str(o): return str(o) - t = Translator(call_str) - t.annotate([object]) - t.specialize() - #t.view() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(call_str)) - db.complete() - - module = compile_db(db) - - f1 = getattr(module, entrypoint) + f1 = compile(call_str, [object]) lst = (1, [5], "'hello'", lambda x: x+1) res = f1(lst) assert res == str(lst) - mallocs, frees = module.malloc_counters() - assert mallocs == frees + def test_rstr(): def fn(i): return "hello"[i] - t = Translator(fn) - t.annotate([int]) - t.specialize() - - db = LowLevelDatabase(t) - entrypoint = db.get(pyobjectptr(fn)) - db.complete() - - module = compile_db(db) - - f1 = getattr(module, entrypoint) + f1 = compile(fn, [int]) res = f1(1) assert res == 'e' - mallocs, frees = module.malloc_counters() - assert mallocs == frees From arigo at codespeak.net Thu Jul 7 20:16:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 20:16:33 +0200 (CEST) Subject: [pypy-svn] r14405 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050707181633.899F127B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 20:16:31 2005 New Revision: 14405 Modified: pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/test/test_fixedname.py Log: LL_os_open(), without exception support. Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 20:16:31 2005 @@ -1,11 +1,37 @@ /************************************************************/ /*** C header subsection: external functions ***/ +#include +#include +#include #include /* The functions below are mapped to functions from pypy.rpython.extfunctable by the pypy.translator.c.fixedname.EXTERNALS dictionary. */ +#define RPyString_GET_SIZE(rps) ((rps)->rs_chars.length) +#define RPyString_AS_STRING(rps) ((rps)->rs_chars.items) + + +int LL_os_open(RPyString *filename, int flag, int mode) +{ + char buf[PATH_MAX]; + int fd, error, namelen = RPyString_GET_SIZE(filename); + if (namelen >= PATH_MAX) { + error = ENAMETOOLONG; + } + else { + memcpy(buf, RPyString_AS_STRING(filename), namelen); + buf[namelen] = 0; + fd = open(buf, flag, mode); + if (fd != -1) + return fd; + error = errno; + } + /* XXX */ + Py_FatalError("oups, that gives an OSError"); +} + double LL_time_clock(void) { Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Thu Jul 7 20:16:31 2005 @@ -8,13 +8,14 @@ # table of functions hand-written in extfunc_include.h EXTERNALS = { + extfunctable.ll_os_open: 'LL_os_open', extfunctable.ll_time_clock: 'LL_time_clock', } def predeclare_common_types(db, rtyper): # Common types - yield ('RPyString', Ptr(STR)) + yield ('RPyString', STR) def predeclare_extfuncs(db, rtyper): @@ -67,7 +68,6 @@ return predeclare(c_name, getfunctionptr(db.translator, ll_func)) def predeclaretype(c_typename, lowleveltype): - assert isinstance(lowleveltype, Ptr) typename = db.gettype(lowleveltype) return 'typedef %s;' % cdecl(typename, c_typename) Modified: pypy/dist/pypy/translator/c/test/test_fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_fixedname.py (original) +++ pypy/dist/pypy/translator/c/test/test_fixedname.py Thu Jul 7 20:16:31 2005 @@ -1,4 +1,5 @@ import autopath +from pypy.tool.udir import udir from pypy.translator.c.test.test_genc import compile @@ -12,3 +13,16 @@ assert type(t1) is float t2 = time.clock() assert t0 <= t1 <= t2 + + +def test_os_open(): + import os + tmpfile = str(udir.join('test_os_open.txt')) + def does_stuff(): + fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) + return fd + + f1 = compile(does_stuff, []) + fd = f1() + os.close(fd) + assert os.path.exists(tmpfile) From arigo at codespeak.net Thu Jul 7 20:18:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 20:18:49 +0200 (CEST) Subject: [pypy-svn] r14406 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050707181849.95A2E27B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 20:18:47 2005 New Revision: 14406 Added: pypy/dist/pypy/translator/c/test/test_extfunc.py - copied unchanged from r14405, pypy/dist/pypy/translator/c/test/test_fixedname.py Removed: pypy/dist/pypy/translator/c/test/test_fixedname.py Modified: pypy/dist/pypy/translator/c/extfunc_include.h Log: Cosmetics of file and macro names. Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 20:18:47 2005 @@ -9,19 +9,19 @@ /* The functions below are mapped to functions from pypy.rpython.extfunctable by the pypy.translator.c.fixedname.EXTERNALS dictionary. */ -#define RPyString_GET_SIZE(rps) ((rps)->rs_chars.length) -#define RPyString_AS_STRING(rps) ((rps)->rs_chars.items) +#define RPyString_Size(rps) ((rps)->rs_chars.length) +#define RPyString_AsString(rps) ((rps)->rs_chars.items) int LL_os_open(RPyString *filename, int flag, int mode) { char buf[PATH_MAX]; - int fd, error, namelen = RPyString_GET_SIZE(filename); + int fd, error, namelen = RPyString_Size(filename); if (namelen >= PATH_MAX) { error = ENAMETOOLONG; } else { - memcpy(buf, RPyString_AS_STRING(filename), namelen); + memcpy(buf, RPyString_AsString(filename), namelen); buf[namelen] = 0; fd = open(buf, flag, mode); if (fd != -1) Deleted: /pypy/dist/pypy/translator/c/test/test_fixedname.py ============================================================================== --- /pypy/dist/pypy/translator/c/test/test_fixedname.py Thu Jul 7 20:18:47 2005 +++ (empty file) @@ -1,28 +0,0 @@ -import autopath -from pypy.tool.udir import udir -from pypy.translator.c.test.test_genc import compile - - -def test_time_clock(): - import time - def does_stuff(): - return time.clock() - f1 = compile(does_stuff, []) - t0 = time.clock() - t1 = f1() - assert type(t1) is float - t2 = time.clock() - assert t0 <= t1 <= t2 - - -def test_os_open(): - import os - tmpfile = str(udir.join('test_os_open.txt')) - def does_stuff(): - fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) - return fd - - f1 = compile(does_stuff, []) - fd = f1() - os.close(fd) - assert os.path.exists(tmpfile) From ericvrp at codespeak.net Thu Jul 7 20:23:59 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 20:23:59 +0200 (CEST) Subject: [pypy-svn] r14407 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050707182359.84D2227B39@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 20:23:58 2005 New Revision: 14407 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py Log: Fixed the amount of llvm code generated. Basicly working towards emitting just the code that is actually used (and its dependencies). This will need refactoring, especially the dict stored in LLVMNode. Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 20:23:58 2005 @@ -1,10 +1,7 @@ -extdeclarations = """; External declarations - - -; XXX these int's might need to be long's on 64 bit CPU's :( - +extdeclarations = """ declare sbyte* %gc_malloc(uint) declare sbyte* %gc_malloc_atomic(uint) + declare int %time(int*) ;void* actually declare int %clock() declare void %sleep(int) @@ -15,12 +12,9 @@ %st.rpy_string.0 = type {int, {int, [0 x sbyte]}} -; End of external declarations - """ -gc_boehm = """; Using Boehm GC - +gc_boehm = """ declare sbyte* %GC_malloc(uint) declare sbyte* %GC_malloc_atomic(uint) @@ -36,8 +30,7 @@ """ -gc_disabled = """; Using no GC - +gc_disabled = """ sbyte* %gc_malloc(uint %n) { %ptr = malloc sbyte, uint %n ret sbyte* %ptr @@ -50,8 +43,7 @@ """ -extfunctions = """; Helper function to convert LLVM <-> C types - +extfunctionshelpers = """ sbyte* %cast(%st.rpy_string.0* %structstring) { %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr @@ -71,14 +63,34 @@ ret sbyte* %dest } -; Wrapper functions that call external (C) functions +%st.rpy_string.0 * %new.st.var.rpy_string.0.helper(int %len) { + %size = getelementptr %st.rpy_string.0* null, int 0, uint 1, uint 1, int %len + %usize = cast sbyte* %size to uint + %malloc.Size.5 = getelementptr sbyte* null, uint %usize + %malloc.SizeU.5 = cast sbyte* %malloc.Size.5 to uint + %malloc.Ptr.5 = call sbyte* %gc_malloc(uint %malloc.SizeU.5) + %ptr = cast sbyte* %malloc.Ptr.5 to sbyte* + %result = cast sbyte* %ptr to %st.rpy_string.0* + %arraylength = getelementptr %st.rpy_string.0* %result, int 0, uint 1, uint 0 + store int %len, int* %arraylength + ret %st.rpy_string.0* %result +} + +""" + +extfunctions = {} + +extfunctions["%ll_time_time"] = """ double %ll_time_time() { %v0 = call int %time(int* null) %v1 = cast int %v0 to double ret double %v1 } +""" + +extfunctions["%ll_time_clock"] = """ double %ll_time_clock() { %v0 = call int %clock() %v1 = cast int %v0 to double @@ -87,12 +99,18 @@ ret double %v2 } +""" + +extfunctions["%ll_time_sleep"] = """ void %ll_time_sleep(double %f) { %i = cast double %f to int call void %sleep(int %i) ret void } +""" + +extfunctions["%ll_os_open"] = """ int %ll_os_open(%st.rpy_string.0* %structstring, int %pythonmode) { %flags = cast int %pythonmode to int %mode = cast int 384 to int ;S_IRUSR=256, S_IWUSR=128 @@ -101,6 +119,9 @@ ret int %fd } +""" + +extfunctions["%ll_os_write"] = """ int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) { %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr @@ -109,9 +130,12 @@ ret int %byteswritten } +""" + +extfunctions["%ll_os_read"] = """ %st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) { ;This is a bit simplistic! It really allocated a large enough buffer to hold all the data in. - %str = call %st.rpy_string.0* %new.st.var.rpy_string.0(int %buffersize) + %str = call %st.rpy_string.0* %new.st.var.rpy_string.0.helper(int %buffersize) ;load the actual data %destptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 1 @@ -125,5 +149,4 @@ ret %st.rpy_string.0* %str } -; End of external functions """ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 7 20:23:58 2005 @@ -199,6 +199,7 @@ def writeimpl(self, codewriter): if self.ref not in self.fnmapping: + self.used_external_functions[self.ref] = True return T = self.value._TYPE Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 7 20:23:58 2005 @@ -11,10 +11,11 @@ from pypy.rpython import lltype from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter +from pypy.translator.llvm2.node import LLVMNode from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.extfunction import extdeclarations, \ - extfunctions, gc_boehm, gc_disabled + extfunctionshelpers, extfunctions, gc_boehm, gc_disabled from pypy.translator.translator import Translator @@ -30,6 +31,7 @@ remove_void(translator) #rename_extfunc_calls(translator) translator.checkgraphs() + LLVMNode.used_external_functions = {} def compile(self, func=None): if func is None: @@ -64,20 +66,23 @@ #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() - if self.embedexterns: - for extfunc in extfunctions.split('\n'): - codewriter.append(extfunc) - if use_boehm_gc: gc_funcs = gc_boehm else: gc_funcs = gc_disabled for extfunc in gc_funcs.split('\n'): codewriter.append(extfunc) - + for typ_decl in self.db.getobjects(): typ_decl.writeimpl(codewriter) + if self.embedexterns: + for extfunchelper in extfunctionshelpers.split('\n'): + codewriter.append(extfunchelper) + for funcname,value in LLVMNode.used_external_functions.iteritems(): + for extfunc in extfunctions[funcname].split('\n'): + codewriter.append(extfunc) + comment("End of file") ; nl() self.content = str(codewriter) return self.content Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Thu Jul 7 20:23:58 2005 @@ -1,5 +1,7 @@ class LLVMNode(object): + used_external_functions = {} + def ref(): def _get_ref(self): return self._ref From arigo at codespeak.net Thu Jul 7 20:46:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 20:46:25 +0200 (CEST) Subject: [pypy-svn] r14408 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050707184625.0976527B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 20:46:20 2005 New Revision: 14408 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/test/test_extfunc.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Can now raise OSError from C code. Actually much easier than expected... if you remember that we can just have an ll_raise_OSError() helper defined by the RTyper. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Jul 7 20:46:20 2005 @@ -2,6 +2,7 @@ The code needed to flow and annotate low-level helpers -- the ll_*() functions """ +import types from pypy.annotation import model as annmodel from pypy.annotation.specialize import decide_callable from pypy.annotation.policy import BasicAnnotatorPolicy @@ -33,7 +34,7 @@ def specialize(pol, bookkeeper, spaceop, func, args, mono): args_s, kwds_s = args.unpack() assert not kwds_s - if not args_s: + if not args_s or not isinstance(func, types.FunctionType): return None, None key = [func] new_args_s = [] Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Thu Jul 7 20:46:20 2005 @@ -30,6 +30,7 @@ self.ll_exception_match = self.make_exception_matcher(rtyper) self.ll_type_of_exc_inst = self.make_type_of_exc_inst(rtyper) self.ll_pyexcclass2exc = self.make_pyexcclass2exc(rtyper) + self.ll_raise_OSError = self.make_raise_OSError(rtyper) def make_standard_exceptions(self, rtyper): @@ -47,6 +48,15 @@ return spec_function + def make_raise_OSError(self, rtyper): + # ll_raise_OSError(errno) + def ll_raise_OSError(errno): + raise OSError(errno, None) + dontcare, spec_function = annotate_lowlevel_helper( + rtyper.annotator, ll_raise_OSError, [annmodel.SomeInteger()]) + return spec_function + + def make_type_of_exc_inst(self, rtyper): # ll_type_of_exc_inst(exception_instance) -> exception_vtable s_excinst = annmodel.SomePtr(self.lltype_of_exception_value) Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 20:46:20 2005 @@ -28,8 +28,8 @@ return fd; error = errno; } - /* XXX */ - Py_FatalError("oups, that gives an OSError"); + RAISE_OSERROR(error); + return -1; } Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Thu Jul 7 20:46:20 2005 @@ -35,6 +35,7 @@ yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) + yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) for pyexccls in exceptiondata.standardexceptions: exc_llvalue = exceptiondata.ll_pyexcclass2exc(pyobjectptr(pyexccls)) Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Thu Jul 7 20:46:20 2005 @@ -1,4 +1,5 @@ import autopath +import py from pypy.tool.udir import udir from pypy.translator.c.test.test_genc import compile @@ -26,3 +27,14 @@ fd = f1() os.close(fd) assert os.path.exists(tmpfile) + +def test_failing_os_open(): + import os + tmpfile = str(udir.join('test_failing_os_open.DOESNTEXIST')) + def does_stuff(): + fd = os.open(tmpfile, os.O_RDONLY, 0777) + return fd + + f1 = compile(does_stuff, []) + py.test.raises(OSError, f1) + assert not os.path.exists(tmpfile) Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Thu Jul 7 20:46:20 2005 @@ -28,6 +28,7 @@ t = Translator(fn) t.annotate(argtypes) t.specialize() + t.backend_optimizations() db = LowLevelDatabase(t) entrypoint = db.get(pyobjectptr(fn)) db.complete() From ericvrp at codespeak.net Thu Jul 7 21:14:14 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Jul 2005 21:14:14 +0200 (CEST) Subject: [pypy-svn] r14409 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050707191414.2783127B3F@code1.codespeak.net> Author: ericvrp Date: Thu Jul 7 21:14:13 2005 New Revision: 14409 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/genllvm.py Log: Emitting just the required (wrapped) external functions and their helpers by checking the dependencies recusively. Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 7 21:14:13 2005 @@ -43,7 +43,9 @@ """ -extfunctionshelpers = """ +extfunctions = {} #dependencies, llvm-code + +extfunctions["%cast"] = ((), """ sbyte* %cast(%st.rpy_string.0* %structstring) { %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr @@ -63,6 +65,9 @@ ret sbyte* %dest } +""") + +extfunctions["%new.st.var.rpy_string.0.helper"] = ((), """ %st.rpy_string.0 * %new.st.var.rpy_string.0.helper(int %len) { %size = getelementptr %st.rpy_string.0* null, int 0, uint 1, uint 1, int %len %usize = cast sbyte* %size to uint @@ -76,21 +81,18 @@ ret %st.rpy_string.0* %result } -""" - - -extfunctions = {} +""") -extfunctions["%ll_time_time"] = """ +extfunctions["%ll_time_time"] = ((), """ double %ll_time_time() { %v0 = call int %time(int* null) %v1 = cast int %v0 to double ret double %v1 } -""" +""") -extfunctions["%ll_time_clock"] = """ +extfunctions["%ll_time_clock"] = ((), """ double %ll_time_clock() { %v0 = call int %clock() %v1 = cast int %v0 to double @@ -99,18 +101,18 @@ ret double %v2 } -""" +""") -extfunctions["%ll_time_sleep"] = """ +extfunctions["%ll_time_sleep"] = ((), """ void %ll_time_sleep(double %f) { %i = cast double %f to int call void %sleep(int %i) ret void } -""" +""") -extfunctions["%ll_os_open"] = """ +extfunctions["%ll_os_open"] = (("%cast",), """ int %ll_os_open(%st.rpy_string.0* %structstring, int %pythonmode) { %flags = cast int %pythonmode to int %mode = cast int 384 to int ;S_IRUSR=256, S_IWUSR=128 @@ -119,9 +121,9 @@ ret int %fd } -""" +""") -extfunctions["%ll_os_write"] = """ +extfunctions["%ll_os_write"] = (("%cast",), """ int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) { %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr @@ -130,9 +132,9 @@ ret int %byteswritten } -""" +""") -extfunctions["%ll_os_read"] = """ +extfunctions["%ll_os_read"] = (("%new.st.var.rpy_string.0.helper",), """ %st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) { ;This is a bit simplistic! It really allocated a large enough buffer to hold all the data in. %str = call %st.rpy_string.0* %new.st.var.rpy_string.0.helper(int %buffersize) @@ -149,4 +151,12 @@ ret %st.rpy_string.0* %str } -""" +""") + +def dependencies(funcname, deplist): + deplist.append(funcname) + if funcname in extfunctions: + for depfuncname in extfunctions[funcname][0]: + if depfuncname not in deplist: #avoid loops + dependencies(depfuncname, deplist) + return deplist Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 7 21:14:13 2005 @@ -15,7 +15,7 @@ from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.extfunction import extdeclarations, \ - extfunctionshelpers, extfunctions, gc_boehm, gc_disabled + extfunctions, gc_boehm, gc_disabled, dependencies from pypy.translator.translator import Translator @@ -76,12 +76,16 @@ for typ_decl in self.db.getobjects(): typ_decl.writeimpl(codewriter) - if self.embedexterns: - for extfunchelper in extfunctionshelpers.split('\n'): - codewriter.append(extfunchelper) - for funcname,value in LLVMNode.used_external_functions.iteritems(): - for extfunc in extfunctions[funcname].split('\n'): - codewriter.append(extfunc) + depdone = {} + for funcname,value in LLVMNode.used_external_functions.iteritems(): + deps = dependencies(funcname,[]) + deps.reverse() + for dep in deps: + if dep not in depdone: + llvm_code = extfunctions[dep][1] + for extfunc in llvm_code.split('\n'): + codewriter.append(extfunc) + depdone[dep] = True comment("End of file") ; nl() self.content = str(codewriter) From arigo at codespeak.net Thu Jul 7 21:16:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 21:16:26 +0200 (CEST) Subject: [pypy-svn] r14410 - pypy/dist/pypy/translator/c Message-ID: <20050707191626.5E3BC27B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 21:16:24 2005 New Revision: 14410 Modified: pypy/dist/pypy/translator/c/extfunc_include.h Log: Oups. Can't include this file if there is no RTyper (as in some tests). Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 21:16:24 2005 @@ -1,6 +1,11 @@ /************************************************************/ /*** C header subsection: external functions ***/ +/******************************************************************/ +#ifdef RPyString /* not defined if we don't have an RTyper */ +/******************************************************************/ + + #include #include #include @@ -37,3 +42,8 @@ { return ((double) clock()) / CLOCKS_PER_SEC; } + + +/******************************************************************/ +#endif /* RPyString */ +/******************************************************************/ From arigo at codespeak.net Thu Jul 7 21:20:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Jul 2005 21:20:19 +0200 (CEST) Subject: [pypy-svn] r14411 - pypy/dist/pypy/translator/c Message-ID: <20050707192019.9E29827B39@code1.codespeak.net> Author: arigo Date: Thu Jul 7 21:20:16 2005 New Revision: 14411 Modified: pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/g_exception.h Log: Oups again. Need a clean way to detect if we have an RTyper or not. Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 21:20:16 2005 @@ -2,7 +2,7 @@ /*** C header subsection: external functions ***/ /******************************************************************/ -#ifdef RPyString /* not defined if we don't have an RTyper */ +#ifdef HAVE_RTYPER /* not defined if we don't have an RTyper */ /******************************************************************/ @@ -45,5 +45,5 @@ /******************************************************************/ -#endif /* RPyString */ +#endif /* HAVE_RTYPER */ /******************************************************************/ Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Thu Jul 7 21:20:16 2005 @@ -72,6 +72,7 @@ typename = db.gettype(lowleveltype) return 'typedef %s;' % cdecl(typename, c_typename) + yield '#define HAVE_RTYPER' for c_name, obj in predeclare_all(db, rtyper): if isinstance(obj, LowLevelType): yield predeclaretype(c_name, obj) Modified: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- pypy/dist/pypy/translator/c/g_exception.h (original) +++ pypy/dist/pypy/translator/c/g_exception.h Thu Jul 7 21:20:16 2005 @@ -6,7 +6,7 @@ /******************************************************************/ -#ifdef RPYTHON_EXCEPTION_MATCH /* RPython version of exceptions */ +#ifdef HAVE_RTYPER /* RPython version of exceptions */ /******************************************************************/ static RPYTHON_EXCEPTION_VTABLE rpython_exc_type = NULL; @@ -96,5 +96,5 @@ PyErr_SetString(Py##exc, msg) /* pun */ /******************************************************************/ -#endif /* RPYTHON_EXCEPTION_MATCH */ +#endif /* HAVE_RTYPER */ /******************************************************************/ From tismer at codespeak.net Thu Jul 7 21:48:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 7 Jul 2005 21:48:16 +0200 (CEST) Subject: [pypy-svn] r14412 - in pypy/dist/pypy: objspace/std objspace/std/test rpython Message-ID: <20050707194816.AC11327B39@code1.codespeak.net> Author: tismer Date: Thu Jul 7 21:48:14 2005 New Revision: 14412 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py pypy/dist/pypy/rpython/rarithmetic.py Log: long objects are complete and pass all tests. Karatsuba isn't done, yet. Also we are currently stuck with 15 bits, because long division needs a signed type that can hold two digits *and* a sign. Temporarily, I had an extra class to emulate this, and all algorithms are tested to work at full bit size. I removed the class because I was not pleased with the overhead. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu Jul 7 21:48:14 2005 @@ -13,17 +13,23 @@ Digit = r_uint # already works: r_ushort Twodigits = r_uint -Stwodigits = int # the following describe a plain digit +# XXX at the moment we can't save this bit, +# or we would need a large enough type to hold +# the carry bits in _x_divrem SHIFT = (Twodigits.BITS // 2) - 1 MASK = int((1 << SHIFT) - 1) # find the correct type for carry/borrow -if Digit.BITS - SHIFT > 0: +if Digit.BITS - SHIFT >= 1: + # we have one more bit in Digit Carryadd = Digit + Stwodigits = int else: + # we need another Digit Carryadd = Twodigits + raise ValueError, "need a large enough type for Stwodigits" Carrymul = Twodigits # Debugging digit array access. @@ -31,7 +37,7 @@ # 0 == no check at all # 1 == check correct type # 2 == check for extra (ab)used bits -CHECK_DIGITS = 1 +CHECK_DIGITS = 2 if CHECK_DIGITS: class DigitArray(list): @@ -560,16 +566,16 @@ i = 0 carry = Carryadd(0) while i < size_b: - carry += a.digits[i] + b.digits[i] - z.digits[i] = carry & MASK + carry += Carryadd(a.digits[i]) + b.digits[i] + z.digits[i] = Digit(carry & MASK) carry >>= SHIFT i += 1 while i < size_a: carry += a.digits[i] - z.digits[i] = carry & MASK + z.digits[i] = Digit(carry & MASK) carry >>= SHIFT i += 1 - z.digits[i] = carry + z.digits[i] = Digit(carry) z._normalize() return z @@ -578,12 +584,12 @@ size_a = len(a.digits) size_b = len(b.digits) sign = 1 - borrow = Digit(0) + borrow = Carryadd(0) # Ensure a is the larger of the two: if size_a < size_b: sign = -1 - a,b=b, a + a, b = b, a size_a, size_b = size_b, size_a elif size_a == size_b: # Find highest digit where a and b differ: @@ -601,14 +607,14 @@ while i < size_b: # The following assumes unsigned arithmetic # works modulo 2**N for some N>SHIFT. - borrow = a.digits[i] - b.digits[i] - borrow - z.digits[i] = borrow & MASK + borrow = Carryadd(a.digits[i]) - b.digits[i] - borrow + z.digits[i] = Digit(borrow & MASK) borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 while i < size_a: borrow = a.digits[i] - borrow - z.digits[i] = borrow & MASK + z.digits[i] = Digit(borrow & MASK) borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 @@ -631,13 +637,13 @@ j = 0 while j < size_b: carry += z.digits[i + j] + b.digits[j] * f - z.digits[i + j] = carry & MASK - carry = carry >> SHIFT + z.digits[i + j] = Digit(carry & MASK) + carry >>= SHIFT j += 1 while carry != 0: assert i + j < size_a + size_b carry += z.digits[i + j] - z.digits[i + j] = carry & MASK + z.digits[i + j] = Digit(carry & MASK) carry >>= SHIFT j += 1 i += 1 @@ -657,7 +663,7 @@ while size >= 0: rem = (rem << SHIFT) + pin.digits[size] hi = rem // n - pout.digits[size] = hi + pout.digits[size] = Digit(hi) rem -= hi * n size -= 1 return rem @@ -684,102 +690,16 @@ i = 0 while i < size_a: carry += Twodigits(a.digits[i]) * n - z.digits[i] = carry & MASK + z.digits[i] = Digit(carry & MASK) carry >>= SHIFT i += 1 - z.digits[i] = carry + z.digits[i] = Digit(carry) z._normalize() return z -# for the carry in _x_divrem, we need something that can hold -# two digits plus a sign. -# for the time being, we here implement such a 33 bit number just -# for the purpose of the division. -# In the long term, it might be considered to implement the -# notation of a "double anything" unsigned type, which could -# be used recursively to implement longs of any size. - -class r_suint(object): - # we do not inherit from Digit, because we only - # support a few operations for our purpose - BITS = Twodigits.BITS - MASK = Twodigits.MASK - - def __init__(self, value=0): - if isinstance(value, r_suint): - self.value = value.value - self.sign = value.sign - else: - self.value = Twodigits(value) - self.sign = -(value < 0) - - def longval(self): - if self.sign: - return -long(-self.value) - else: - return long(self.value) - - def __repr__(self): - return repr(self.longval()) - - def __str__(self): - return str(self.longval()) - - def __iadd__(self, other): - hold = self.value - self.value += other - self.sign ^= - ( (other < 0) != (self.value < hold) ) - return self - - def __add__(self, other): - res = r_suint(self) - res += other - return res - - def __isub__(self, other): - hold = self.value - self.value -= other - self.sign ^= - ( (other < 0) != (self.value > hold) ) - return self - - def __sub__(self, other): - res = r_suint(self) - res -= other - return res - - def __irshift__(self, n): - self.value >>= n - if self.sign: - self.value += self.MASK << (self.BITS - n) - return self - - def __rshift__(self, n): - res = r_suint(self) - res >>= n - return res - - def __ilshift__(self, n): - self.value <<= n - return self - - def __lshift__(self, n): - res = r_suint(self) - res <<= n - return res - - def __and__(self, mask): - # only used to get bits from the value - return self.value & mask - - def __eq__(self, other): - if not isinstance(other, r_suint): - other = r_suint(other) - return self.sign == other.sign and self.value == other.value - - def __ne__(self, other): - return not self == other def _x_divrem(v1, w1): + """ Unsigned long division with remainder -- the algorithm """ size_w = len(w1.digits) d = Digit(Twodigits(MASK+1) // (w1.digits[size_w-1] + 1)) v = _muladd1(v1, d, Digit(0)) @@ -798,7 +718,7 @@ vj = Digit(0) else: vj = v.digits[j] - carry = r_suint(0) # note: this must hold two digits and a sign! + carry = Stwodigits(0) # note: this must hold two digits and a sign! if vj == w.digits[size_w-1]: q = Twodigits(MASK) @@ -810,51 +730,40 @@ # or we get an overflow. while (w.digits[size_w-2] * q > (( - r_suint(vj << SHIFT) # this one dominates - + v.digits[j-1] - - long(q) * long(w.digits[size_w-1]) + (Stwodigits(vj) << SHIFT) # this one dominates + + Stwodigits(v.digits[j-1]) + - Stwodigits(q) * Stwodigits(w.digits[size_w-1]) ) << SHIFT) - + v.digits[j-2]): + + Stwodigits(v.digits[j-2])): q -= 1 i = 0 while i < size_w and i+k < size_v: - z = w.digits[i] * q + z = Stwodigits(w.digits[i] * q) zz = z >> SHIFT - carry += v.digits[i+k] + (zz << SHIFT) - carry -= z - if hasattr(carry, 'value'): - v.digits[i+k] = Digit(carry.value & MASK) - else: - v.digits[i+k] = Digit(carry & MASK) + carry += Stwodigits(v.digits[i+k]) - z + (zz << SHIFT) + v.digits[i+k] = Digit(carry & MASK) carry >>= SHIFT carry -= zz i += 1 if i+k < size_v: - carry += v.digits[i+k] + carry += Stwodigits(v.digits[i+k]) v.digits[i+k] = Digit(0) if carry == 0: - a.digits[k] = q & MASK + a.digits[k] = Digit(q & MASK) assert not q >> SHIFT else: - #assert carry == -1 - if carry != -1: - print 70*"*" - print "CARRY", carry - print "comparison:", carry == -1 - print hex(v1.longval()) - print hex(w1.longval()) - print 70*"*" + assert carry == -1 q -= 1 - a.digits[k] = q-1 & MASK + a.digits[k] = Digit(q & MASK) assert not q >> SHIFT - carry = r_suint(0) + carry = Stwodigits(0) i = 0 while i < size_w and i+k < size_v: - carry += v.digits[i+k] + w.digits[i] - v.digits[i+k] = Digit(carry.value) & MASK + carry += Stwodigits(v.digits[i+k]) + Stwodigits(w.digits[i]) + v.digits[i+k] = Digit(carry & MASK) carry >>= SHIFT i += 1 j -= 1 @@ -1049,7 +958,7 @@ while i > 1: bits += 1 i >>= 1 - i = 5 + int(bool(addL)) + (size_a*LONG_BIT + bits-1) // bits + i = 5 + int(bool(addL)) + (size_a*SHIFT + bits-1) // bits s = [chr(0)] * i p = i if addL: @@ -1104,10 +1013,10 @@ powbase = Digit(base) # powbase == base ** power power = 1 while 1: - newpow = powbase * Digit(base) + newpow = Twodigits(powbase) * Digit(base) if newpow >> SHIFT: # doesn't fit in a digit break - powbase = newpow + powbase = Digit(newpow) power += 1 # Get a scratch area for repeated division. @@ -1144,7 +1053,7 @@ break if base == 8: - if size_a != 0: + if a.sign != 0: p -= 1 s[p] = '0' elif base == 16: 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 Thu Jul 7 21:48:14 2005 @@ -329,7 +329,6 @@ y >>= s2*16 x = 0x3FE0003FFFFC0001FFFL y = 0x9800FFC1L - print "special case" check_division(x, y) raises(ZeroDivisionError, "x // 0L") Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Thu Jul 7 21:48:14 2005 @@ -328,10 +328,12 @@ return _widen(self, other, res) class r_ushort(r_uint): + """ fake unsigned short integer implementation """ BITS = r_uint.BITS // 2 MASK = (1L << BITS) - 1 class r_ulong(r_uint): + """ fake unsigned long integer implementation """ BITS = r_uint.BITS * 2 MASK = (1L << BITS) - 1 From tismer at codespeak.net Thu Jul 7 22:23:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 7 Jul 2005 22:23:20 +0200 (CEST) Subject: [pypy-svn] r14413 - pypy/dist/pypy/rpython Message-ID: <20050707202320.7527527B3B@code1.codespeak.net> Author: tismer Date: Thu Jul 7 22:23:19 2005 New Revision: 14413 Modified: pypy/dist/pypy/rpython/rtyper.py Log: added block shuffling to the rtyper. Instructions: set the environment variable 'RTYPERSEED' to a number. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 7 22:23:19 2005 @@ -12,7 +12,7 @@ """ from __future__ import generators -import sys +import sys, os import py from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel @@ -50,6 +50,14 @@ r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r self.exceptiondata = ExceptionData(self) + try: + self.seed = int(os.getenv('RTYPERSEED')) + s = 'Using %d as seed for block shuffling' % self.seed + print '*' * len(s) + print s + print '*' * len(s) + except: + self.seed = 0 def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -99,6 +107,11 @@ if block not in self.already_seen] if not pending: break + # shuffle blocks a bit + if self.seed: + import random + r = random.Random(self.seed) + r.shuffle(pending) # specialize all blocks in the 'pending' list for block in pending: self.specialize_block(block) From tismer at codespeak.net Thu Jul 7 22:45:37 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 7 Jul 2005 22:45:37 +0200 (CEST) Subject: [pypy-svn] r14414 - pypy/dist/pypy/translator/c Message-ID: <20050707204537.02D3F27B3B@code1.codespeak.net> Author: tismer Date: Thu Jul 7 22:45:37 2005 New Revision: 14414 Modified: pypy/dist/pypy/translator/c/extfunc_include.h Log: hack to support windows Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Thu Jul 7 22:45:37 2005 @@ -10,6 +10,10 @@ #include #include #include +#ifndef PATH_MAX + /* assume windows */ + #define PATH_MAX 254 +#endif /* The functions below are mapped to functions from pypy.rpython.extfunctable by the pypy.translator.c.fixedname.EXTERNALS dictionary. */ From ludal at codespeak.net Thu Jul 7 23:12:48 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 7 Jul 2005 23:12:48 +0200 (CEST) Subject: [pypy-svn] r14415 - pypy/dist/pypy/documentation Message-ID: <20050707211248.42A7B27B3B@code1.codespeak.net> Author: ludal Date: Thu Jul 7 23:12:46 2005 New Revision: 14415 Added: pypy/dist/pypy/documentation/parser-design.txt Log: first draft Added: pypy/dist/pypy/documentation/parser-design.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/parser-design.txt Thu Jul 7 23:12:46 2005 @@ -0,0 +1,160 @@ + +================== +PyPy parser design +================== + + +Overview +======== + +The PyPy parser includes a tokenizer and a recursive descent parser. + +Tokenizer +--------- + +The tokenizer accepts as string as input and provides tokens through +a ``next()`` and a ``peek()`` method. The tokenizer is implemented as a finite +automata like lex. + +Parser +------ + +The parser is a tree of grammar rules. EBNF grammar rules are decomposed +as a tree of objects. +Looking at a grammar rule one can see it is composed of a set of four basic +subrules. In the following exemple we have all four of them: + +S <- A '+' (C | D) + + + +The previous line says S is a sequence of symbol A, token '+', a subrule + which +matches one or more of an alternative between symbol C and symbol D. +Thus the four basic grammar rule types are : +* sequence +* alternative +* multiplicity (called kleen star after the * multiplicity type) +* token + +The four types are represented by a class in pyparser/grammar.py +( Sequence, Alternative, KleenStar, Token) all classes have a ``match()`` method +accepting a source (the tokenizer) and a builder (an object responsible for +building something out of the grammar). + +Here's a basic exemple and how the grammar is represented:: + + S <- A ('+'|'-') A + A <- V ( ('*'|'/') V )* + V <- 'x' | 'y' + + In python: + V = Alternative( Token('x'), Token('y') ) + A = Sequence( V, + KleenStar( + Sequence( + Alternative( Token('*'), Token('/') ), V + ) + ) + ) + S = Sequence( A, Alternative( Token('+'), Token('-') ), A ) + + +Detailed design +=============== + +Building the Python grammar +--------------------------- + +The python grammar is built at startup from the pristine CPython grammar file. +The grammar framework is first used to build a simple grammar to parse the +grammar itself. +The builder provided to the parser generates another grammar which is the Python +grammar itself. +The grammar file should represent an LL(1) grammar. LL(k) should still work since +the parser supports backtracking through the use of source and builder contexts +(The memento patterns for those who like Design Patterns) + +The match function for a sequence is pretty simple:: + + for each rule in the sequence: + save the source and builder context + if the rule doesn't match: + restore the source and builder context + return false + call the builder method to build the sequence + return true + +Now this really is an LL(0) grammar since it explores the whole tree of rule +possibilities. +In fact there is another member of the rule objects which is built once the +grammar is complete. +This member is a set of the tokens that match the begining of each rule. Like +the grammar it is precomputed at startup. +Then each rule starts by the following test:: + + if source.peek() not in self.firstset: return false + + +Efficiency should be similar (not too worse) to an automata based grammar since it is +basicly building an automata but it uses the execution stack to store its parsing state. +This also means that recursion in the grammar are directly translated as recursive calls. + + +Redisigning the parser to remove recursion shouldn't be difficult but would make the code +less obvious. (patches welcome). The basic idea + + +Parsing +------- + +This grammar is then used to parse Python input and transform it into a syntax tree. + +As of now the syntax tree is built as a tuple to match the output of the parser module +and feed it to the compiler package + +the compiler package uses the Transformer class to transform this tuple tree into an +abstract syntax tree. + +sticking to our previous example, the syntax tree for x+x*y would be:: + + Rule('S', nodes=[ + Rule('A',nodes=[Rule('V', nodes=[Token('x')])]), + Token('+'), + Rule('A',nodes=[ + Rule('V', nodes=[Token('x')]), + Token('*'), + Rule('V', nodes=[Token('y')]) + ]) + ]) + + +The abstract syntax tree for the same expression would look like:: + + Add(Var('x'),Mul(Var('x'),Var('y'))) + + + +Examples using the parser within PyPy +------------------------------------- + + +API Quickref +------------ + +Modules + +Main facade functions + +Grammar + + +Long term goals +=============== + +parser implementation + +compiler implementation + +parser module + +compiler module + From ludal at codespeak.net Fri Jul 8 01:26:41 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 8 Jul 2005 01:26:41 +0200 (CEST) Subject: [pypy-svn] r14416 - in pypy/dist/pypy/interpreter: astcompiler pyparser pyparser/test Message-ID: <20050707232641.9450B27B3B@code1.codespeak.net> Author: ludal Date: Fri Jul 8 01:26:38 2005 New Revision: 14416 Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/dist/pypy/interpreter/astcompiler/astgen.py pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: more work on astbuilder Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.py Fri Jul 8 01:26:38 2005 @@ -33,6 +33,13 @@ pass # implemented by subclasses def visit(self, visitor, *args): return visitor.visitNode(self, *args) + def __eq__(self, right): + if type(self)!=type(right): + return False + for i,j in zip(self.getChildren(),right.getChildren()): + if not i==j: + return False + return True class EmptyNode(Node): def visit(self, visitor, *args): Modified: pypy/dist/pypy/interpreter/astcompiler/astgen.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/astgen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/astgen.py Fri Jul 8 01:26:38 2005 @@ -296,6 +296,13 @@ pass # implemented by subclasses def visit(self, visitor, *args): return visitor.visitNode(self, *args) + def __eq__(self, right): + if type(self)!=type(right): + return False + for i,j in zip(self.getChildren(),right.getChildren()): + if not i==j: + return False + return True class EmptyNode(Node): def visit(self, visitor, *args): Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Fri Jul 8 01:26:38 2005 @@ -1,7 +1,28 @@ from grammar import BaseGrammarBuilder -import pypy.interpreter.astcompiler.ast as ast +from pypy.interpreter.astcompiler import ast, consts + +## these tests should be methods of the ast objects + +def is_lvalue( ast_node ): + return True + +def to_lvalue( ast_node, OP ): + if isinstance( ast_node, ast.Name ): + return ast.AssName( ast_node.name, OP ) + else: + assert False, "TODO" + +def is_augassign( ast_node ): + if ( isinstance( ast_node, ast.Name ) or + isinstance( ast_node, ast.Slice ) or + isinstance( ast_node, ast.Subscript ) or + isinstance( ast_node, ast.Getattr ) ): + return True + return False + +## building functions def get_atoms( builder, nb ): L = [] @@ -108,7 +129,100 @@ raise ValueError, "unexpected token: %s : %s" % L[i-1] builder.push( left ) + +def build_binary_expr( builder, nb, OP ): + L = get_atoms( builder, nb ) + l = len(L) + if l==1: + builder.push( L[0] ) + return + items = [] + for i in range(0,l,2): # this is L not 1 + items.append( L[i] ) + builder.push( OP( items ) ) + return + +def build_and_expr( builder, nb ): + return build_binary_expr( builder, nb, ast.Bitand ) + +def build_xor_expr( builder, nb ): + return build_binary_expr( builder, nb, ast.Bitxor ) + +def build_expr( builder, nb ): + return build_binary_expr( builder, nb, ast.Bitor ) + +def build_comparison( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + if l==1: + builder.push( L[0] ) + return + # TODO + assert False + +def build_and_test( builder, nb ): + return build_binary_expr( builder, nb, ast.And ) + +def build_test( builder, nb ): + return build_binary_expr( builder, nb, ast.Or ) + +def build_testlist( builder, nb ): + return build_binary_expr( builder, nb, ast.Tuple ) + +def build_not_test( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + if l==1: + builder.push( L[0] ) + return + +def build_expr_stmt( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + if l==1: + builder.push( ast.Discard( L[0] ) ) + return + op = L[1] + if op.name == '=': + nodes = [] + for i in range(0,l-2,2): + lvalue = to_lvalue( L[i], consts.OP_ASSIGN ) + nodes.append( lvalue ) + rvalue = L[-1] + builder.push( ast.Assign( nodes, rvalue ) ) + pass + else: + assert l==3 + lvalue = L[0] + assert is_augassign( lvalue ) + builder.push( ast.AugAssign( lvalue, op, L[2] ) ) + +def return_one( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + if l==1: + builder.push( L[0] ) + return + raise WalkerError("missing one node in stack") + +def build_simple_stmt( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + nodes = [] + for n in range(0,l,2): + nodes.append(L[n]) + builder.push( ast.Stmt( nodes ) ) + return + +def build_single_input( builder, nb ): + L = get_atoms( builder, nb ) + l = len(L) + if l>=1: + builder.push( ast.Module( None, L[0] ) ) + return + raise WalkerError("error") + ASTRULES = { # "single_input" : build_single_input, "atom" : build_atom, @@ -117,6 +231,17 @@ "term" : build_term, "arith_expr" : build_arith_expr, "shift_expr" : build_shift_expr, + "and_expr" : build_and_expr, + "xor_expr" : build_xor_expr, + "expr" : build_expr, + "comparison" : build_comparison, + "and_test" : build_and_test, + "test" : build_test, + "testlist" : build_testlist, + "expr_stmt" : build_expr_stmt, + "small_stmt" : return_one, + "simple_stmt" : build_simple_stmt, + "single_input" : build_single_input, } class RuleObject(ast.Node): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Fri Jul 8 01:26:38 2005 @@ -5,10 +5,38 @@ from pypy.interpreter.stablecompiler.transformer import Transformer import py.test -expr1 = "x = a + 1" - - +from pypy.interpreter.astcompiler import ast +expressions = [ + "x = a + 1", + "x = 1 - a", + "x = a * b", + "x = a ** 2", + "x = a / b", + "x = a & b", + "x = a | b", + "x = a ^ b", + "x = a // b", + "x = a * b + 1", + "x = a + 1 * b", + "x = a * b / c", + "x = a * (1 + c)", + "f = lambda x: x+1", + "x, y, z = 1, 2, 3", +] +expression_tests = [ 0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, ] # = range(len(expressions)) +failed_expression_tests = [ 12, 13, 14 ] + +comparisons = [ + "a < b", + "a > b", + "a not in b", + "a in b", + "3 < x < 5", + "(3 < x) < 5", + ] +comparison_tests = [] +failed_comparison_tests = range( len(comparisons) ) def ast_parse_expr( expr ): builder = AstBuilder() PYTHON_PARSER.parse_source( expr, "single_input", builder ) @@ -18,9 +46,19 @@ t = Transformer() return ast_from_input( expr, "single", t ) -def test_expr1(): - py.test.skip("work in progress") - r1 = ast_parse_expr( expr1 ) - ast = tuple_parse_expr( expr1 ) - print ast - +def check_expression( expr ): + r1 = ast_parse_expr( expr ) + ast = tuple_parse_expr( expr ) + print "ORIG :", ast + print "BUILT:", r1.rule_stack[-1] + assert ast == r1.rule_stack[-1] + +def test_expressions(): +## py.test.skip("work in progress") + for i in expression_tests: + yield check_expression, expressions[i] + +def test_comparisons(): +## py.test.skip("work in progress") + for i in comparison_tests: + yield check_expression, comparisons[i] From arigo at codespeak.net Sat Jul 9 12:58:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Jul 2005 12:58:55 +0200 (CEST) Subject: [pypy-svn] r14447 - in pypy/dist/pypy/rpython: . test Message-ID: <20050709105855.D0A8E27B41@code1.codespeak.net> Author: arigo Date: Sat Jul 9 12:58:50 2005 New Revision: 14447 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: - implemented ''.join() on a list of characters (with empty ''), and special-cased ''.join() on a list of strings. Still missing: sep.join() on a list of characters. - modified BuiltinMethodRepr to handle itself Constant bound methods, so that we don't have to care any more for bound method objects in rtype_method_xxx() and convert_const(). - fixed a comment in lltype.py. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sat Jul 9 12:58:50 2005 @@ -559,7 +559,7 @@ return _expose(o) raise TypeError("%r instance is not an array" % (self._T,)) - def __setitem__(self, i, val): # ! not allowed ! + def __setitem__(self, i, val): if isinstance(self._T, Array): T1 = self._T.OF if isinstance(T1, ContainerType): Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jul 9 12:58:50 2005 @@ -4,7 +4,7 @@ from pypy.rpython import rarithmetic from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, Constant from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr, FloatRepr @@ -21,8 +21,7 @@ else: # built-in method case assert self.methodname is not None - return BuiltinMethodRepr(rtyper.getrepr(self.s_self), - self.methodname) + return BuiltinMethodRepr(rtyper, self.s_self, self.methodname) def rtyper_makekey(self): if self.s_self is None: # built-in function case @@ -51,11 +50,12 @@ class BuiltinMethodRepr(Repr): - def __init__(self, self_repr, methodname): - self.self_repr = self_repr + def __init__(self, rtyper, s_self, methodname): + self.s_self = s_self + self.self_repr = rtyper.getrepr(s_self) self.methodname = methodname # methods of a known name are implemented as just their 'self' - self.lowleveltype = self_repr.lowleveltype + self.lowleveltype = self.self_repr.lowleveltype def rtype_simple_call(self, hop): # methods: look up the rtype_method_xxx() @@ -68,6 +68,10 @@ # hack based on the fact that 'lowleveltype == self_repr.lowleveltype' hop2 = hop.copy() assert hop2.args_r[0] is self + if isinstance(hop2.args_v[0], Constant): + c = hop2.args_v[0].value # get object from bound method + hop2.args_v[0] = Constant(c.__self__) + hop2.args_s[0] = self.s_self hop2.args_r[0] = self.self_repr return bltintyper(hop2) Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sat Jul 9 12:58:50 2005 @@ -45,7 +45,7 @@ def convert_const(self, dictobj): # get object from bound dict methods - dictobj = getattr(dictobj, '__self__', dictobj) + #dictobj = getattr(dictobj, '__self__', dictobj) if not isinstance(dictobj, dict): raise TyperError("expected a dict: %r" % (dictobj,)) try: Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jul 9 12:58:50 2005 @@ -77,7 +77,7 @@ def convert_const(self, dictobj): # get object from bound dict methods - dictobj = getattr(dictobj, '__self__', dictobj) + #dictobj = getattr(dictobj, '__self__', dictobj) if not isinstance(dictobj, dict): raise TyperError("expected a dict: %r" % (dictobj,)) try: Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jul 9 12:58:50 2005 @@ -61,7 +61,7 @@ def convert_const(self, listobj): # get object from bound list method - listobj = getattr(listobj, '__self__', listobj) + #listobj = getattr(listobj, '__self__', listobj) if not isinstance(listobj, list): raise TyperError("expected a list: %r" % (listobj,)) try: Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 9 12:58:50 2005 @@ -59,7 +59,7 @@ def convert_const(self, value): if value is None: return nullptr(STR) - value = getattr(value, '__self__', value) # for bound string methods + #value = getattr(value, '__self__', value) # for bound string methods if not isinstance(value, str): raise TyperError("not a str: %r" % (value,)) try: @@ -119,17 +119,27 @@ return hop.gendirectcall(ll_lower, v_str) def rtype_method_join(_, hop): + if hop.s_result.is_constant(): + return inputconst(string_repr, hop.s_result.const) r_lst = hop.args_r[1] - s_item = r_lst.listitem.s_value - if s_item == annmodel.SomeImpossibleValue(): - return inputconst(string_repr, "") - elif not s_item.__class__ == annmodel.SomeString: - raise TyperError("join of non-string list: %r" % r_lst) v_str, v_lst = hop.inputargs(string_repr, r_lst) cname = inputconst(Void, "items") v_items = hop.genop("getfield", [v_lst, cname], - resulttype=Ptr(GcArray(Ptr(STR)))) - return hop.gendirectcall(ll_join, v_str, v_items) + resulttype=r_lst.lowleveltype.TO.items) + if hop.args_s[0].is_constant() and hop.args_s[0].const == '': + if r_lst.item_repr == string_repr: + llfn = ll_join_strs + elif r_lst.item_repr == char_repr: + llfn = ll_join_chars + else: + raise TyperError("''.join() of non-string list: %r" % r_lst) + return hop.gendirectcall(llfn, v_items) + else: + if r_lst.item_repr == string_repr: + llfn = ll_join + else: + raise TyperError("sep.join() of non-string list: %r" % r_lst) + return hop.gendirectcall(llfn, v_str, v_items) def rtype_method_split(_, hop): v_str, v_chr = hop.inputargs(string_repr, char_repr) @@ -299,7 +309,7 @@ i = inputconst(Signed, i) hop.genop('setarrayitem', [vtemp, i, vchunk]) - return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp) + return hop.gendirectcall(ll_join_strs, vtemp) class __extend__(pairtype(StringRepr, TupleRepr)): @@ -698,6 +708,38 @@ i += 1 return result +def ll_join_strs(items): + num_items = len(items) + 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(chars): + num_chars = len(chars) + 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) 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 Jul 9 12:58:50 2005 @@ -209,6 +209,12 @@ 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" def fn(i, j): s1 = [ '', ',', ' and '] From pedronis at codespeak.net Sun Jul 10 01:56:14 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 01:56:14 +0200 (CEST) Subject: [pypy-svn] r14460 - pypy/dist/pypy/rpython Message-ID: <20050709235614.6337927B3F@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 01:56:13 2005 New Revision: 14460 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/llinterp.py Log: going in the direction of having llannotatable True by default (with appropriately written testing implementations for the ll_* defs for external functions this should work "out-of-the-box"). Flag suggested_primitive to avoid infinite interpretation in llinterp. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun Jul 10 01:56:13 2005 @@ -34,11 +34,12 @@ return p def from_rstr(rs): - return ''.join(rs.chars) + return ''.join([rs.chars[i] for i in range(len(rs.chars))]) # dummy low-level implementations for the external functions def ll_os_open(fname, flag, mode): return os.open(from_rstr(fname), flag, mode) +ll_os_open.suggested_primitive=True def ll_os_read(fd, n): return to_rstr(os.read(fd, n)) @@ -68,7 +69,7 @@ nonefactory = lambda *args: None # external function declarations -declare(os.open , int , ll_os_open) +declare(os.open , int , ll_os_open, True) declare(os.read , str , ll_os_read) declare(os.write , int , ll_os_write) declare(os.close , nonefactory, ll_os_close) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Jul 10 01:56:13 2005 @@ -166,13 +166,16 @@ array[index] = item def op_direct_call(self, f, *args): + has_callable = hasattr(f._obj, '_callable') + if has_callable and getattr(f._obj._callable, 'suggested_primitive', False): + return f._obj._callable(*args) if hasattr(f._obj, 'graph'): graph = f._obj.graph else: try: graph = self.llinterpreter.getgraph(f._obj._callable) except KeyError: - assert hasattr(f._obj, '_callable'), "don't know how to execute %r" % f + assert has_callable, "don't know how to execute %r" % f return f._obj._callable(*args) frame = self.__class__(graph, args, self.llinterpreter) return frame.eval() From pedronis at codespeak.net Sun Jul 10 03:07:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 03:07:34 +0200 (CEST) Subject: [pypy-svn] r14461 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050710010734.EBDEE27B3C@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 03:07:33 2005 New Revision: 14461 Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: give these tests a better chance to work Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Sun Jul 10 03:07:33 2005 @@ -55,7 +55,7 @@ import os def openclose(a,b,c,d,e,f): s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT|os.O_RDWR) + fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) os.close(fd) return fd @@ -72,7 +72,7 @@ import os def openwriteclose(a,b,c,d,e,f): s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT|os.O_RDWR) + fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) byteswritten = os.write(fd, s) os.close(fd) return byteswritten @@ -92,11 +92,11 @@ def openwriteclose_openreadclose(a,b,c,d,e,f): s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT|os.O_RDWR) + fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) byteswritten = os.write(fd, s+s+s) os.close(fd) - fd = os.open(s, os.O_RDWR) + fd = os.open(s, os.O_RDWR, 0777) maxread = 1000 r = os.read(fd, maxread) os.close(fd) From pedronis at codespeak.net Sun Jul 10 03:20:45 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 03:20:45 +0200 (CEST) Subject: [pypy-svn] r14462 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050710012045.0F6F927B41@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 03:20:44 2005 New Revision: 14462 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: fix. Trusting names instead of functions' identity is a bit fragile. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 10 03:20:44 2005 @@ -89,7 +89,8 @@ type_ = lltype.typeOf(value) node = None if isinstance(type_, lltype.FuncType): - if ((not hasattr(value, "graph")) or value.graph is None) and value._callable: + if value._callable and (not hasattr(value, "graph") or value.graph is None + or getattr(value._callable, "suggested_primitive", False)): node = ExternalFuncNode(self, value) else: node = FuncNode(self, value) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 10 03:20:44 2005 @@ -167,7 +167,7 @@ def __init__(self, db, value): self.db = db self.value = value - self.ref = "%" + value._name + self.ref = "%" + value._callable.__name__ def setup(self): self._issetup = True From pedronis at codespeak.net Sun Jul 10 04:35:58 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 04:35:58 +0200 (CEST) Subject: [pypy-svn] r14463 - pypy/dist/pypy/rpython Message-ID: <20050710023558.109C627B3F@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 04:35:57 2005 New Revision: 14463 Modified: pypy/dist/pypy/rpython/llinterp.py Log: _callable should always be present but can be None Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Jul 10 04:35:57 2005 @@ -166,7 +166,7 @@ array[index] = item def op_direct_call(self, f, *args): - has_callable = hasattr(f._obj, '_callable') + has_callable = getattr(f._obj, '_callable', None) is not None if has_callable and getattr(f._obj._callable, 'suggested_primitive', False): return f._obj._callable(*args) if hasattr(f._obj, 'graph'): From arigo at codespeak.net Sun Jul 10 12:47:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Jul 2005 12:47:26 +0200 (CEST) Subject: [pypy-svn] r14464 - in pypy/dist/pypy/translator: . c Message-ID: <20050710104726.6688427B41@code1.codespeak.net> Author: arigo Date: Sun Jul 10 12:47:23 2005 New Revision: 14464 Modified: pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/gensupp.py Log: Generate struct names with always a number at the end. This is both to avoid potential conflicts with predefined structures, and because it's less surprizing to have e.g. array structures called 'array0', 'array1', 'array2'... instead of 'array', 'array_1', 'array_2'. Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sun Jul 10 12:47:23 2005 @@ -36,10 +36,12 @@ varlength = self.varlength if varlength == 1: basename = STRUCT._name + with_number = True else: basename = db.gettypedefnode(STRUCT).name basename = '%s_len%d' % (basename, varlength) - self.name = db.namespace.uniquename(basename) + with_number = False + self.name = db.namespace.uniquename(basename, with_number=with_number) self.dependencies = {} self.fields = [] self.prefix = somelettersfrom(STRUCT._name) + '_' @@ -178,10 +180,12 @@ varlength = self.varlength if varlength == 1: basename = 'array' + with_number = True else: basename = db.gettypedefnode(ARRAY).name basename = '%s_len%d' % (basename, varlength) - self.name = db.namespace.uniquename(basename) + with_number = False + self.name = db.namespace.uniquename(basename, with_number=with_number) self.dependencies = {} self.itemtypename = db.gettype(ARRAY.OF, who_asks=self) Modified: pypy/dist/pypy/translator/gensupp.py ============================================================================== --- pypy/dist/pypy/translator/gensupp.py (original) +++ pypy/dist/pypy/translator/gensupp.py Sun Jul 10 12:47:23 2005 @@ -99,11 +99,13 @@ raise NameError, "%s has already been seen!" self.seennames[name] = 1 - def uniquename(self, basename): + def uniquename(self, basename, with_number=None): basename = basename.translate(C_IDENTIFIER) n = self.seennames.get(basename, 0) self.seennames[basename] = n+1 - if basename in ('v', 'w_'): + if with_number is None: + with_number = basename in ('v', 'w_') + if with_number: if n == 0: return '%s%d' % (basename, n) else: From arigo at codespeak.net Sun Jul 10 13:49:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Jul 2005 13:49:58 +0200 (CEST) Subject: [pypy-svn] r14469 - in pypy/dist/pypy: rpython rpython/module rpython/module/test translator/c Message-ID: <20050710114958.A76D927B41@code1.codespeak.net> Author: arigo Date: Sun Jul 10 13:49:53 2005 New Revision: 14469 Added: pypy/dist/pypy/rpython/module/ (props changed) pypy/dist/pypy/rpython/module/__init__.py (contents, props changed) pypy/dist/pypy/rpython/module/ll_os.py (contents, props changed) pypy/dist/pypy/rpython/module/ll_time.py (contents, props changed) pypy/dist/pypy/rpython/module/test/ (props changed) pypy/dist/pypy/rpython/module/test/__init__.py (contents, props changed) pypy/dist/pypy/rpython/module/test/test_ll_os.py (contents, props changed) Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/node.py Log: Trying to write a bit more for ll_os_read(), I ran into circular import problems which have prompted this refactoring (which would have been done soon anyway): the ll_xxx() functions are grouped by module, in a 'rpython/module/' subdirectory. The extfunctable imports these modules lazily. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun Jul 10 13:49:53 2005 @@ -5,14 +5,35 @@ import time import types + class ExtFuncInfo: - def __init__(self, func, annotation, ll_function, ll_annotable, backend_functiontemplate): + def __init__(self, func, annotation, ll_function_path, ll_annotable, backend_functiontemplate): self.func = func self.annotation = annotation - self.ll_function = ll_function + modulename, ignored = ll_function_path.split('/') + self.ll_module = ImportMe('pypy.rpython.module.%s' % modulename) + self.ll_function_name = ll_function_path.replace('/', '_') self.ll_annotable = ll_annotable self.backend_functiontemplate = backend_functiontemplate + def get_ll_function(self): + """Get the ll_*() function implementing the given high-level 'func'.""" + mod = self.ll_module.load() + return getattr(mod, self.ll_function_name) + ll_function = property(get_ll_function) + + +class ImportMe: + "Lazily imported module, for circular imports :-/" + def __init__(self, modulename): + self.modulename = modulename + self._mod = None + def load(self): + if self._mod is None: + self._mod = __import__(self.modulename, None, None, ['__doc__']) + return self._mod + + table = {} def declare(func, annotation, ll_function, ll_annotable=False, backend_functiontemplate=None): # annotation can be a function computing the annotation @@ -25,56 +46,17 @@ return bookkeeper.getbookkeeper().valueoftype(typ) table[func] = ExtFuncInfo(func, annotation, ll_function, ll_annotable, backend_functiontemplate) -# utility conversion functions -def to_rstr(s): - from pypy.rpython import rstr - p = rstr.malloc(rstr.STR, len(s)) - for i in range(len(s)): - p.chars[i] = s[i] - return p - -def from_rstr(rs): - return ''.join([rs.chars[i] for i in range(len(rs.chars))]) - -# dummy low-level implementations for the external functions -def ll_os_open(fname, flag, mode): - return os.open(from_rstr(fname), flag, mode) -ll_os_open.suggested_primitive=True - -def ll_os_read(fd, n): - return to_rstr(os.read(fd, n)) - -def ll_os_write(fd, astring): - return os.write(fd, from_rstr(astring)) - -def ll_os_close(fd): - os.close(fd) - -def ll_os_getcwd(): - return to_rstr(os.getcwd()) - -def ll_os_dup(fd): - return os.dup(fd) - -def ll_time_time(): - return time.time() - -def ll_time_clock(): - return time.clock() - -def ll_time_sleep(t): - time.sleep(t) - +# _____________________________________________________________ nonefactory = lambda *args: None # external function declarations -declare(os.open , int , ll_os_open, True) -declare(os.read , str , ll_os_read) -declare(os.write , int , ll_os_write) -declare(os.close , nonefactory, ll_os_close) -declare(os.getcwd , str , ll_os_getcwd) -declare(os.dup , int , ll_os_dup) -declare(time.time , float , ll_time_time) -declare(time.clock, float , ll_time_clock) -declare(time.sleep, nonefactory, ll_time_sleep) +declare(os.open , int , 'll_os/open', True) +declare(os.read , str , 'll_os/read') +declare(os.write , int , 'll_os/write') +declare(os.close , nonefactory, 'll_os/close') +declare(os.getcwd , str , 'll_os/getcwd') +declare(os.dup , int , 'll_os/dup') +declare(time.time , float , 'll_time/time') +declare(time.clock, float , 'll_time/clock') +declare(time.sleep, nonefactory, 'll_time/sleep') Added: pypy/dist/pypy/rpython/module/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/__init__.py Sun Jul 10 13:49:53 2005 @@ -0,0 +1 @@ +# Added: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/ll_os.py Sun Jul 10 13:49:53 2005 @@ -0,0 +1,79 @@ +""" +Dummy low-level implementations for the external functions of the 'os' module. +""" + +# Idea: each ll_os_xxx() function calls back the os.xxx() function that it +# is supposed to implement, either directly or indirectly if there is some +# argument decoding and buffering preparation that can be done here. + +# The specific function that calls back to os.xxx() is tagged with the +# 'suggested_primitive' flag. The back-end should special-case it and really +# implement it. The back-end can actually choose to special-case any function: +# it can for example special-case ll_os_xxx() directly even if the +# 'suggested_primitive' flag is set to another function, if the conversion +# and buffer preparation stuff is not useful. + +import os, errno +from pypy.rpython.rstr import STR +from pypy.rpython.lltype import malloc + + +# utility conversion functions +def to_rstr(s): + p = malloc(STR, len(s)) + for i in range(len(s)): + p.chars[i] = s[i] + return p + +def from_rstr(rs): + return ''.join([rs.chars[i] for i in range(len(rs.chars))]) + +def ll_strcpy(dstchars, srcchars, n): + i = 0 + while i < n: + dstchars[i] = srcchars[i] + i += 1 + +# ____________________________________________________________ + +def ll_os_open(fname, flag, mode): + return os.open(from_rstr(fname), flag, mode) +ll_os_open.suggested_primitive = True + + +def ll_read_into(fd, buffer): + data = os.read(fd, len(buffer.chars)) + ll_strcpy(buffer.chars, data, len(data)) + return len(data) +ll_read_into.suggested_primitive = True + +def ll_os_read(fd, count): + if count < 0: + raise OSError(errno.EINVAL, None) + buffer = malloc(STR, count) + n = ll_read_into(fd, buffer) + if n != count: + s = malloc(STR, n) + ll_strcpy(s.chars, buffer.chars, n) + buffer = s + return buffer + + +def ll_os_write(fd, astring): + return os.write(fd, from_rstr(astring)) +ll_os_write.suggested_primitive = True + + +def ll_os_close(fd): + os.close(fd) +ll_os_close.suggested_primitive = True + + +def ll_os_getcwd(): + return to_rstr(os.getcwd()) +ll_os_getcwd.suggested_primitive = True + + +def ll_os_dup(fd): + return os.dup(fd) +ll_os_dup.suggested_primitive = True Added: pypy/dist/pypy/rpython/module/ll_time.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/ll_time.py Sun Jul 10 13:49:53 2005 @@ -0,0 +1,20 @@ +""" +Dummy low-level implementations for the external functions of the 'time' module. +""" + +# See ll_os.py. + +import time + + +def ll_time_time(): + return time.time() +ll_time_time.suggested_primitive = True + +def ll_time_clock(): + return time.clock() +ll_time_clock.suggested_primitive = True + +def ll_time_sleep(t): + time.sleep(t) +ll_time_sleep.suggested_primitive = True Added: pypy/dist/pypy/rpython/module/test/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/test/__init__.py Sun Jul 10 13:49:53 2005 @@ -0,0 +1 @@ +# Added: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Sun Jul 10 13:49:53 2005 @@ -0,0 +1,25 @@ +import os +from pypy.tool.udir import udir +from pypy.rpython.module.ll_os import * + + +def test_open_read_write_close(): + filename = str(udir.join('test_open_read_write_close.txt')) + rsfilename = to_rstr(filename) + + fd = ll_os_open(rsfilename, os.O_WRONLY | os.O_CREAT, 0777) + count = ll_os_write(fd, to_rstr("hello world\n")) + assert count == len("hello world\n") + ll_os_close(fd) + + fd = ll_os_open(rsfilename, os.O_RDONLY, 0777) + data = ll_os_read(fd, 500) + assert from_rstr(data) == "hello world\n" + ll_os_close(fd) + + os.unlink(filename) + + +def test_getcwd(): + data = ll_os_getcwd() + assert from_rstr(data) == os.getcwd() Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Sun Jul 10 13:49:53 2005 @@ -3,13 +3,13 @@ from pypy.translator.c.support import cdecl from pypy.rpython.rmodel import getfunctionptr from pypy.rpython.rstr import STR -from pypy.rpython import extfunctable +from pypy.rpython.module import ll_os, ll_time # table of functions hand-written in extfunc_include.h EXTERNALS = { - extfunctable.ll_os_open: 'LL_os_open', - extfunctable.ll_time_clock: 'LL_time_clock', + ll_os .ll_os_open: 'LL_os_open', + ll_time.ll_time_clock: 'LL_time_clock', } Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sun Jul 10 13:49:53 2005 @@ -474,9 +474,10 @@ def select_function_code_generator(fnobj, db): if fnobj._callable in fixedname.EXTERNALS: - # 'fnobj' is one of the ll_xyz() functions special-cased in - # pypy.rpython.extfunctable. The corresponding C wrappers are written - # by hand in extfunc_include.h, and declared in fixedname.EXTERNALS. + # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive + # flag in pypy.rpython.module.*. The corresponding C wrappers are + # written by hand in extfunc_include.h, and declared in + # fixedname.EXTERNALS. db.externalfuncs[fnobj._callable] = fnobj return None elif hasattr(fnobj, 'graph'): From arigo at codespeak.net Sun Jul 10 14:34:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Jul 2005 14:34:58 +0200 (CEST) Subject: [pypy-svn] r14471 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050710123458.1C71227B41@code1.codespeak.net> Author: arigo Date: Sun Jul 10 14:34:56 2005 New Revision: 14471 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/c/test/test_exception.py Log: Support for raising AssertionErrors (e.g. with 'assert' statements) in ll functions. That was easy, but testing it is more fun because it confuses py.test quite a bit. We might have later to write some conftest.py code that handles AssertionErrors coming from compiled functions, or try to see how exactly py.test is confused. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sun Jul 10 14:34:56 2005 @@ -194,6 +194,7 @@ BUILTIN_TYPER[math.floor] = rtype_math_floor BUILTIN_TYPER[math.fmod] = rtype_math_fmod BUILTIN_TYPER[Exception.__init__.im_func] = rtype_Exception__init__ +BUILTIN_TYPER[AssertionError.__init__.im_func] = rtype_Exception__init__ BUILTIN_TYPER[OSError.__init__.im_func] = rtype_OSError__init__ # annotation of low-level types Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Sun Jul 10 14:34:56 2005 @@ -41,3 +41,36 @@ assert str(e) == 'MyException' # which is genc's best effort else: py.test.fail("f1(1) did not raise anything") + +def test_assert(): + def testfn(n): + assert n >= 0 + + # big confusion with py.test's AssertionError handling here... + # some hacks to try to disable it for the current test. + saved = no_magic() + try: + t = Translator(testfn) + t.annotate([int]).simplify() + t.specialize() + f1 = t.ccompile() + res = f1(0) + assert res is None, repr(res) + res = f1(42) + assert res is None, repr(res) + py.test.raises(AssertionError, f1, -2) + 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) From arigo at codespeak.net Sun Jul 10 15:27:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Jul 2005 15:27:45 +0200 (CEST) Subject: [pypy-svn] r14474 - in pypy/dist/pypy: annotation rpython rpython/test translator/c translator/c/test Message-ID: <20050710132745.0F61A27B41@code1.codespeak.net> Author: arigo Date: Sun Jul 10 15:27:40 2005 New Revision: 14474 Modified: pypy/dist/pypy/annotation/specialize.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_extfunc.py Log: GenC now passes a test for os.open/write/read/close(). This required the following changes: - some C code in extfunc_include.h, but not too much. It looks quite nice. - specialization now always attached an attribute _specializedversionof_ to the specialized functions, pointing back to the original one. This allows the function pointer objects to have the original function as _callable in all cases, which is needed to be able to recognize them. - all ll_os_* and ll_time_* functions are now annotated by default. This required some more allowance in annlowlevel to not complain on high-level objects (e.g. SomeStrings) being passed around in low-level functions. - fix some broken tests. - GenC checks that it isn't trying to compile a suggested_primitive. Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Sun Jul 10 15:27:40 2005 @@ -27,7 +27,7 @@ if isinstance(key, tuple): # cache specialization try: - func = bookkeeper.cachespecializations[key] + newfunc = bookkeeper.cachespecializations[key] except KeyError: if key[0] is func: postfix = key[1:] @@ -36,14 +36,16 @@ newfunc = clone(func, postfix) if key[0] is func: bookkeeper.cachespecializations[(newfunc,) + postfix] = newfunc - func = bookkeeper.cachespecializations[key] = newfunc + bookkeeper.cachespecializations[key] = newfunc elif isinstance(key, str): # specialization explicit in operation annotation postfix = key - func = clone(func, postfix) + newfunc = clone(func, postfix) else: # specialization already retrieved - func = key + newfunc = key + newfunc._specializedversionof_ = func + func = newfunc if unpacked: func = func, args Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sun Jul 10 15:27:40 2005 @@ -45,7 +45,12 @@ new_args_s.append(s_obj) else: new_args_s.append(not_const(s_obj)) - key.append(annmodel.annotation_to_lltype(s_obj)) + try: + key.append(annmodel.annotation_to_lltype(s_obj)) + except ValueError: + # passing non-low-level types to a ll_* function is allowed + # for module/ll_* + key.append(s_obj.__class__) return tuple(key), bookkeeper.build_args('simple_call', new_args_s) Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun Jul 10 15:27:40 2005 @@ -35,7 +35,7 @@ table = {} -def declare(func, annotation, ll_function, ll_annotable=False, backend_functiontemplate=None): +def declare(func, annotation, ll_function, ll_annotable=True, backend_functiontemplate=None): # annotation can be a function computing the annotation # or a simple python type from which an annotation will be constructed global table @@ -51,7 +51,7 @@ nonefactory = lambda *args: None # external function declarations -declare(os.open , int , 'll_os/open', True) +declare(os.open , int , 'll_os/open') declare(os.read , str , 'll_os/read') declare(os.write , int , 'll_os/write') declare(os.close , nonefactory, 'll_os/close') Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sun Jul 10 15:27:40 2005 @@ -226,13 +226,12 @@ def getconcretetype(v): return getattr(v, 'concretetype', PyObjPtr) -def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype, _callable=None): +def getfunctionptr(translator, graphfunc, getconcretetype=getconcretetype): """Make a functionptr from the given Python function.""" graph = translator.getflowgraph(graphfunc) llinputs = [getconcretetype(v) for v in graph.getargs()] lloutput = getconcretetype(graph.getreturnvar()) FT = FuncType(llinputs, lloutput) - if _callable is None: - _callable = graphfunc + _callable = getattr(graphfunc, '_specializedversionof_', graphfunc) return functionptr(FT, graphfunc.func_name, graph = graph, _callable = _callable) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun Jul 10 15:27:40 2005 @@ -382,10 +382,10 @@ # __________ utilities __________ - def getfunctionptr(self, graphfunc, _callable=None): + def getfunctionptr(self, graphfunc): def getconcretetype(v): return self.bindingrepr(v).lowleveltype - return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype, _callable=_callable) + return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype) def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): self.call_all_setups() # compute ForwardReferences now @@ -543,7 +543,7 @@ dontcare, spec_function = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s) # build the 'direct_call' operation - f = self.rtyper.getfunctionptr(spec_function, _callable=ll_function) + f = self.rtyper.getfunctionptr(spec_function) c = inputconst(typeOf(f), f) return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Sun Jul 10 15:27:40 2005 @@ -93,10 +93,10 @@ except OSError: pass count = 0 - from pypy.rpython import extfunctable + from pypy.rpython.module import ll_os for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, fn): cfptr = dir_call.args[0] - assert cfptr.value._obj._callable == extfunctable.ll_os_dup + assert cfptr.value._obj._callable == ll_os.ll_os_dup count += 1 assert count == 1 @@ -110,10 +110,10 @@ res = interpret(f, []) os.close(res) count = 0 - from pypy.rpython import extfunctable + from pypy.rpython.module import ll_os for dir_call in enum_direct_calls(test_llinterp.typer.annotator.translator, wr_open): cfptr = dir_call.args[0] - assert cfptr.value._obj._callable == extfunctable.ll_os_open + assert cfptr.value._obj._callable == ll_os.ll_os_open count += 1 assert count == 1 Modified: pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/extfunc_include.h Sun Jul 10 15:27:40 2005 @@ -6,6 +6,7 @@ /******************************************************************/ +#include #include #include #include @@ -15,32 +16,66 @@ #define PATH_MAX 254 #endif -/* The functions below are mapped to functions from pypy.rpython.extfunctable - by the pypy.translator.c.fixedname.EXTERNALS dictionary. */ +/* The functions below are mapped to functions from pypy.rpython.module.* + by the pypy.translator.c.fixedname.EXTERNALS dictionary. + They should correspond to the functions with the suggested_primitive + flag set, and NOT necessarily directly to the ll_os_*() functions. + See for example ll_read_into(), which is called by ll_os_read(). + The latter would be messy to write here, but LL_read_into() is quite easy. +*/ #define RPyString_Size(rps) ((rps)->rs_chars.length) #define RPyString_AsString(rps) ((rps)->rs_chars.items) +/************************************************************/ + /*** os module ***/ + + int LL_os_open(RPyString *filename, int flag, int mode) { char buf[PATH_MAX]; int fd, error, namelen = RPyString_Size(filename); if (namelen >= PATH_MAX) { - error = ENAMETOOLONG; + RAISE_OSERROR(ENAMETOOLONG); + return -1; } else { memcpy(buf, RPyString_AsString(filename), namelen); buf[namelen] = 0; fd = open(buf, flag, mode); - if (fd != -1) - return fd; - error = errno; + if (fd == -1) + RAISE_OSERROR(errno); + return fd; } - RAISE_OSERROR(error); - return -1; } +long LL_read_into(int fd, RPyString *buffer) +{ + long n = read(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); + if (n == -1) + RAISE_OSERROR(errno); + return n; +} + +long LL_os_write(int fd, RPyString *buffer) +{ + long n = write(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); + if (n == -1) + RAISE_OSERROR(errno); + return n; +} + +void LL_os_close(int fd) +{ + if (close(fd) == -1) + RAISE_OSERROR(errno); +} + + +/************************************************************/ + /*** time module ***/ + double LL_time_clock(void) { Modified: pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/fixedname.py Sun Jul 10 15:27:40 2005 @@ -9,6 +9,9 @@ # table of functions hand-written in extfunc_include.h EXTERNALS = { ll_os .ll_os_open: 'LL_os_open', + ll_os .ll_read_into: 'LL_read_into', + ll_os .ll_os_write: 'LL_os_write', + ll_os .ll_os_close: 'LL_os_close', ll_time.ll_time_clock: 'LL_time_clock', } Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sun Jul 10 15:27:40 2005 @@ -480,6 +480,9 @@ # fixedname.EXTERNALS. db.externalfuncs[fnobj._callable] = fnobj return None + elif getattr(fnobj._callable, 'suggested_primitive', False): + raise ValueError, "trying to compile suggested primitive %r" % ( + fnobj._callable,) elif hasattr(fnobj, 'graph'): cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython" return FunctionCodeGenerator(fnobj.graph, db, cpython_exc) Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sun Jul 10 15:27:40 2005 @@ -1,11 +1,11 @@ import autopath import py +import os, time from pypy.tool.udir import udir from pypy.translator.c.test.test_genc import compile def test_time_clock(): - import time def does_stuff(): return time.clock() f1 = compile(does_stuff, []) @@ -17,7 +17,6 @@ def test_os_open(): - import os tmpfile = str(udir.join('test_os_open.txt')) def does_stuff(): fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) @@ -29,7 +28,6 @@ assert os.path.exists(tmpfile) def test_failing_os_open(): - import os tmpfile = str(udir.join('test_failing_os_open.DOESNTEXIST')) def does_stuff(): fd = os.open(tmpfile, os.O_RDONLY, 0777) @@ -38,3 +36,20 @@ f1 = compile(does_stuff, []) py.test.raises(OSError, f1) assert not os.path.exists(tmpfile) + +def test_open_read_write_close(): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + count = os.write(fd, "hello world\n") + assert count == len("hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDONLY, 0777) + data = os.read(fd, 500) + assert data == "hello world\n" + os.close(fd) + + f1 = compile(does_stuff, []) + f1() + assert open(filename, 'r').read() == "hello world\n" + os.unlink(filename) From pedronis at codespeak.net Sun Jul 10 23:57:46 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 23:57:46 +0200 (CEST) Subject: [pypy-svn] r14477 - pypy/dist/pypy/interpreter Message-ID: <20050710215746.E93C327B41@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 23:57:43 2005 New Revision: 14477 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/typedef.py Log: reorganize slot support such that slots_w does not get improperly attached to W_Root by annotation. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sun Jul 10 23:57:43 2005 @@ -54,6 +54,12 @@ id = r_uint(id) # XXX what about sizeof(void*) > sizeof(long) !! return space.wrap("<%s at 0x%x>" % (info, id)) + def getslotvalue(self, index): + raise NotImplementedError + + def setslotvalue(self, index, w_val): + raise NotImplementedError + class BaseWrappable(W_Root): """A subclass of BaseWrappable is an internal, interpreter-level class that can nevertheless be exposed at application-level by space.wrap().""" Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Sun Jul 10 23:57:43 2005 @@ -89,6 +89,12 @@ if wants_slots: def user_setup_slots(self, nslots): self.slots_w = [None] * nslots + + def setslotvalue(self, index, w_value): + self.slots_w[index] = w_value + + def getslotvalue(self, index): + return self.slots_w[index] else: def user_setup_slots(self, nslots): assert nslots == 0 @@ -273,7 +279,7 @@ else: self = member self.typecheck(space, w_obj) - w_result = w_obj.slots_w[self.index] + w_result = w_obj.getslotvalue(self.index) if w_result is None: raise OperationError(space.w_AttributeError, space.wrap(self.name)) # XXX better message @@ -284,14 +290,14 @@ Write into the slot 'member' of the given 'obj'.""" self = member self.typecheck(space, w_obj) - w_obj.slots_w[self.index] = w_value + w_obj.setslotvalue(self.index, w_value) def descr_member_del(space, member, w_obj): """member.__delete__(obj) Delete the value of the slot 'member' from the given 'obj'.""" self = member self.typecheck(space, w_obj) - w_obj.slots_w[self.index] = None + w_obj.setslotvalue(self.index, None) Member.typedef = TypeDef( "Member", From pedronis at codespeak.net Sun Jul 10 23:59:09 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 10 Jul 2005 23:59:09 +0200 (CEST) Subject: [pypy-svn] r14478 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050710215909.0FB7B27B43@code1.codespeak.net> Author: pedronis Date: Sun Jul 10 23:59:05 2005 New Revision: 14478 Modified: pypy/branch/pypy-translation-snapshot/interpreter/baseobjspace.py pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Log: merge slots reorg. Modified: pypy/branch/pypy-translation-snapshot/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/baseobjspace.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/baseobjspace.py Sun Jul 10 23:59:05 2005 @@ -51,6 +51,12 @@ id = r_uint(id) # XXX what about sizeof(void*) > sizeof(long) !! return space.wrap("<%s at 0x%x>" % (info, id)) + def getslotvalue(self, index): + raise NotImplementedError + + def setslotvalue(self, index, w_val): + raise NotImplementedError + class BaseWrappable(W_Root): """A subclass of BaseWrappable is an internal, interpreter-level class that can nevertheless be exposed at application-level by space.wrap().""" Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Sun Jul 10 23:59:05 2005 @@ -89,6 +89,12 @@ if wants_slots: def user_setup_slots(self, nslots): self.slots_w = [None] * nslots + + def setslotvalue(self, index, w_value): + self.slots_w[index] = w_value + + def getslotvalue(self, index): + return self.slots_w[index] else: def user_setup_slots(self, nslots): assert nslots == 0 @@ -273,7 +279,7 @@ else: self = member self.typecheck(space, w_obj) - w_result = w_obj.slots_w[self.index] + w_result = w_obj.getslotvalue(self.index) if w_result is None: raise OperationError(space.w_AttributeError, space.wrap(self.name)) # XXX better message @@ -284,14 +290,14 @@ Write into the slot 'member' of the given 'obj'.""" self = member self.typecheck(space, w_obj) - w_obj.slots_w[self.index] = w_value + w_obj.setslotvalue(self.index, w_value) def descr_member_del(space, member, w_obj): """member.__delete__(obj) Delete the value of the slot 'member' from the given 'obj'.""" self = member self.typecheck(space, w_obj) - w_obj.slots_w[self.index] = None + w_obj.setslotvalue(self.index, None) Member.typedef = TypeDef( "Member", From rxe at codespeak.net Mon Jul 11 01:16:15 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 11 Jul 2005 01:16:15 +0200 (CEST) Subject: [pypy-svn] r14479 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050710231615.C388927B41@code1.codespeak.net> Author: rxe Date: Mon Jul 11 01:16:13 2005 New Revision: 14479 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: Some tests were failing wrt to changes to external functions. Some quick fixes and disabled the last one which wasnt obvious how to fix. Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Mon Jul 11 01:16:13 2005 @@ -113,11 +113,9 @@ """) extfunctions["%ll_os_open"] = (("%cast",), """ -int %ll_os_open(%st.rpy_string.0* %structstring, int %pythonmode) { - %flags = cast int %pythonmode to int - %mode = cast int 384 to int ;S_IRUSR=256, S_IWUSR=128 +int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) { %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) - %fd = call int %open(sbyte* %dest, int %flags, int %mode) + %fd = call int %open(sbyte* %dest, int %flag, int %mode) ret int %fd } Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Mon Jul 11 01:16:13 2005 @@ -85,7 +85,7 @@ assert os.path.exists(path) assert open(path).read() == path -def test_os_file_ops_open_write_read_close(): +def Xtest_os_file_ops_open_write_read_close(): # the test is overly complicated because # we don't have prebuilt string constants yet import os From rxe at codespeak.net Mon Jul 11 02:09:04 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 11 Jul 2005 02:09:04 +0200 (CEST) Subject: [pypy-svn] r14480 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050711000904.21AB027B44@code1.codespeak.net> Author: rxe Date: Mon Jul 11 02:09:00 2005 New Revision: 14480 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_lltype.py Log: * Fleshed out test_lltype.py. * Sanitised StructNode, StructVarNode and ArrayNode * Added support for getarraysubstruct() * Added repr_argwithtype which returns both arg and type * Refactoring of database * We now setup all the types before setup all the constants - as we need to know what the type names are to cast (if we need to cast to at all) * Added repr_constant() to database which returns a representation for a in a generic way (credit hpk) pbcs for llvm are nearly there. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Mon Jul 11 02:09:00 2005 @@ -15,14 +15,14 @@ self.db = db self.array = array - + self.arraytype = array.OF # ref is used to reference the arraytype in llvm source # constructor_ref is used to reference the constructor # for the array type in llvm source code # constructor_decl is used to declare the constructor # for the array type (see writeimpl) c = nextnum() - self.ref = "%%array.%s.%s" % (c, array.OF) + self.ref = "%%array.%s.%s" % (c, self.arraytype) self.constructor_ref = "%%new.array.%s" % c self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -31,14 +31,14 @@ return "" % self.ref def setup(self): - self.db.prepare_repr_arg_type(self.array.OF) + self.db.prepare_repr_arg_type(self.arraytype) self._issetup = True # ______________________________________________________________________ # entry points from genllvm # def writedatatypedecl(self, codewriter): - codewriter.arraydef(self.ref, self.db.repr_arg_type(self.array.OF)) + codewriter.arraydef(self.ref, self.db.repr_arg_type(self.arraytype)) def writedecl(self, codewriter): # declaration for constructor @@ -46,44 +46,66 @@ def writeimpl(self, codewriter): log.writeimpl(self.ref) - fromtype = self.db.repr_arg_type(self.array.OF) + fromtype = self.db.repr_arg_type(self.arraytype) varsize.write_constructor(codewriter, self.ref, self.constructor_decl, fromtype) class ArrayNode(LLVMNode): + """ An arraynode. Elements can be + a primitive, + a struct, + pointer to struct/array + """ _issetup = True def __init__(self, db, value): assert isinstance(lltype.typeOf(value), lltype.Array) self.db = db self.value = value self.arraytype = lltype.typeOf(value).OF - self.ref = "%%arrayinstance.%s.%s" % (self.arraytype, nextnum()) + self.ref = "%%arrayinstance.%s" % (nextnum(),) + + def __str__(self): + return "" % (self.ref,) + + def setup(self): if isinstance(self.arraytype, lltype.Ptr): for item in self.value.items: self.db.addptrvalue(item) - def __str__(self): - return "" %(self.ref,) - - def typeandvalue(self): - """ Returns the type and value for this node. """ + # set castref (note we must ensure that types are "setup" before we can + # get typeval) + typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) + self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(), + self.ref, + typeval) + self._issetup = True + + def get_typestr(self): items = self.value.items arraylen = len(items) + typeval = self.db.repr_arg_type(self.arraytype) + return "{ int, [%s x %s] }" % (arraylen, typeval) + def castfrom(self): + return "%s*" % self.get_typestr() + + def constantvalue(self): + """ Returns the constant representation for this node. """ + items = self.value.items + arraylen = len(items) typeval = self.db.repr_arg_type(self.arraytype) - type_ = "{ int, [%s x %s] }" % (arraylen, typeval) - arrayvalues = ["%s %s" % self.db.reprs_constant(v) for v in items] + arrayvalues = [self.db.reprs_constant(v) for v in items] value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, typeval, ", ".join(arrayvalues)) - return type_, value + + return "%s {%s}" % (self.get_typestr(), value) # ______________________________________________________________________ # entry points from genllvm def writeglobalconstants(self, codewriter): - type_, values = self.typeandvalue() - codewriter.globalinstance(self.ref, type_, values) + codewriter.globalinstance(self.ref, self.constantvalue()) Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Mon Jul 11 02:09:00 2005 @@ -3,7 +3,7 @@ from pypy.translator.llvm2.log import log log = log.codewriter -show_line_numbers = False # True +show_line_numbers = True # False count = count().next class CodeWriter(object): @@ -16,8 +16,12 @@ self._lines.append(line) log(line) - def comment(self, line): - self.append(";; " + line) + def comment(self, line, indent=False): + line = ";; " + line + if indent: + self.indent(line) + else: + self.append(line) def newline(self): self.append("") @@ -28,8 +32,8 @@ def label(self, name): self.append(" %s:" % name) - def globalinstance(self, name, type, data): - self.append("%s = constant %s {%s}" % (name, type, data)) + def globalinstance(self, name, typeandata): + self.append("%s = constant %s" % (name, typeandata)) def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Mon Jul 11 02:09:00 2005 @@ -52,40 +52,31 @@ def items(self): return self._dict.items() +def primitive_to_str(type_, value): + if type_ is lltype.Bool: + repr = str(value).lower() #False --> false + elif type_ is lltype.Char: + repr = str(ord(value)) + elif type_ is lltype.UniChar: + repr = "0" #XXX + else: + repr = str(value) + return repr + class Database(object): def __init__(self, translator): self._translator = translator self.obj2node = NormalizingDict() self.ptr2nodevalue = {} self._pendingsetup = [] + self._pendingconstants = [] self._tmpcount = 1 def addptrvalue(self, ptrvalue): value = ptrvalue._obj - node = self.create_constant_node(value) - self.ptr2nodevalue[value] = self.create_constant_node(value) - - def getptrnode(self, ptrvalue): - return self.ptr2nodevalue[ptrvalue._obj] - - def getptrref(self, ptrvalue): - return self.ptr2nodevalue[ptrvalue._obj].ref - - def reprs_constant(self, value): - type_ = lltype.typeOf(value) - if isinstance(type_, lltype.Primitive): - if isinstance(value, str) and len(value) == 1: - res = ord(value) - res = str(value) - elif isinstance(type_, lltype.Ptr): - res = self.getptrref(value) - #elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): - #XXX res = self.value.typeandvalue() - else: - assert False, "not supported XXX" - return self.repr_arg_type(type_), res + self.ptr2nodevalue[value] = self.create_constant_node(value, setup=True) - def create_constant_node(self, value): + def create_constant_node(self, value, setup=False): type_ = lltype.typeOf(value) node = None if isinstance(type_, lltype.FuncType): @@ -104,14 +95,19 @@ elif isinstance(type_, lltype.Array): node = ArrayNode(self, value) assert node is not None, "%s not supported" % lltype.typeOf(value) + if setup: + node.setup() return node - def addpending(self, key, node): + def addpending(self, key, node): assert key not in self.obj2node, ( "node with key %r already known!" %(key,)) self.obj2node[key] = node log("added to pending nodes:", node) - self._pendingsetup.append(node) + if isinstance(node, (StructNode, ArrayNode)): + self._pendingconstants.append(node) + else: + self._pendingsetup.append(node) def prepare_repr_arg(self, const_or_var): """if const_or_var is not already in a dictionary self.obj2node, @@ -126,7 +122,7 @@ log.prepare(const_or_var, "(is primitive)") return - assert isinstance(ct, lltype.Ptr), "Preperation of non primitive and non pointer" + assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" value = const_or_var.value._obj self.addpending(const_or_var, self.create_constant_node(value)) @@ -156,8 +152,8 @@ elif isinstance(type_, lltype.Array): self.addpending(type_, ArrayTypeNode(self, type_)) - else: - log.XXX("need to prepare typerepr", type_) + else: + assert False, "need to prepare typerepr %s %s" % (type_, type(type_)) def prepare_repr_arg_type_multi(self, types): for type_ in types: @@ -171,9 +167,15 @@ def setup_all(self): while self._pendingsetup: x = self._pendingsetup.pop() - log.setup_all(x) + log.settingup(x) + x.setup() + + while self._pendingconstants: + x = self._pendingconstants.pop() + log.settingup_constant(x) x.setup() + def getobjects(self, subset_types=None): res = [] for v in self.obj2node.values() + self.ptr2nodevalue.values(): @@ -185,16 +187,18 @@ # Representing variables and constants in LLVM source code def repr_arg(self, arg): - if (isinstance(arg, Constant) and - isinstance(arg.concretetype, lltype.Primitive)): - - # XXX generalize and test this - if isinstance(arg.value, str) and len(arg.value) == 1: - return str(ord(arg.value)) - return str(arg.value).lower() #False --> false - elif isinstance(arg, Variable): + if isinstance(arg, Constant): + if isinstance(arg.concretetype, lltype.Primitive): + return primitive_to_str(arg.concretetype, arg.value) + else: + node = self.obj2node[arg] + if hasattr(node, "castref"): + return node.castref + else: + return node.ref + else: + assert isinstance(arg, Variable) return "%" + str(arg) - return self.obj2node[arg].ref def repr_arg_type(self, arg): if isinstance(arg, (Constant, Variable)): @@ -209,12 +213,38 @@ else: raise TypeError("cannot represent %r" %(arg,)) + def repr_argwithtype(self, arg): + return self.repr_arg(arg), self.repr_arg_type(arg) + def repr_arg_multi(self, args): return [self.repr_arg(arg) for arg in args] def repr_arg_type_multi(self, args): return [self.repr_arg_type(arg) for arg in args] + def reprs_constant(self, value): + type_ = lltype.typeOf(value) + if isinstance(type_, lltype.Primitive): + repr = primitive_to_str(type_, value) + return "%s %s" % (self.repr_arg_type(type_), repr) + + elif isinstance(type_, lltype.Ptr): + node = self.ptr2nodevalue[value._obj] + ref = node.ref + + fromptr = node.castfrom() + toptr = self.repr_arg_type(type_) + if fromptr: + refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref) + ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) + return "%s %s" % (toptr, ref) + + elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): + node = self.create_constant_node(value, setup=True) + return node.constantvalue() + + assert False, "%s not supported" % (type(value)) + def repr_tmpvar(self): count = self._tmpcount self._tmpcount += 1 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Mon Jul 11 02:09:00 2005 @@ -140,7 +140,7 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) for op in block.operations: - #codewriter.comment(str(op)) + codewriter.comment(str(op), indent=True) opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) @@ -327,6 +327,7 @@ cast_bool_to_int = cast_primitive cast_bool_to_uint = uint_is_true = cast_primitive cast_int_to_char = cast_char_to_int = cast_primitive + cast_int_to_uint = cast_primitive def int_is_true(self, op): self.codewriter.binaryop("setne", @@ -382,54 +383,56 @@ def getfield(self, op): tmpvar = self.db.repr_tmpvar() - typ = self.db.repr_arg_type(op.args[0]) - typevar = self.db.repr_arg(op.args[0]) + struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, typ, typevar, ("uint", index)) + self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" self.codewriter.load(targetvar, targettype, tmpvar) def getsubstruct(self, op): - typ = self.db.repr_arg_type(op.args[0]) - typevar = self.db.repr_arg(op.args[0]) + struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) targetvar = self.db.repr_arg(op.result) - self.codewriter.getelementptr(targetvar, typ, - typevar, ("uint", index)) + self.codewriter.getelementptr(targetvar, structtype, + struct, ("uint", index)) targettype = self.db.repr_arg_type(op.result) assert targettype != "void" def setfield(self, op): tmpvar = self.db.repr_tmpvar() - type = self.db.repr_arg_type(op.args[0]) - typevar = self.db.repr_arg(op.args[0]) + struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, type, typevar, ("uint", index)) - valuevar = self.db.repr_arg(op.args[2]) - valuetype = self.db.repr_arg_type(op.args[2]) + self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index)) + valuevar, valuetype = self.db.repr_argwithtype(op.args[2]) assert valuetype != "void" self.codewriter.store(valuetype, valuevar, tmpvar) - def getarrayitem(self, op): - var = self.db.repr_arg(op.args[0]) - vartype = self.db.repr_arg_type(op.args[0]) + def getarrayitem(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) index = self.db.repr_arg(op.args[1]) indextype = self.db.repr_arg_type(op.args[1]) tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, vartype, var, + self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 1), (indextype, index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) self.codewriter.load(targetvar, targettype, tmpvar) + def getarraysubstruct(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + targetvar = self.db.repr_arg(op.result) + self.codewriter.getelementptr(targetvar, arraytype, array, + ("uint", 1), (indextype, index)) + def setarrayitem(self, op): - array = self.db.repr_arg(op.args[0]) - arraytype = self.db.repr_arg_type(op.args[0]) + array, arraytype = self.db.repr_argwithtype(op.args[0]) index = self.db.repr_arg(op.args[1]) indextype = self.db.repr_arg_type(op.args[1]) @@ -439,14 +442,12 @@ valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) - assert valuevar.strip() != '-' self.codewriter.store(valuetype, valuevar, tmpvar) def getarraysize(self, op): - var = self.db.repr_arg(op.args[0]) - vartype = self.db.repr_arg_type(op.args[0]) + array, arraytype = self.db.repr_argwithtype(op.args[0]) tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, vartype, var, ("uint", 0)) + self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) self.codewriter.load(targetvar, targettype, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Mon Jul 11 02:09:00 2005 @@ -9,7 +9,7 @@ if hasattr(self, "_ref"): raise TypeError, ("can only set ref once! currently: %s" % (self._ref,)) - if " " in ref: + if " " in ref or "<" in ref: ref = '"%s"' % (ref,) self._ref = ref return property(_get_ref, _set_ref) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Mon Jul 11 02:09:00 2005 @@ -16,15 +16,15 @@ assert isinstance(struct, lltype.Struct) self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name, nextnum()) - self.ref = "%%st.%s" % self.name + self.name = "%s.%s" % (self.struct._name , nextnum()) + self.ref = "%%st.%s" % (self.name) def __str__(self): return "" %(self.ref,) def setup(self): # Recurse - for field in self.struct._flds: + for field in self.struct._flds.values(): self.db.prepare_repr_arg_type(field) self._issetup = True @@ -33,9 +33,10 @@ def writedatatypedecl(self, codewriter): assert self._issetup - fields = [getattr(self.struct, name) for name in self.struct._names_without_voids()] - l = [self.db.repr_arg_type(field) for field in fields] - codewriter.structdef(self.ref, l) + fields = [getattr(self.struct, name) + for name in self.struct._names_without_voids()] + codewriter.structdef(self.ref, + self.db.repr_arg_type_multi(fields)) class StructVarsizeTypeNode(StructTypeNode): @@ -48,6 +49,9 @@ def __str__(self): return "" %(self.ref,) + # ______________________________________________________________________ + # main entry points from genllvm + def writedecl(self, codewriter): # declaration for constructor codewriter.declare(self.constructor_decl) @@ -73,92 +77,95 @@ self.ref, self.constructor_decl, arraytype, indices_to_array) - -#XXX Everything downwind of here is experimental code - -def cast_global(toptr, from_, name): - s = "cast(%s* getelementptr (%s* %s, int 0) to %s)" % (from_, - from_, - name, - toptr) - return s - class StructNode(LLVMNode): + """ A struct constant. Can simply contain + a primitive, + a struct, + pointer to struct/array + """ _issetup = False def __init__(self, db, value): self.db = db self.value = value - self.ref = "%%stinstance.%s.%s" % (value._TYPE._name, nextnum()) - for name in self.value._TYPE._names_without_voids(): - T = self.value._TYPE._flds[name] - assert T is not lltype.Void - if isinstance(T, lltype.Ptr): - self.db.addptrvalue(getattr(self.value, name)) + self.structtype = self.value._TYPE + self.ref = "%%stinstance.%s" % (nextnum(),) def __str__(self): - return "" %(self.ref,) + return "" % (self.ref,) + + def _gettypes(self): + return [(name, self.structtype._flds[name]) + for name in self.structtype._names_without_voids()] def setup(self): + for name, T in self._gettypes(): + assert T is not lltype.Void + if isinstance(T, lltype.Ptr): + self.db.addptrvalue(getattr(self.value, name)) self._issetup = True - def typeandvalue(self): - res = [] - type_ = self.value._TYPE - for name in type_._names_without_voids(): - T = type_._flds[name] + def castfrom(self): + return None + + def get_typestr(self): + return self.db.repr_arg_type(self.structtype) + + def constantvalue(self): + """ Returns the constant representation for this node. """ + values = [] + for name, T in self._gettypes(): value = getattr(self.value, name) - if isinstance(T, lltype.Ptr): - x = self.db.getptrnode(value) - value = self.db.getptrref(value) - t, v = x.typeandvalue() - value = cast_global(self.db.repr_arg_type(T), t, value) + values.append(self.db.reprs_constant(value)) - else: - value = str(value) - res.append((self.db.repr_arg_type(T), value)) - - typestr = self.db.repr_arg_type(type_) - values = ", ".join(["%s %s" % (t, v) for t, v in res]) - return typestr, values + return "%s {%s}" % (self.get_typestr(), ", ".join(values)) - def writeglobalconstants(self, codewriter): - type_, values = self.typeandvalue() - codewriter.globalinstance(self.ref, type_, values) + # ______________________________________________________________________ + # main entry points from genllvm -#XXX Everything downwind of here is very experimental code and no tests pass + def writeglobalconstants(self, codewriter): + codewriter.globalinstance(self.ref, self.constantvalue()) class StructVarsizeNode(StructNode): + """ A varsize struct constant. Can simply contain + a primitive, + a struct, + pointer to struct/array + + and the last element *must* be + an array + OR + a series of embedded structs, which has as its last element an array. + """ + def __str__(self): - return "" %(self.ref,) + return "" % (self.ref,) - def typeandvalue(self): - res = [] - type_ = self.value._TYPE - for name in type_._names_without_voids()[:-1]: - T = type_._flds[name] - value = getattr(self.value, name) - if not isinstance(T, lltype.Primitive): - # Create a dummy constant hack XXX - value = self.db.repr_arg(Constant(value, T)) - else: - value = str(value) - res.append((self.db.repr_arg_type(T), value)) - - # Special case for varsized arrays - name = type_._names_without_voids()[-1] - T = type_._flds[name] - assert not isinstance(T, lltype.Primitive) - value = getattr(self.value, name) - c = Constant(value, T) - x = self.db.obj2node[c] - t, v = x.typeandvalue() - - #value = self.db.repr_arg(c) - value = cast_global(self.db.repr_arg_type(T), t, "{%s}" % v) - res.append((self.db.repr_arg_type(T), value)) - - typestr = self.db.repr_arg_type(type_) - values = ", ".join(["%s %s" % (t, v) for t, v in res]) - return typestr, values - + def setup(self): + # set castref (note we must ensure that types are "setup" before we can + # get typeval) + typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) + self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(), + self.ref, + typeval) + super(StructVarsizeNode, self).setup() + + def get_typestr(self): + lastname, LASTT = self._gettypes()[-1] + assert isinstance(LASTT, lltype.Array) or ( + isinstance(LASTT, lltype.Struct) and LASTT._arrayfld) + + #XXX very messy + node = self.db.create_constant_node(getattr(self.value, lastname), True) + lasttype = node.get_typestr() + + types = [] + for name, T in self._gettypes()[:-1]: + types.append(self.db.repr_arg_type(T)) + types.append(lasttype) + + return "{%s}" % ", ".join(types) + + def castfrom(self): + return "%s*" % self.get_typestr() + Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_lltype.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Mon Jul 11 02:09:00 2005 @@ -1,60 +1,180 @@ + import py from pypy.rpython import lltype from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.llvm2 import database, codewriter +from pypy.rpython import rarithmetic py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) -P = lltype.GcStruct("s", - ('signed', lltype.Signed), - ('unsigned', lltype.Unsigned), - ('float', lltype.Float), - ('char', lltype.Char), - ('bool', lltype.Bool), - ('unichar', lltype.UniChar) - ) - -def test_struct1(): - # struct of primitives - def simple1(): - s = lltype.malloc(P) - return s.signed# + s.unsigned + s.float + s.char + s.bool + s.unichar - fn = compile_function(simple1, [], embedexterns=False) - assert fn() == 0 - -# def test_struct2(): -# S = lltype.Struct("s", ('v', lltype.Signed)) -# S2 = lltype.GcStruct("s2", ('a', S), ('b', S)) -# def simple2(): -# s = lltype.malloc(S2) -# s.a.v = 6 -# s.b.v = 12 -# return s.a.v + s.b.v -# fn = compile_function(simple2, [], embedexterns=False, view=True) -# assert fn() == 18 - -# def test_simple_struct(): -# S0 = lltype.GcStruct("s0", ('a', lltype.Signed), ('b', lltype.Signed)) -# c0 = lltype.malloc(S0) -# c0.a, c0.b = 1, 2 -# def simple_struct(): -# return c0.a + c0.b -# f = compile_function(simple_struct, [], embedexterns=False, view=True) -# assert f() == 3 - -# def test_simple_struct2(): -# S0 = lltype.GcStruct("s0", ('a', lltype.Char), ('b', lltype.Signed)) -# def build(): -# s0 = lltype.malloc(S0) -# s0.a = "l" -# s0.b = 2 -# return s0 -# c0 = build() -# def simple_struct2(): -# return c0.a + c0.b -# f = compile_function(simple_struct, [], embedexterns=False, view=True) -# assert f() == 3 +S = lltype.Struct("base", ('a', lltype.Signed), ('b', lltype.Signed)) + +def test_struct_constant1(): + P = lltype.GcStruct("s", + ('signed', lltype.Signed), + ('unsigned', lltype.Unsigned), + ('float', lltype.Float), + ('char', lltype.Char), + ('bool', lltype.Bool), + ('unichar', lltype.UniChar) + ) + + s = lltype.malloc(P) + s.signed = 2 + s.unsigned = rarithmetic.r_uint(1) + def struct_constant(): + x1 = s.signed + s.unsigned + return x1 + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == 3 + +def test_struct_constant2(): + S2 = lltype.GcStruct("struct2", ('a', lltype.Signed), ('s1', S), ('s2', S)) + + s = lltype.malloc(S2) + s.a = 5 + s.s1.a = 2 + s.s1.b = 4 + s.s2.b = 3 + def struct_constant(): + return s.a + s.s2.b + s.s1.a + s.s1.b + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == 14 + +def test_struct_constant3(): + structs = [] + cur = S + for n in range(20): + cur = lltype.Struct("struct%s" % n, ("s", cur)) + structs.append(cur) + TOP = lltype.GcStruct("top", ("s", cur)) + + top = lltype.malloc(TOP) + cur = top.s + for ii in range(20): + cur = cur.s + cur.a = 10 + cur.b = 5 + def struct_constant(): + return (top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a - + top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.b) + + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == 5 + +def test_struct_constant4(): + SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed)) + STEST = lltype.GcStruct('test', ('sptr', lltype.Ptr(SPTR))) + s = lltype.malloc(STEST) + s.sptr = lltype.malloc(SPTR) + s.sptr.a = 21 + def struct_constant(): + return s.sptr.a * 2 + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == 42 + +def test_struct_constant5(): + SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed), ('b', S)) + STEST = lltype.GcStruct('test', ('sptr', lltype.Ptr(SPTR))) + s = lltype.malloc(STEST) + s.sptr = lltype.malloc(SPTR) + s.sptr.a = 21 + s.sptr.b.a = 11 + s.sptr.b.b = 10 + def struct_constant(): + return s.sptr.a + s.sptr.b.a + s.sptr.b.b + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == 42 + +def test_struct_constant6(): + U = lltype.Struct('inlined', ('z', lltype.Signed)) + T = lltype.GcStruct('subtest', ('y', lltype.Signed)) + S = lltype.GcStruct('test', ('x', lltype.Ptr(T)), ('u', U), ('p', lltype.Ptr(U))) + + s = lltype.malloc(S) + s.x = lltype.malloc(T) + s.x.y = 42 + s.u.z = -100 + s.p = s.u + def struct_constant(): + return s.x.y + s.p.z + fn = compile_function(struct_constant, [], embedexterns=False) + assert fn() == -58 + +def test_array_constant(): + A = lltype.GcArray(lltype.Signed) + a = lltype.malloc(A, 3) + a[0] = 100 + a[1] = 101 + a[2] = 102 + def array_constant(): + return a[0] + a[1] + a[2] + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 303 + +def test_array_constant2(): + A = lltype.GcArray(lltype.Signed) + a = lltype.malloc(A, 3) + a[0] = 100 + a[1] = 101 + a[2] = 102 + def array_constant(): + a[0] = 0 + return a[0] + a[1] + a[2] + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 203 + +def test_array_constant3(): + A = lltype.GcArray(('x', lltype.Signed)) + a = lltype.malloc(A, 3) + a[0].x = 100 + a[1].x = 101 + a[2].x = 102 + def array_constant(): + return a[0].x + a[1].x + a[2].x + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 303 + +def test_struct_array1(): + A = lltype.GcArray(lltype.Signed) + STEST = lltype.GcStruct('test', ('aptr', lltype.Ptr(A))) + s = lltype.malloc(STEST) + s.aptr = a = lltype.malloc(A, 2) + a[0] = 100 + a[1] = 101 + def array_constant(): + return s.aptr[1] - a[0] + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 1 + +def test_struct_array2(): + A = lltype.Array(lltype.Signed) + STEST = lltype.GcStruct('test', ('a', lltype.Signed), ('b', A)) + s = lltype.malloc(STEST, 2) + s.a = 41 + s.b[0] = 100 + s.b[1] = 101 + def array_constant(): + return s.b[1] - s.b[0] + s.a + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 42 + +def test_struct_array3(): + A = lltype.Array(lltype.Signed) + STEST = lltype.GcStruct('test', ('a', lltype.Signed), ('b', A)) + SBASE = lltype.GcStruct('base', ('p', lltype.Ptr(STEST))) + s = lltype.malloc(STEST, 2) + s.a = 41 + s.b[0] = 100 + s.b[1] = 101 + b = lltype.malloc(SBASE) + b.p = s + def array_constant(): + s = b.p + return s.b[1] - s.b[0] + s.a + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 42 From rxe at codespeak.net Mon Jul 11 02:14:33 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 11 Jul 2005 02:14:33 +0200 (CEST) Subject: [pypy-svn] r14481 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050711001433.A05C527B3F@code1.codespeak.net> Author: rxe Date: Mon Jul 11 02:14:31 2005 New Revision: 14481 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Enable string rpc tests. Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 11 02:14:31 2005 @@ -93,7 +93,6 @@ assert factorial(4) == 24 assert factorial(5) == 120 - def test_primitive_is_true(): def var_is_true(v): return bool(v) @@ -107,7 +106,6 @@ assert f(256.0) assert not f(0.0) - def test_uint_ops(): def ops(i): x = r_uint(0) @@ -141,7 +139,6 @@ assert f(1) == 1 assert f(2) == 2 - def test_function_call(): def callee(): return 1 @@ -205,7 +202,7 @@ assert f(-1) == 3 assert f(0) == 5 -def DONTtest_simple_chars(): +def test_simple_chars(): def char_constant2(s): s = s + s + s return len(s + '.') @@ -266,7 +263,7 @@ def test_string_simple(): def string_simple(i): return ord(str(i)) - f = compile_function(string_simple, [int], view=False) + f = compile_function(string_simple, [int]) assert f(0) def test_string_simple_ops(): @@ -282,18 +279,17 @@ f = compile_function(string_simple_ops, [int]) assert f(5) == ord('5') + 2 - -def DONTtest_string_getitem1(): +def test_string_getitem1(): l = "Hello, World" def string_getitem1(i): - return l[i] - f = compile_function(string_getitem1, [int], view=True) + return ord(l[i]) + f = compile_function(string_getitem1, [int]) assert f(0) == ord("H") -def DONTtest_string_getitem2(): +def test_string_getitem2(): def string_test(i): l = "Hello, World" - return l[i] + return ord(l[i]) f = compile_function(string_test, [int]) assert f(0) == ord("H") From rxe at codespeak.net Mon Jul 11 02:34:39 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 11 Jul 2005 02:34:39 +0200 (CEST) Subject: [pypy-svn] r14482 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050711003439.8EEED27B3F@code1.codespeak.net> Author: rxe Date: Mon Jul 11 02:34:37 2005 New Revision: 14482 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Add some more interesting tests. Need some help to fix these! :-) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Mon Jul 11 02:34:37 2005 @@ -293,6 +293,37 @@ f = compile_function(string_test, [int]) assert f(0) == ord("H") +def test_list_of_string(): + a = ["hello", "world"] + def string_simple(i, j, k, l): + s = a[i][j] + a[k][l] + return ord(s[0]) + ord(s[1]) + f = compile_function(string_simple, [int, int, int, int]) + assert f(0, 0, 1, 4) == ord("h") + ord("d") + +def Xtest_dict_creation(): + d = {'hello' : 23, + 'world' : 21} + l = ["hello", "world"] + def createdict(i, j): + return d[l[i]] + d[l[j]] + f = compile_function(createdict, [int, int], view=True) + + assert createdict(0, 1) == 43 + +def Xtest_method_call(): + class MyBase: + def m(self, x): + return self.z + x + + def method_call(a, b): + obj = MyBase() + obj.z = a + return obj.m(b) + f = compile_function(f, [int, int], view=True) + assert f(4, 5) == 9 + + class TestException(Exception): pass From ac at codespeak.net Mon Jul 11 10:26:27 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 11 Jul 2005 10:26:27 +0200 (CEST) Subject: [pypy-svn] r14486 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050711082627.E3A1727B43@code1.codespeak.net> Author: ac Date: Mon Jul 11 10:26:27 2005 New Revision: 14486 Modified: pypy/dist/pypy/objspace/std/test/test_unicodeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: Implement repr for unicode strings. 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 Mon Jul 11 10:26:27 2005 @@ -169,3 +169,10 @@ def test_float_from_unicode(self): assert float(u'123.456e89') == float('123.456e89') + + def test_repr(self): + for ustr in [u"", u"a", u"'", u"\'", u"\"", u"\t", u"\\", u'', + u'a', u'"', u'\'', u'\"', u'\t', u'\\', u"'''\"", + unichr(19), unichr(2), u'\u1234', u'\U00101234']: + assert eval(repr(ustr)) == ustr + Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Mon Jul 11 10:26:27 2005 @@ -61,9 +61,6 @@ def str_w__Unicode(space, w_uni): return space.str_w(space.str(w_uni)) -def repr__Unicode(space, w_uni): - return space.wrap(repr(u''.join(w_uni._value))) # XXX: We don't support unicodestrings and certainly not repr on them. - def str__Unicode(space, w_uni): return space.call_method(w_uni, 'encode') @@ -871,6 +868,78 @@ unicode_encode__Unicode_ANY_ANY = app.interphook('unicode_encode__Unicode_ANY_ANY') +def repr__Unicode(space, w_unicode): + hexdigits = "0123456789abcdef" + chars = w_unicode._value + size = len(chars) + result = ['\0'] * (2 + size*6 + 1) + result[0] = 'u' + result[1] = "'" + i = 2 + for ch in chars: + if ch == u'\\': + result[i] = result[i + 1] = '\\' + i += 2 + continue + if ch == u"'": + result[i] = '\\' + result[i + 1] = "'" + i += 2 + continue + code = ord(ch) + if code > 0x10000: + # Resize if needed + if i + 12 > len(result): + result.extend(['\0'] * 100) + result[i] = '\\' + result[i + 1] = "U" + result[i + 2] = hexdigits[(code >> 28) & 0xf] + result[i + 3] = hexdigits[(code >> 24) & 0xf] + result[i + 4] = hexdigits[(code >> 20) & 0xf] + result[i + 5] = hexdigits[(code >> 16) & 0xf] + result[i + 6] = hexdigits[(code >> 12) & 0xf] + result[i + 7] = hexdigits[(code >> 8) & 0xf] + result[i + 8] = hexdigits[(code >> 4) & 0xf] + result[i + 9] = hexdigits[(code >> 0) & 0xf] + i += 10 + continue + if code > 0x100: + result[i] = '\\' + result[i + 1] = "u" + result[i + 2] = hexdigits[(code >> 12) & 0xf] + result[i + 3] = hexdigits[(code >> 8) & 0xf] + result[i + 4] = hexdigits[(code >> 4) & 0xf] + result[i + 5] = hexdigits[(code >> 0) & 0xf] + i += 6 + continue + if code == ord('\t'): + result[i] = '\\' + result[i + 1] = "t" + i += 2 + continue + if code == ord('\r'): + result[i] = '\\' + result[i + 1] = "r" + i += 2 + continue + if code == ord('\n'): + result[i] = '\\' + result[i + 1] = "n" + i += 2 + continue + if code < ord(' ') or code >= 0x7f: + result[i] = '\\' + result[i + 1] = "x" + result[i + 2] = hexdigits[(code >> 4) & 0xf] + result[i + 3] = hexdigits[(code >> 0) & 0xf] + i += 4 + continue + result[i] = chr(code) + i += 1 + result[i] = "'" + i += 1 + return space.wrap(''.join(result[:i])) + import unicodetype register_all(vars(), unicodetype) From arigo at codespeak.net Mon Jul 11 12:24:51 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 12:24:51 +0200 (CEST) Subject: [pypy-svn] r14487 - in pypy/dist/pypy/translator/c: . src Message-ID: <20050711102451.E4D2B27B45@code1.codespeak.net> Author: arigo Date: Mon Jul 11 12:24:42 2005 New Revision: 14487 Added: pypy/dist/pypy/translator/c/extfunc.py - copied, changed from r14486, pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/src/ pypy/dist/pypy/translator/c/src/char.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/char_include.h pypy/dist/pypy/translator/c/src/debuginfo.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/g_debuginfo.h pypy/dist/pypy/translator/c/src/exception.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/g_exception.h pypy/dist/pypy/translator/c/src/float.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/float_include.h pypy/dist/pypy/translator/c/src/g_include.h - copied, changed from r14486, pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/src/int.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/src/ll_os.h - copied, changed from r14486, pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/src/ll_time.h (contents, props changed) pypy/dist/pypy/translator/c/src/mem.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/ll_include.h pypy/dist/pypy/translator/c/src/mkuint.py - copied unchanged from r14486, pypy/dist/pypy/translator/c/mkuint.py pypy/dist/pypy/translator/c/src/module.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/g_module.h pypy/dist/pypy/translator/c/src/pyobj.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/pyobj_include.h pypy/dist/pypy/translator/c/src/rtyper.h (contents, props changed) pypy/dist/pypy/translator/c/src/support.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/g_support.h pypy/dist/pypy/translator/c/src/trace.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/g_trace.h pypy/dist/pypy/translator/c/src/unichar.h - copied unchanged from r14486, pypy/dist/pypy/translator/c/unichar_include.h Removed: pypy/dist/pypy/translator/c/char_include.h pypy/dist/pypy/translator/c/extfunc_include.h pypy/dist/pypy/translator/c/fixedname.py pypy/dist/pypy/translator/c/float_include.h pypy/dist/pypy/translator/c/g_debuginfo.h pypy/dist/pypy/translator/c/g_exception.h pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/g_module.h pypy/dist/pypy/translator/c/g_support.h pypy/dist/pypy/translator/c/g_trace.h pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/ll_include.h pypy/dist/pypy/translator/c/mkuint.py pypy/dist/pypy/translator/c/pyobj_include.h pypy/dist/pypy/translator/c/unichar_include.h Modified: pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py Log: Cleaned up the genc directory by moving the .h files to their own subdirectory. Split the extfunc_include.h into module-specific include files, ll_os.h and ll_time.h. Deleted: /pypy/dist/pypy/translator/c/char_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/char_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,15 +0,0 @@ -/************************************************************/ -/*** C header subsection: operations between chars ***/ - -/*** unary operations ***/ - -/*** binary operations ***/ - - -#define OP_CHAR_EQ(x,y,r,err) r = ((x) == (y)); -#define OP_CHAR_NE(x,y,r,err) r = ((x) != (y)); -#define OP_CHAR_LE(x,y,r,err) r = ((unsigned char)(x) <= (unsigned char)(y)); -#define OP_CHAR_GT(x,y,r,err) r = ((unsigned char)(x) > (unsigned char)(y)); -#define OP_CHAR_LT(x,y,r,err) r = ((unsigned char)(x) < (unsigned char)(y)); -#define OP_CHAR_GE(x,y,r,err) r = ((unsigned char)(x) >= (unsigned char)(y)); - Copied: pypy/dist/pypy/translator/c/extfunc.py (from r14486, pypy/dist/pypy/translator/c/fixedname.py) ============================================================================== --- pypy/dist/pypy/translator/c/fixedname.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Mon Jul 11 12:24:42 2005 @@ -6,7 +6,7 @@ from pypy.rpython.module import ll_os, ll_time -# table of functions hand-written in extfunc_include.h +# table of functions hand-written in src/ll_*.h EXTERNALS = { ll_os .ll_os_open: 'LL_os_open', ll_os .ll_read_into: 'LL_read_into', Deleted: /pypy/dist/pypy/translator/c/extfunc_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/extfunc_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,88 +0,0 @@ -/************************************************************/ - /*** C header subsection: external functions ***/ - -/******************************************************************/ -#ifdef HAVE_RTYPER /* not defined if we don't have an RTyper */ -/******************************************************************/ - - -#include -#include -#include -#include -#include -#ifndef PATH_MAX - /* assume windows */ - #define PATH_MAX 254 -#endif - -/* The functions below are mapped to functions from pypy.rpython.module.* - by the pypy.translator.c.fixedname.EXTERNALS dictionary. - They should correspond to the functions with the suggested_primitive - flag set, and NOT necessarily directly to the ll_os_*() functions. - See for example ll_read_into(), which is called by ll_os_read(). - The latter would be messy to write here, but LL_read_into() is quite easy. -*/ - -#define RPyString_Size(rps) ((rps)->rs_chars.length) -#define RPyString_AsString(rps) ((rps)->rs_chars.items) - - -/************************************************************/ - /*** os module ***/ - - -int LL_os_open(RPyString *filename, int flag, int mode) -{ - char buf[PATH_MAX]; - int fd, error, namelen = RPyString_Size(filename); - if (namelen >= PATH_MAX) { - RAISE_OSERROR(ENAMETOOLONG); - return -1; - } - else { - memcpy(buf, RPyString_AsString(filename), namelen); - buf[namelen] = 0; - fd = open(buf, flag, mode); - if (fd == -1) - RAISE_OSERROR(errno); - return fd; - } -} - -long LL_read_into(int fd, RPyString *buffer) -{ - long n = read(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); - if (n == -1) - RAISE_OSERROR(errno); - return n; -} - -long LL_os_write(int fd, RPyString *buffer) -{ - long n = write(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); - if (n == -1) - RAISE_OSERROR(errno); - return n; -} - -void LL_os_close(int fd) -{ - if (close(fd) == -1) - RAISE_OSERROR(errno); -} - - -/************************************************************/ - /*** time module ***/ - - -double LL_time_clock(void) -{ - return ((double) clock()) / CLOCKS_PER_SEC; -} - - -/******************************************************************/ -#endif /* HAVE_RTYPER */ -/******************************************************************/ Deleted: /pypy/dist/pypy/translator/c/fixedname.py ============================================================================== --- /pypy/dist/pypy/translator/c/fixedname.py Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,87 +0,0 @@ -import types -from pypy.rpython.lltype import Ptr, pyobjectptr, LowLevelType, _ptr, typeOf -from pypy.translator.c.support import cdecl -from pypy.rpython.rmodel import getfunctionptr -from pypy.rpython.rstr import STR -from pypy.rpython.module import ll_os, ll_time - - -# table of functions hand-written in extfunc_include.h -EXTERNALS = { - ll_os .ll_os_open: 'LL_os_open', - ll_os .ll_read_into: 'LL_read_into', - ll_os .ll_os_write: 'LL_os_write', - ll_os .ll_os_close: 'LL_os_close', - ll_time.ll_time_clock: 'LL_time_clock', - } - - -def predeclare_common_types(db, rtyper): - # Common types - yield ('RPyString', STR) - - -def predeclare_extfuncs(db, rtyper): - for func, funcobj in db.externalfuncs.items(): - c_name = EXTERNALS[func] - funcptr = _ptr(Ptr(typeOf(funcobj)), funcobj) # hum - yield c_name, funcptr - - -def predeclare_exception_data(db, rtyper): - # Exception-related types and constants - exceptiondata = rtyper.getexceptiondata() - - yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) - yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) - - yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) - yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) - yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) - yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) - - for pyexccls in exceptiondata.standardexceptions: - exc_llvalue = exceptiondata.ll_pyexcclass2exc(pyobjectptr(pyexccls)) - # strange naming here because the macro name must be - # a substring of PyExc_%s - yield ('Exc_%s' % pyexccls.__name__, exc_llvalue) - - -def predeclare_all(db, rtyper): - for fn in [predeclare_common_types, - predeclare_exception_data, - predeclare_extfuncs, - ]: - for t in fn(db, rtyper): - yield t - -# ____________________________________________________________ - -def pre_include_code_lines(db, rtyper): - # generate some #defines that go before the #include to provide - # predeclared well-known names for constant objects, functions and - # types. These names are then used by the #included files, like - # g_exception.h. - - def predeclare(c_name, lowlevelobj): - llname = db.get(lowlevelobj) - assert '\n' not in llname - return '#define\t%s\t%s' % (c_name, llname) - - def predeclarefn(c_name, ll_func): - return predeclare(c_name, getfunctionptr(db.translator, ll_func)) - - def predeclaretype(c_typename, lowleveltype): - typename = db.gettype(lowleveltype) - return 'typedef %s;' % cdecl(typename, c_typename) - - yield '#define HAVE_RTYPER' - for c_name, obj in predeclare_all(db, rtyper): - if isinstance(obj, LowLevelType): - yield predeclaretype(c_name, obj) - elif isinstance(obj, types.FunctionType): - yield predeclarefn(c_name, obj) - else: - yield predeclare(c_name, obj) - - db.complete() # because of the get() and gettype() above Deleted: /pypy/dist/pypy/translator/c/float_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/float_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,43 +0,0 @@ - -/************************************************************/ - /*** C header subsection: operations between floats ***/ - - -/* XXX INCOMPLETE */ - - -/*** unary operations ***/ - -#define OP_FLOAT_IS_TRUE(x,r,err) OP_FLOAT_NE(x,0.0,r,err) -#define OP_FLOAT_NEG(x,r,err) r = -x; - - -/*** binary operations ***/ - -#define OP_FLOAT_EQ(x,y,r,err) r = (x == y); -#define OP_FLOAT_NE(x,y,r,err) r = (x != y); -#define OP_FLOAT_LE(x,y,r,err) r = (x <= y); -#define OP_FLOAT_GT(x,y,r,err) r = (x > y); -#define OP_FLOAT_LT(x,y,r,err) r = (x < y); -#define OP_FLOAT_GE(x,y,r,err) r = (x >= y); - -#define OP_FLOAT_CMP(x,y,r,err) \ - r = ((x > y) - (x < y)) - -/* addition, subtraction */ - -#define OP_FLOAT_ADD(x,y,r,err) r = x + y; -#define OP_FLOAT_SUB(x,y,r,err) r = x - y; -#define OP_FLOAT_MUL(x,y,r,err) r = x * y; -#define OP_FLOAT_DIV(x,y,r,err) r = x / y; -#define OP_FLOAT_TRUEDIV(x,y,r,err) OP_FLOAT_DIV(x,y,r,err) -#define OP_FLOAT_MOD(x,y,r,err) r = fmod(x, y); -#define OP_FLOAT_POW(x,y,r,err) r = pow(x, y); - -/*** conversions ***/ - -#define OP_CAST_FLOAT_TO_INT(x,r,err) r = (long)(x); -#define OP_CAST_FLOAT_TO_UINT(x,r,err) r = (unsigned long)(x); -#define OP_CAST_INT_TO_FLOAT(x,r,err) r = (double)(x); -#define OP_CAST_UINT_TO_FLOAT(x,r,err) r = (double)(x); -#define OP_CAST_BOOL_TO_FLOAT(x,r,err) r = (double)(x); Deleted: /pypy/dist/pypy/translator/c/g_debuginfo.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_debuginfo.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,42 +0,0 @@ - -/************************************************************/ - /*** C header subsection: debugging info ***/ - -/* NOTE: this is not included by . - The #include is generated manually if needed. */ - -#undef METHODDEF_DEBUGINFO -#define METHODDEF_DEBUGINFO \ - { "debuginfo_offset", debuginfo_offset, METH_VARARGS }, \ - { "debuginfo_global", debuginfo_global, METH_VARARGS }, \ - { "debuginfo_peek", debuginfo_peek, METH_VARARGS }, - - -static PyObject *debuginfo_offset(PyObject *self, PyObject *args) -{ - int index; - if (!PyArg_ParseTuple(args, "i", &index)) - return NULL; - return PyInt_FromLong(debuginfo_offsets[index]); -} - -static PyObject *debuginfo_global(PyObject *self, PyObject *args) -{ - int index; - if (!PyArg_ParseTuple(args, "i", &index)) - return NULL; - return PyLong_FromVoidPtr(debuginfo_globals[index]); -} - -static PyObject *debuginfo_peek(PyObject *self, PyObject *args) -{ - PyObject *o; - int size; - void *start; - if (!PyArg_ParseTuple(args, "Oi", &o, &size)) - return NULL; - start = PyLong_AsVoidPtr(o); - if (PyErr_Occurred()) - return NULL; - return PyString_FromStringAndSize((char *)start, size); -} Deleted: /pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_exception.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,100 +0,0 @@ - -/************************************************************/ - /*** C header subsection: exceptions ***/ - -static PyObject *RPythonError; - - -/******************************************************************/ -#ifdef HAVE_RTYPER /* RPython version of exceptions */ -/******************************************************************/ - -static RPYTHON_EXCEPTION_VTABLE rpython_exc_type = NULL; -static RPYTHON_EXCEPTION rpython_exc_value = NULL; - -#define ExceptionOccurred() (rpython_exc_type != NULL) - -#define RaiseException(etype, evalue) \ - assert(!ExceptionOccurred()); \ - rpython_exc_type = etype; \ - rpython_exc_value = evalue - -#define FetchException(etypevar, evaluevar, type_of_evaluevar) \ - etypevar = rpython_exc_type; \ - evaluevar = (type_of_evaluevar) rpython_exc_value; \ - rpython_exc_type = NULL; \ - rpython_exc_value = NULL - -#define MatchException(etype) RPYTHON_EXCEPTION_MATCH(rpython_exc_type, \ - (RPYTHON_EXCEPTION_VTABLE) etype) - -static void ConvertExceptionFromCPython(void) -{ - /* convert the CPython exception to an RPython one */ - PyObject *exc_type, *exc_value, *exc_tb; - assert(PyErr_Occurred()); - assert(!ExceptionOccurred()); - PyErr_Fetch(&exc_type, &exc_value, &exc_tb); - /* XXX loosing the error message here */ - rpython_exc_value = RPYTHON_PYEXCCLASS2EXC(exc_type); - rpython_exc_type = RPYTHON_TYPE_OF_EXC_INST(rpython_exc_value); -} - -static void _ConvertExceptionToCPython(void) -{ - /* XXX 1. uses officially bad fishing */ - /* XXX 2. looks for exception classes by name, fragile */ - char* clsname; - PyObject* pycls; - assert(ExceptionOccurred()); - assert(!PyErr_Occurred()); - clsname = rpython_exc_type->ov_name->items; - pycls = PyDict_GetItemString(PyEval_GetBuiltins(), clsname); - if (pycls != NULL && PyClass_Check(pycls) && - PyClass_IsSubclass(pycls, PyExc_Exception)) { - PyErr_SetNone(pycls); - } - else { - PyErr_SetString(RPythonError, clsname); - } -} - -#define ConvertExceptionToCPython(vanishing) \ - _ConvertExceptionToCPython(); \ - vanishing = rpython_exc_value; \ - rpython_exc_type = NULL; \ - rpython_exc_value = NULL; - - -#define RaiseSimpleException(exc, msg) \ - /* XXX 1. uses officially bad fishing */ \ - /* XXX 2. msg is ignored */ \ - rpython_exc_type = (exc)->o_typeptr; \ - rpython_exc_value = (exc); \ - rpython_exc_value->refcount++ - -/******************************************************************/ -#else /* non-RPython version of exceptions, using CPython only */ -/******************************************************************/ - -#define ExceptionOccurred() PyErr_Occurred() -#define RaiseException(etype, evalue) PyErr_Restore(etype, evalue, NULL) -#define FetchException(etypevar, evaluevar, ignored) { \ - PyObject *__tb; \ - PyErr_Fetch(&etypevar, &evaluevar, &__tb); \ - if (evaluevar == NULL) { \ - evaluevar = Py_None; \ - Py_INCREF(Py_None); \ - } \ - Py_XDECREF(__tb); \ - } -#define MatchException(etype) PyErr_ExceptionMatches(etype) -#define ConvertExceptionFromCPython() /* nothing */ -#define ConvertExceptionToCPython(vanishing) vanishing = NULL - -#define RaiseSimpleException(exc, msg) \ - PyErr_SetString(Py##exc, msg) /* pun */ - -/******************************************************************/ -#endif /* HAVE_RTYPER */ -/******************************************************************/ Deleted: /pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,24 +0,0 @@ - -/************************************************************/ -/*** C header file for code produced by genc.py ***/ - -#include "Python.h" -#include "compile.h" -#include "frameobject.h" -#include "structmember.h" -#include "traceback.h" -#include "marshal.h" -#include "eval.h" - -#include "g_exception.h" -#include "g_trace.h" -#include "g_support.h" -#include "g_module.h" - -#include "int_include.h" -#include "char_include.h" -#include "unichar_include.h" -#include "float_include.h" -#include "ll_include.h" -#include "pyobj_include.h" -#include "extfunc_include.h" Deleted: /pypy/dist/pypy/translator/c/g_module.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_module.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,131 +0,0 @@ - -/************************************************************/ - /*** C header subsection: CPython-extension-module-ness ***/ - -#ifdef COUNT_OP_MALLOCS -# define METHODDEF_MALLOC_COUNTERS \ - { "malloc_counters", malloc_counters, METH_VARARGS }, -#else -# define METHODDEF_MALLOC_COUNTERS /* nothing */ -#endif - -#define METHODDEF_DEBUGINFO /* nothing, unless overridden by g_debuginfo.h */ - -#define MODULE_INITFUNC(modname) \ - static PyMethodDef my_methods[] = { \ - METHODDEF_MALLOC_COUNTERS \ - METHODDEF_DEBUGINFO \ - { (char *)NULL, (PyCFunction)NULL } }; \ - PyMODINIT_FUNC init##modname(void) - -#define SETUP_MODULE(modname) \ - PyObject *m = Py_InitModule(#modname, my_methods); \ - PyModule_AddStringConstant(m, "__sourcefile__", __FILE__); \ - this_module_globals = PyModule_GetDict(m); \ - PyGenCFunction_Type.tp_base = &PyCFunction_Type; \ - PyType_Ready(&PyGenCFunction_Type); \ - RPythonError = PyErr_NewException(#modname ".RPythonError", \ - NULL, NULL); \ - if (RPythonError == NULL) \ - return; \ - PyModule_AddObject(m, "RPythonError", RPythonError); \ - if (setup_globalfunctions(globalfunctiondefs, #modname) < 0) \ - return; \ - if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \ - return; \ - if (setup_globalobjects(globalobjectdefs) < 0) \ - return; - - -/*** table of global objects ***/ - -static PyObject *this_module_globals; - -typedef struct { - PyObject** p; - char* name; -} globalobjectdef_t; - -typedef struct { - PyObject** p; - char* gfunc_name; - PyMethodDef ml; -} globalfunctiondef_t; - -static int setup_globalobjects(globalobjectdef_t* def) -{ - PyObject* obj; - - for (; def->p != NULL; def++) { - obj = PyDict_GetItemString(this_module_globals, def->name); - if (obj == NULL) { - PyErr_Format(PyExc_AttributeError, - "initialization code should have " - "created '%s'", def->name); - return -1; - } - Py_INCREF(obj); - *def->p = obj; /* store the object ref in the global var */ - } - return 0; -} - -static int setup_globalfunctions(globalfunctiondef_t* def, char* modname) -{ - PyObject* fn; - PyObject* modname_o = PyString_FromString(modname); - if (modname_o == NULL) - return -1; - - for (; def->p != NULL; def++) { - fn = PyCFunction_NewEx(&def->ml, NULL, modname_o); - if (fn == NULL) - return -1; - fn->ob_type = &PyGenCFunction_Type; - *def->p = fn; /* store the object ref in the global var */ - - if (PyDict_SetItemString(this_module_globals, - def->gfunc_name, - fn) < 0) - return -1; - } - return 0; -} - -static int setup_initcode(char* frozendata[], int len) -{ - PyObject* co; - PyObject* globals; - PyObject* res; - char *buffer, *bufp; - int chunk, count = 0; - - buffer = PyMem_NEW(char, len); - if (buffer == NULL) - return -1; - bufp = buffer; - while (count < len) { - chunk = len-count < 1024 ? len-count : 1024; - memcpy(bufp, *frozendata, chunk); - bufp += chunk; - count += chunk; - ++frozendata; - } - co = PyMarshal_ReadObjectFromString(buffer, len); - if (co == NULL) - return -1; - PyMem_DEL(buffer); - if (!PyCode_Check(co)) { - PyErr_SetString(PyExc_TypeError, "uh?"); - return -1; - } - globals = this_module_globals; - if (PyDict_GetItemString(globals, "__builtins__") == NULL) - PyDict_SetItemString(globals, "__builtins__", - PyEval_GetBuiltins()); - res = PyEval_EvalCode((PyCodeObject *) co, globals, globals); - if (res == NULL) - return -1; - Py_DECREF(res); - return 0; -} Deleted: /pypy/dist/pypy/translator/c/g_support.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_support.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,377 +0,0 @@ - -/************************************************************/ - /*** C header subsection: support functions ***/ - - -/*** misc ***/ - -#if !defined(MIN) -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif /* MIN */ - -#define FAIL_EXCEPTION(err, exc, msg) \ - { \ - RaiseSimpleException(exc, msg); \ - FAIL(err) \ - } -#define FAIL_OVF(err, msg) FAIL_EXCEPTION(err, Exc_OverflowError, msg) -#define FAIL_VAL(err, msg) FAIL_EXCEPTION(err, Exc_ValueError, msg) -#define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, Exc_ZeroDivisionError, msg) -#define CFAIL(err) { ConvertExceptionFromCPython(); FAIL(err) } - -/* we need a subclass of 'builtin_function_or_method' which can be used - as methods: builtin function objects that can be bound on instances */ -static PyObject * -gencfunc_descr_get(PyObject *func, PyObject *obj, PyObject *type) -{ - if (obj == Py_None) - obj = NULL; - return PyMethod_New(func, obj, type); -} -static PyTypeObject PyGenCFunction_Type = { - PyObject_HEAD_INIT(NULL) - 0, - "pypy_generated_function", - sizeof(PyCFunctionObject), - 0, - 0, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - /*&PyCFunction_Type set below*/ 0, /* tp_base */ - 0, /* tp_dict */ - gencfunc_descr_get, /* tp_descr_get */ - 0, /* tp_descr_set */ -}; - - -/*** misc support functions ***/ - -static PyObject* PyList_Pack(int n, ...) -{ - int i; - PyObject *o; - PyObject *result; - va_list vargs; - - va_start(vargs, n); - result = PyList_New(n); - if (result == NULL) { - return NULL; - } - for (i = 0; i < n; i++) { - o = va_arg(vargs, PyObject *); - Py_INCREF(o); - PyList_SET_ITEM(result, i, o); - } - va_end(vargs); - return result; -} - -static PyObject* PyDict_Pack(int n, ...) -{ - int i; - PyObject *key, *val; - PyObject *result; - va_list vargs; - - va_start(vargs, n); - result = PyDict_New(); - if (result == NULL) { - return NULL; - } - for (i = 0; i < n; i++) { - key = va_arg(vargs, PyObject *); - val = va_arg(vargs, PyObject *); - if (PyDict_SetItem(result, key, val) < 0) { - Py_DECREF(result); - return NULL; - } - } - va_end(vargs); - return result; -} - -#if PY_VERSION_HEX < 0x02040000 /* 2.4 */ -static PyObject* PyTuple_Pack(int n, ...) -{ - int i; - PyObject *o; - PyObject *result; - PyObject **items; - va_list vargs; - - va_start(vargs, n); - result = PyTuple_New(n); - if (result == NULL) { - return NULL; - } - items = ((PyTupleObject *)result)->ob_item; - for (i = 0; i < n; i++) { - o = va_arg(vargs, PyObject *); - Py_INCREF(o); - items[i] = o; - } - va_end(vargs); - return result; -} -#endif - -#if PY_VERSION_HEX >= 0x02030000 /* 2.3 */ -# define PyObject_GetItem1 PyObject_GetItem -# define PyObject_SetItem1 PyObject_SetItem -#else -/* for Python 2.2 only */ -static PyObject* PyObject_GetItem1(PyObject* obj, PyObject* index) -{ - int start, stop, step; - if (!PySlice_Check(index)) { - return PyObject_GetItem(obj, index); - } - if (((PySliceObject*) index)->start == Py_None) { - start = -INT_MAX-1; - } else { - start = PyInt_AsLong(((PySliceObject*) index)->start); - if (start == -1 && PyErr_Occurred()) { - return NULL; - } - } - if (((PySliceObject*) index)->stop == Py_None) { - stop = INT_MAX; - } else { - stop = PyInt_AsLong(((PySliceObject*) index)->stop); - if (stop == -1 && PyErr_Occurred()) { - return NULL; - } - } - if (((PySliceObject*) index)->step != Py_None) { - step = PyInt_AsLong(((PySliceObject*) index)->step); - if (step == -1 && PyErr_Occurred()) { - return NULL; - } - if (step != 1) { - PyErr_SetString(PyExc_ValueError, - "obj[slice]: no step allowed"); - return NULL; - } - } - return PySequence_GetSlice(obj, start, stop); -} -static PyObject* PyObject_SetItem1(PyObject* obj, PyObject* index, PyObject* v) -{ - int start, stop, step; - if (!PySlice_Check(index)) { - return PyObject_SetItem(obj, index, v); - } - if (((PySliceObject*) index)->start == Py_None) { - start = -INT_MAX-1; - } else { - start = PyInt_AsLong(((PySliceObject*) index)->start); - if (start == -1 && PyErr_Occurred()) { - return NULL; - } - } - if (((PySliceObject*) index)->stop == Py_None) { - stop = INT_MAX; - } else { - stop = PyInt_AsLong(((PySliceObject*) index)->stop); - if (stop == -1 && PyErr_Occurred()) { - return NULL; - } - } - if (((PySliceObject*) index)->step != Py_None) { - step = PyInt_AsLong(((PySliceObject*) index)->step); - if (step == -1 && PyErr_Occurred()) { - return NULL; - } - if (step != 1) { - PyErr_SetString(PyExc_ValueError, - "obj[slice]: no step allowed"); - return NULL; - } - } - return PySequence_SetSlice(obj, start, stop, v); -} -#endif - -static PyObject* CallWithShape(PyObject* callable, PyObject* shape, ...) -{ - /* XXX the 'shape' argument is a tuple as specified by - XXX pypy.interpreter.argument.fromshape(). This code should - XXX we made independent on the format of the 'shape' later... */ - PyObject* result = NULL; - PyObject* t = NULL; - PyObject* d = NULL; - PyObject* o; - PyObject* key; - PyObject* t2; - int i, nargs, nkwds, starflag, starstarflag; - va_list vargs; - - if (!PyTuple_Check(shape) || - PyTuple_GET_SIZE(shape) != 4 || - !PyInt_Check(PyTuple_GET_ITEM(shape, 0)) || - !PyTuple_Check(PyTuple_GET_ITEM(shape, 1)) || - !PyInt_Check(PyTuple_GET_ITEM(shape, 2)) || - !PyInt_Check(PyTuple_GET_ITEM(shape, 3))) { - Py_FatalError("in genc.h: invalid 'shape' argument"); - } - nargs = PyInt_AS_LONG(PyTuple_GET_ITEM(shape, 0)); - nkwds = PyTuple_GET_SIZE(PyTuple_GET_ITEM(shape, 1)); - starflag = PyInt_AS_LONG(PyTuple_GET_ITEM(shape, 2)); - starstarflag = PyInt_AS_LONG(PyTuple_GET_ITEM(shape, 3)); - - va_start(vargs, shape); - t = PyTuple_New(nargs); - if (t == NULL) - goto finally; - for (i = 0; i < nargs; i++) { - o = va_arg(vargs, PyObject *); - Py_INCREF(o); - PyTuple_SET_ITEM(t, i, o); - } - if (nkwds) { - d = PyDict_New(); - if (d == NULL) - goto finally; - for (i = 0; i < nkwds; i++) { - o = va_arg(vargs, PyObject *); - key = PyTuple_GET_ITEM(PyTuple_GET_ITEM(shape, 1), i); - if (PyDict_SetItem(d, key, o) < 0) - goto finally; - } - } - if (starflag) { - o = va_arg(vargs, PyObject *); - o = PySequence_Tuple(o); - if (o == NULL) - goto finally; - t2 = PySequence_Concat(t, o); - Py_DECREF(o); - Py_DECREF(t); - t = t2; - if (t == NULL) - goto finally; - } - if (starstarflag) { - int len1, len2, len3; - o = va_arg(vargs, PyObject *); - len1 = PyDict_Size(d); - len2 = PyDict_Size(o); - if (len1 < 0 || len2 < 0) - goto finally; - if (PyDict_Update(d, o) < 0) - goto finally; - len3 = PyDict_Size(d); - if (len1 + len2 != len3) { - PyErr_SetString(PyExc_TypeError, - "genc.h: duplicate keyword arguments"); - goto finally; - } - } - va_end(vargs); - - result = PyObject_Call(callable, t, d); - - finally: - Py_XDECREF(d); - Py_XDECREF(t); - return result; -} - -static PyObject* decode_arg(PyObject* fname, int position, PyObject* name, - PyObject* vargs, PyObject* vkwds, PyObject* def) -{ - PyObject* result; - int size = PyTuple_Size(vargs); - if (size < 0) - return NULL; - if (vkwds != NULL) { - result = PyDict_GetItem(vkwds, name); - if (result != NULL) { - if (position < size) { - PyErr_Format(PyExc_TypeError, - "%s() got duplicate value for " - "its '%s' argument", - PyString_AS_STRING(fname), - PyString_AS_STRING(name)); - return NULL; - } - Py_INCREF(result); - return result; - } - } - if (position < size) { - /* common case */ - result = PyTuple_GET_ITEM(vargs, position); - Py_INCREF(result); - return result; - } - if (def != NULL) { - Py_INCREF(def); - return def; - } - PyErr_Format(PyExc_TypeError, "%s() got only %d argument(s)", - PyString_AS_STRING(fname), - position); - return NULL; -} - -static int check_no_more_arg(PyObject* fname, int n, PyObject* vargs) -{ - int size = PyTuple_Size(vargs); - if (size < 0) - return -1; - if (size > n) { - PyErr_Format(PyExc_TypeError, - "%s() got %d argument(s), expected %d", - PyString_AS_STRING(fname), - size, n); - return -1; - } - return 0; -} - -/************************************************************/ - -static PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index) -{ - PyObject *result = PyTuple_GetItem(tuple, index); - Py_XINCREF(result); - return result; -} - -static int PyTuple_SetItem_WithIncref(PyObject *tuple, int index, PyObject *o) -{ - Py_INCREF(o); - return PyTuple_SetItem(tuple, index, o); -} - -#define PyString_FromLLCharArrayAndSize(itemsarray, size) \ - PyString_FromStringAndSize(itemsarray->items, size) - -#define PyString_ToLLCharArray(s, itemsarray) \ - memcpy(itemsarray->items, PyString_AS_STRING(s), \ - itemsarray->length) Deleted: /pypy/dist/pypy/translator/c/g_trace.h ============================================================================== --- /pypy/dist/pypy/translator/c/g_trace.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,313 +0,0 @@ - -/************************************************************/ - /*** C header subsection: pdb tracing of calls ***/ - -/* Set genc_funcdef.USE_CALL_TRACE if you want call trace frames to be built */ - -#if 0 -#define OBNOXIOUS_PRINT_STATEMENTS -#endif - - -/*** Interface ***/ - -#if defined(USE_CALL_TRACE) - -#define TRACE_CALL __f, __tstate -#define TRACE_ARGS PyFrameObject *__f, PyThreadState *__tstate - -#define FAIL(err) { __f->f_lineno = __f->f_code->co_firstlineno = __LINE__; goto err; } - -#define FUNCTION_HEAD(signature, self, args, names, file, line) \ - PyThreadState *__tstate = PyThreadState_GET(); \ - PyObject *__localnames = PyList_CrazyStringPack names; \ - PyFrameObject *__f = traced_function_head(self, args, signature, file, line, __tstate, __localnames); - -#define FUNCTION_CHECK() \ - assert (__f != NULL); - -#define ERR_DECREF(arg) { if (__f->f_locals) { PyDict_SetItemString(__f->f_locals, #arg, arg); } Py_DECREF(arg); } - -#define FUNCTION_RETURN(rval) return traced_function_tail(rval, __f, __tstate); - -#else /* !defined(USE_CALL_TRACE) */ - -#define FAIL(err) { goto err; } - -#define ERR_DECREF(arg) { Py_DECREF(arg); } - -#define FUNCTION_RETURN(rval) return rval; - -#endif /* defined(USE_CALL_TRACE) */ - - -/*** Implementation ***/ - -#if defined(USE_CALL_TRACE) - -static int callstack_depth = -1; -static PyCodeObject* getcode(char *func_name, char *func_filename, int lineno); -static int trace_frame(PyThreadState *tstate, PyFrameObject *f, int code, PyObject *val); -static int trace_frame_exc(PyThreadState *tstate, PyFrameObject *f); - -static int -trace_frame(PyThreadState *tstate, PyFrameObject *f, int code, PyObject *val) -{ - int result = 0; - if (!tstate->use_tracing || tstate->tracing) { - /*printf("if (!tstate->use_tracing || tstate->tracing)\n");*/ - return 0; - } - if (tstate->c_profilefunc != NULL) { - /*printf("if (tstate->c_profilefunc != NULL)\n");*/ - tstate->tracing++; - result = tstate->c_profilefunc(tstate->c_profileobj, - f, code , val); - tstate->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); - tstate->tracing--; - if (result) { - /*printf(" if (result)\n");*/ - return result; - } - } - if (tstate->c_tracefunc != NULL) { - /*printf("if (tstate->c_tracefunc != NULL)\n");*/ - tstate->tracing++; - result = tstate->c_tracefunc(tstate->c_traceobj, - f, code , val); - tstate->use_tracing = ((tstate->c_tracefunc != NULL) - || (tstate->c_profilefunc != NULL)); - tstate->tracing--; - } - /*printf("return result;\n");*/ - return result; -} - -static int -trace_frame_exc(PyThreadState *tstate, PyFrameObject *f) -{ - PyObject *type, *value, *traceback, *arg; - int err; - - if (tstate->c_tracefunc == NULL) { - return 0; - } - - PyErr_Fetch(&type, &value, &traceback); - if (value == NULL) { - value = Py_None; - Py_INCREF(value); - } - arg = PyTuple_Pack(3, type, value, traceback); - if (arg == NULL) { - PyErr_Restore(type, value, traceback); - return 0; - } - err = trace_frame(tstate, f, PyTrace_EXCEPTION, arg); - Py_DECREF(arg); - if (err == 0) { - PyErr_Restore(type, value, traceback); - } else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - } - return err; -} - -static PyCodeObject* -getcode(char *func_name, char *func_filename, int lineno) -{ - PyObject *code = NULL; - PyObject *name = NULL; - PyObject *nulltuple = NULL; - PyObject *filename = NULL; - PyCodeObject *tb_code = NULL; -#if defined(OBNOXIOUS_PRINT_STATEMENTS) - int i; - - printf("%5d: ", lineno); - assert(callstack_depth >= 0); - if (callstack_depth) { - for (i=0; iframe = f; - if (trace_frame(tstate, f, PyTrace_CALL, Py_None) < 0) { - Py_DECREF(args); - callstack_depth--; - return NULL; - } - - return f; -} - -static PyObject *traced_function_tail(PyObject *rval, PyFrameObject *f, PyThreadState *tstate) { - /* - STEALS a reference to f - */ - if (f == NULL) { - goto bad_args; - } - if (rval == NULL) { - if (tstate->curexc_traceback == NULL) { - PyTraceBack_Here(f); - } - if (trace_frame_exc(tstate, f) < 0) { - goto end; - } - } else { - if (trace_frame(tstate, f, PyTrace_RETURN, rval) < 0) { - Py_DECREF(rval); - rval = NULL; - } - } -end: - tstate->frame = f->f_back; - Py_DECREF(f); -bad_args: - callstack_depth--; - return rval; -} - -static PyObject* PyList_CrazyStringPack(char *begin, ...) -{ - PyObject *o; - PyObject *result; - va_list vargs; - - result = PyList_New(0); - if (result == NULL || begin == NULL) { - return result; - } - va_start(vargs, begin); - o = PyString_FromString(begin); - if (o == NULL) { - Py_XDECREF(result); - return NULL; - } - if (PyList_Append(result, o) == -1) { - Py_DECREF(o); - Py_XDECREF(result); - return result; - } - Py_DECREF(o); - while ((begin = va_arg(vargs, char *)) != NULL) { - o = PyString_FromString(begin); - if (o == NULL) { - Py_XDECREF(result); - return NULL; - } - if (PyList_Append(result, o) == -1) { - Py_DECREF(o); - Py_XDECREF(result); - return NULL; - } - Py_DECREF(o); - } - va_end(vargs); - return result; -} - -#endif /* defined(USE_CALL_TRACE) */ Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Mon Jul 11 12:24:42 2005 @@ -2,7 +2,7 @@ import os, py from pypy.translator.c.node import PyObjectNode from pypy.translator.c.database import LowLevelDatabase -from pypy.translator.c.fixedname import pre_include_code_lines +from pypy.translator.c.extfunc import pre_include_code_lines from pypy.translator.gensupp import uniquemodulename from pypy.translator.tool.buildpyxmodule import make_module_from_c from pypy.rpython.lltype import pyobjectptr @@ -79,7 +79,7 @@ print >> f for line in preimplementationlines: print >> f, line - print >> f, '#include "g_include.h"' + print >> f, '#include "src/g_include.h"' print >> f blank = False for node in database.structdeflist: @@ -148,7 +148,7 @@ result = symboltable.generate_global_info(database, node) print >> f, '\t%s,' % (result,) print >> f, '\tNULL };' - print >> f, '#include "g_debuginfo.h"' + print >> f, '#include "src/debuginfo.h"' # # PyObject support (strange) code Deleted: /pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/int_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,267 +0,0 @@ - -/************************************************************/ - /*** C header subsection: operations between ints ***/ - -/*** unary operations ***/ - -#define OP_INT_IS_TRUE(x,r,err) OP_INT_NE(x,0,r,err) - -#define OP_INT_INVERT(x,r,err) r = ~((x)); - -#define OP_INT_POS(x,r,err) r = x; - -#define OP_INT_NEG(x,r,err) r = -(x); - -#define OP_INT_NEG_OVF(x,r,err) \ - OP_INT_NEG(x,r,err) \ - if ((x) >= 0 || (x) != -(x)); \ - else FAIL_OVF(err, "integer negate") - -#define OP_INT_ABS(x,r,err) r = (x) >= 0 ? x : -(x); -#define OP_UINT_ABS(x,r,err) r = (x); - -#define OP_INT_ABS_OVF(x,r,err) \ - OP_INT_ABS(x,r,err) \ - if ((x) >= 0 || (x) != -(x)); \ - else FAIL_OVF(err, "integer absolute") - -/*** binary operations ***/ - -#define OP_INT_EQ(x,y,r,err) r = ((x) == (y)); -#define OP_INT_NE(x,y,r,err) r = ((x) != (y)); -#define OP_INT_LE(x,y,r,err) r = ((x) <= (y)); -#define OP_INT_GT(x,y,r,err) r = ((x) > (y)); -#define OP_INT_LT(x,y,r,err) r = ((x) < (y)); -#define OP_INT_GE(x,y,r,err) r = ((x) >= (y)); - -#define OP_INT_CMP(x,y,r,err) \ - r = (((x) > (y)) - ((x) < (y))) - -/* addition, subtraction */ - -#define OP_INT_ADD(x,y,r,err) r = (x) + (y); - -#define OP_INT_ADD_OVF(x,y,r,err) \ - OP_INT_ADD(x,y,r,err) \ - if ((r^(x)) >= 0 || (r^(y)) >= 0); \ - else FAIL_OVF(err, "integer addition") - -#define OP_INT_SUB(x,y,r,err) r = (x) - (y); - -#define OP_INT_SUB_OVF(x,y,r,err) \ - OP_INT_SUB(x,y,r,err) \ - if ((r^(x)) >= 0 || (r^~(y)) >= 0); \ - else FAIL_OVF(err, "integer subtraction") - -#define OP_INT_MUL(x,y,r,err) r = (x) * (y); - -#ifndef HAVE_LONG_LONG - -#define OP_INT_MUL_OVF(x,y,r,err) \ - if (op_int_mul_ovf(x,y,&r)); \ - else FAIL_OVF(err, "integer multiplication") - -#else - -#define OP_INT_MUL_OVF(x,y,r,err) \ - { \ - PY_LONG_LONG lr = (PY_LONG_LONG)(x) * (PY_LONG_LONG)(y); \ - r = lr; \ - if ((PY_LONG_LONG)r == lr); \ - else FAIL_OVF(err, "integer multiplication") \ - } -#endif - -/* shifting */ - -/* NB. shifting has same limitations as C: the shift count must be - >= 0 and < LONG_BITS. */ -#define OP_INT_RSHIFT(x,y,r,err) r = Py_ARITHMETIC_RIGHT_SHIFT(long, x, y); -#define OP_UINT_RSHIFT(x,y,r,err) r = (x) >> (y); - -#define OP_INT_LSHIFT(x,y,r,err) r = (x) << (y); -#define OP_UINT_LSHIFT(x,y,r,err) r = (x) << (y); - -#define OP_INT_LSHIFT_OVF(x,y,r,err) \ - OP_INT_LSHIFT(x,y,r,err) \ - if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ - FAIL_OVF(err, "x<= 0) { OP_INT_RSHIFT(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ - -/* #define OP_INT_LSHIFT(x,y,r,err) \ */ -/* if ((y) < LONG_BIT) \ */ -/* r = (x) << (y); \ */ -/* else r = 0; */ - -/* #define OP_INT_LSHIFT_VAL(x,y,r,err) \ */ -/* if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ - -/* #define OP_INT_LSHIFT_OVF(x,y,r,err) \ */ -/* OP_INT_LSHIFT(x,y,r,err) \ */ -/* if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ */ -/* FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ - - -/* floor division */ - -#define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); -#define OP_UINT_FLOORDIV(x,y,r,err) & Is_Unsigned_Division_Really_Useful; - -#define OP_INT_FLOORDIV_OVF(x,y,r,err) \ - if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ - FAIL_OVF(err, "integer division") \ - OP_INT_FLOORDIV(x,y,r,err) - -#define OP_INT_FLOORDIV_ZER(x,y,r,err) \ - if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ - else FAIL_ZER(err, "integer division") -#define OP_UINT_FLOORDIV_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; - -#define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ - if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ - else FAIL_ZER(err, "integer division") - -/* modulus */ - -#define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); -#define OP_UINT_MOD(x,y,r,err) & Is_Unsigned_Division_Really_Useful; - -#define OP_INT_MOD_OVF(x,y,r,err) \ - if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ - FAIL_OVF(err, "integer modulo") \ - OP_INT_MOD(x,y,r,err); - -#define OP_INT_MOD_ZER(x,y,r,err) \ - if ((y)) { OP_INT_MOD(x,y,r,err) } \ - else FAIL_ZER(err, "integer modulo") -#define OP_UINT_MOD_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; - -#define OP_INT_MOD_OVF_ZER(x,y,r,err) \ - if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ - else FAIL_ZER(err, "integer modulo") - -/* bit operations */ - -#define OP_INT_AND(x,y,r,err) r = (x) & (y); -#define OP_INT_OR( x,y,r,err) r = (x) | (y); -#define OP_INT_XOR(x,y,r,err) r = (x) ^ (y); - -/*** conversions ***/ - -#define OP_CAST_BOOL_TO_INT(x,r,err) r = (long)(x); -#define OP_CAST_BOOL_TO_UINT(x,r,err) r = (unsigned long)(x); -#define OP_CAST_UINT_TO_INT(x,r,err) r = (long)(x); -#define OP_CAST_INT_TO_UINT(x,r,err) r = (unsigned long)(x); -#define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)(x); -#define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); -#define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ - -#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (x); -#define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (Py_UCS4)(x); - -/* bool operations */ - -#define OP_BOOL_NOT(x, r, err) r = !(x); - -/* _________________ certain implementations __________________ */ - -#ifndef HAVE_LONG_LONG -/* adjusted from intobject.c, Python 2.3.3 */ -int -op_int_mul_ovf(long a, long b, long *longprod) -{ - double doubled_longprod; /* (double)longprod */ - double doubleprod; /* (double)a * (double)b */ - - *longprod = a * b; - doubleprod = (double)a * (double)b; - doubled_longprod = (double)*longprod; - - /* Fast path for normal case: small multiplicands, and no info - is lost in either method. */ - if (doubled_longprod == doubleprod) - return 1; - - /* Somebody somewhere lost info. Close enough, or way off? Note - that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0). - The difference either is or isn't significant compared to the - true value (of which doubleprod is a good approximation). - */ - { - const double diff = doubled_longprod - doubleprod; - const double absdiff = diff >= 0.0 ? diff : -diff; - const double absprod = doubleprod >= 0.0 ? doubleprod : - -doubleprod; - /* absdiff/absprod <= 1/32 iff - 32 * absdiff <= absprod -- 5 good bits is "close enough" */ - if (32.0 * absdiff <= absprod) - return 1; - return 0; - } -} -#endif /* HAVE_LONG_LONG */ - -/* XXX we might probe the compiler whether it does what we want */ - -long op_divmod_adj(long x, long y, long *p_rem) -{ - long xdivy = x / y; - long xmody = x - xdivy * y; - /* If the signs of x and y differ, and the remainder is non-0, - * C89 doesn't define whether xdivy is now the floor or the - * ceiling of the infinitely precise quotient. We want the floor, - * and we have it iff the remainder's sign matches y's. - */ - if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) { - xmody += y; - --xdivy; - assert(xmody && ((y ^ xmody) >= 0)); - } - if (p_rem) - *p_rem = xmody; - return xdivy; -} -/* no editing below this point */ -/* following lines are generated by mkuint.py */ - -#define OP_UINT_IS_TRUE OP_INT_IS_TRUE -#define OP_UINT_INVERT OP_INT_INVERT -#define OP_UINT_POS OP_INT_POS -#define OP_UINT_NEG OP_INT_NEG -/* skipping OP_UINT_ABS */ -#define OP_UINT_EQ OP_INT_EQ -#define OP_UINT_NE OP_INT_NE -#define OP_UINT_LE OP_INT_LE -#define OP_UINT_GT OP_INT_GT -#define OP_UINT_LT OP_INT_LT -#define OP_UINT_GE OP_INT_GE -#define OP_UINT_CMP OP_INT_CMP -#define OP_UINT_ADD OP_INT_ADD -#define OP_UINT_SUB OP_INT_SUB -#define OP_UINT_MUL OP_INT_MUL -/* skipping OP_UINT_RSHIFT */ -/* skipping OP_UINT_LSHIFT */ -/* skipping OP_UINT_FLOORDIV */ -/* skipping OP_UINT_FLOORDIV_ZER */ -/* skipping OP_UINT_MOD */ -/* skipping OP_UINT_MOD_ZER */ -#define OP_UINT_AND OP_INT_AND -#define OP_UINT_OR OP_INT_OR -#define OP_UINT_XOR OP_INT_XOR Deleted: /pypy/dist/pypy/translator/c/ll_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/ll_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,44 +0,0 @@ - -/************************************************************/ - /*** C header subsection: operations on LowLevelTypes ***/ - - -/* XXX hack to initialize the refcount of global structures: officially, - we need a value equal to the number of references to this global from - other globals, plus one. This upper bound "approximation" will do... */ -#define REFCOUNT_IMMORTAL (INT_MAX/2) - -#define OP_ZERO_MALLOC(size, r, err) { \ - r = (void*) PyObject_Malloc(size); \ - if (r == NULL) FAIL_EXCEPTION(err, Exc_MemoryError, "out of memory")\ - memset((void*) r, 0, size); \ - COUNT_MALLOC \ - } - -#define OP_FREE(p) { PyObject_Free(p); COUNT_FREE } - - -/*------------------------------------------------------------*/ -#ifndef COUNT_OP_MALLOCS -/*------------------------------------------------------------*/ - -#define COUNT_MALLOC /* nothing */ -#define COUNT_FREE /* nothing */ - -/*------------------------------------------------------------*/ -#else /*COUNT_OP_MALLOCS*/ -/*------------------------------------------------------------*/ - -static int count_mallocs=0, count_frees=0; - -#define COUNT_MALLOC count_mallocs++; -#define COUNT_FREE count_frees++; - -PyObject* malloc_counters(PyObject* self, PyObject* args) -{ - return Py_BuildValue("ii", count_mallocs, count_frees); -} - -/*------------------------------------------------------------*/ -#endif /*COUNT_OP_MALLOCS*/ -/*------------------------------------------------------------*/ Deleted: /pypy/dist/pypy/translator/c/mkuint.py ============================================================================== --- /pypy/dist/pypy/translator/c/mkuint.py Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,36 +0,0 @@ -# auto-generating the unsigned part of int_include.h - -""" -usage: -run this script in int_include.h's folder. - -Rule: -all #define OP_INT_ macros are repeated for uint, -except: -if an int macro is immediately followed by an uint -version, this takes precedence. -""" - -fname = 'int_include.h' - -srclines = [] -lines = [] - -stopline = '/* no editing below this point */' - -for srcline in file(fname): - srcline = srcline.rstrip() - line = srcline.lstrip() - if line.startswith('#define OP_INT_') and line.find('_OVF') < 0: - macroname = line.split('(')[0].split()[1] - newname = 'OP_UINT_' + macroname[7:] - lines.append('#define %s %s' % (newname, macroname)) - elif line.startswith('#define OP_UINT_'): - # comment the last one out - lines.append('/* skipping %s */' % lines.pop().split()[1]) - elif line == stopline: - break - srclines.append(srcline) - -print >> file(fname, 'w'), '\n'.join(srclines + [stopline, - '/* following lines are generated by mkuint.py */', ''] + lines) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Mon Jul 11 12:24:42 2005 @@ -7,7 +7,7 @@ from pypy.translator.c.external import CExternalFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType -from pypy.translator.c import fixedname +from pypy.translator.c import extfunc def needs_refcount(T): @@ -473,11 +473,10 @@ def select_function_code_generator(fnobj, db): - if fnobj._callable in fixedname.EXTERNALS: + if fnobj._callable in extfunc.EXTERNALS: # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive # flag in pypy.rpython.module.*. The corresponding C wrappers are - # written by hand in extfunc_include.h, and declared in - # fixedname.EXTERNALS. + # written by hand in src/ll_*.h, and declared in extfunc.EXTERNALS. db.externalfuncs[fnobj._callable] = fnobj return None elif getattr(fnobj._callable, 'suggested_primitive', False): Deleted: /pypy/dist/pypy/translator/c/pyobj_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/pyobj_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,221 +0,0 @@ - -/************************************************************/ - /*** C header subsection: untyped operations ***/ - /*** as OP_XXX() macros calling the CPython API ***/ - - -#define op_bool(r,err,what) { \ - int _retval = what; \ - if (_retval < 0) { \ - CFAIL(err) \ - } \ - r = PyBool_FromLong(_retval); \ - } - -#define op_richcmp(x,y,r,err,dir) \ - if (!(r=PyObject_RichCompare(x,y,dir))) CFAIL(err) -#define OP_LT(x,y,r,err) op_richcmp(x,y,r,err, Py_LT) -#define OP_LE(x,y,r,err) op_richcmp(x,y,r,err, Py_LE) -#define OP_EQ(x,y,r,err) op_richcmp(x,y,r,err, Py_EQ) -#define OP_NE(x,y,r,err) op_richcmp(x,y,r,err, Py_NE) -#define OP_GT(x,y,r,err) op_richcmp(x,y,r,err, Py_GT) -#define OP_GE(x,y,r,err) op_richcmp(x,y,r,err, Py_GE) - -#define OP_IS_(x,y,r,err) op_bool(r,err,(x == y)) - -#define OP_IS_TRUE(x,r,err) op_bool(r,err,PyObject_IsTrue(x)) -#define OP_NONZERO(x,r,err) op_bool(r,err,PyObject_IsTrue(x)) - -#define OP_LEN(x,r,err) { \ - int _retval = PyObject_Size(x); \ - if (_retval < 0) { \ - CFAIL(err) \ - } \ - r = PyInt_FromLong(_retval); \ - } -#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) CFAIL(err) -#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) CFAIL(err) -#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) CFAIL(err) -#define OP_ABS(x,r,err) if (!(r=PyNumber_Absolute(x))) CFAIL(err) - -#define OP_ADD(x,y,r,err) if (!(r=PyNumber_Add(x,y))) CFAIL(err) -#define OP_SUB(x,y,r,err) if (!(r=PyNumber_Subtract(x,y))) CFAIL(err) -#define OP_MUL(x,y,r,err) if (!(r=PyNumber_Multiply(x,y))) CFAIL(err) -#define OP_TRUEDIV(x,y,r,err) if (!(r=PyNumber_TrueDivide(x,y))) CFAIL(err) -#define OP_FLOORDIV(x,y,r,err) if (!(r=PyNumber_FloorDivide(x,y)))CFAIL(err) -#define OP_DIV(x,y,r,err) if (!(r=PyNumber_Divide(x,y))) CFAIL(err) -#define OP_MOD(x,y,r,err) if (!(r=PyNumber_Remainder(x,y))) CFAIL(err) -#define OP_DIVMOD(x,y,r,err) if (!(r=PyNumber_Divmod(x,y))) CFAIL(err) -#define OP_POW(x,y,z,r,err) if (!(r=PyNumber_Power(x,y,z))) CFAIL(err) -#define OP_LSHIFT(x,y,r,err) if (!(r=PyNumber_Lshift(x,y))) CFAIL(err) -#define OP_RSHIFT(x,y,r,err) if (!(r=PyNumber_Rshift(x,y))) CFAIL(err) -#define OP_AND_(x,y,r,err) if (!(r=PyNumber_And(x,y))) CFAIL(err) -#define OP_OR_(x,y,r,err) if (!(r=PyNumber_Or(x,y))) CFAIL(err) -#define OP_XOR(x,y,r,err) if (!(r=PyNumber_Xor(x,y))) CFAIL(err) - -#define OP_INPLACE_ADD(x,y,r,err) if (!(r=PyNumber_InPlaceAdd(x,y))) \ - CFAIL(err) -#define OP_INPLACE_SUB(x,y,r,err) if (!(r=PyNumber_InPlaceSubtract(x,y))) \ - CFAIL(err) -#define OP_INPLACE_MUL(x,y,r,err) if (!(r=PyNumber_InPlaceMultiply(x,y))) \ - CFAIL(err) -#define OP_INPLACE_TRUEDIV(x,y,r,err) if (!(r=PyNumber_InPlaceTrueDivide(x,y)))\ - CFAIL(err) -#define OP_INPLACE_FLOORDIV(x,y,r,err)if(!(r=PyNumber_InPlaceFloorDivide(x,y)))\ - CFAIL(err) -#define OP_INPLACE_DIV(x,y,r,err) if (!(r=PyNumber_InPlaceDivide(x,y))) \ - CFAIL(err) -#define OP_INPLACE_MOD(x,y,r,err) if (!(r=PyNumber_InPlaceRemainder(x,y))) \ - CFAIL(err) -#define OP_INPLACE_POW(x,y,r,err) if (!(r=PyNumber_InPlacePower(x,y,Py_None))) \ - CFAIL(err) -#define OP_INPLACE_LSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceLshift(x,y))) \ - CFAIL(err) -#define OP_INPLACE_RSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceRshift(x,y))) \ - CFAIL(err) -#define OP_INPLACE_AND(x,y,r,err) if (!(r=PyNumber_InPlaceAnd(x,y))) \ - CFAIL(err) -#define OP_INPLACE_OR(x,y,r,err) if (!(r=PyNumber_InPlaceOr(x,y))) \ - CFAIL(err) -#define OP_INPLACE_XOR(x,y,r,err) if (!(r=PyNumber_InPlaceXor(x,y))) \ - CFAIL(err) - -#define OP_GETITEM(x,y,r,err) if (!(r=PyObject_GetItem1(x,y))) CFAIL(err) -#define OP_SETITEM(x,y,z,r,err) if ((PyObject_SetItem1(x,y,z))<0) CFAIL(err) \ - r=Py_None; Py_INCREF(r); -#define OP_DELITEM(x,y,r,err) if ((PyObject_DelItem(x,y))<0) CFAIL(err) \ - r=Py_None; Py_INCREF(r); -#define OP_CONTAINS(x,y,r,err) op_bool(r,err,(PySequence_Contains(x,y))) - -#define OP_GETATTR(x,y,r,err) if (!(r=PyObject_GetAttr(x,y))) CFAIL(err) -#define OP_SETATTR(x,y,z,r,err) if ((PyObject_SetAttr(x,y,z))<0) CFAIL(err) \ - r=Py_None; Py_INCREF(r); -#define OP_DELATTR(x,y,r,err) if ((PyObject_SetAttr(x,y,NULL))<0)CFAIL(err) \ - r=Py_None; Py_INCREF(r); - -#define OP_NEWSLICE(x,y,z,r,err) if (!(r=PySlice_New(x,y,z))) CFAIL(err) - -#define OP_GETSLICE(x,y,z,r,err) { \ - PyObject *__yo = y, *__zo = z; \ - int __y = 0, __z = INT_MAX; \ - if (__yo == Py_None) __yo = NULL; \ - if (__zo == Py_None) __zo = NULL; \ - if (!_PyEval_SliceIndex(__yo, &__y) || \ - !_PyEval_SliceIndex(__zo, &__z) || \ - !(r=PySequence_GetSlice(x, __y, __z))) CFAIL(err) \ - } - -#define OP_ALLOC_AND_SET(x,y,r,err) { \ - /* XXX check for long/int overflow */ \ - int __i, __x = PyInt_AsLong(x); \ - if (PyErr_Occurred()) CFAIL(err) \ - if (!(r = PyList_New(__x))) CFAIL(err) \ - for (__i=0; __i<__x; __i++) { \ - Py_INCREF(y); \ - PyList_SET_ITEM(r, __i, y); \ - } \ - } - -#define OP_ITER(x,r,err) if (!(r=PyObject_GetIter(x))) CFAIL(err) -#define OP_NEXT(x,r,err) if (!(r=PyIter_Next(x))) { \ - if (!PyErr_Occurred()) PyErr_SetNone(PyExc_StopIteration); \ - CFAIL(err) \ - } - -#define OP_STR(x,r,err) if (!(r=PyObject_Str(x))) CFAIL(err) -#define OP_REPR(x,r,err) if (!(r=PyObject_Repr(x))) CFAIL(err) -#define OP_ORD(s,r,err) { \ - char *__c = PyString_AsString(s); \ - int __len; \ - if ( !__c) CFAIL(err) \ - if ((__len = PyString_GET_SIZE(s)) != 1) { \ - PyErr_Format(PyExc_TypeError, \ - "ord() expected a character, but string of length %d found", \ - __len); \ - CFAIL(err) \ - } \ - if (!(r = PyInt_FromLong((unsigned char)(__c[0])))) \ - CFAIL(err) \ - } -#define OP_ID(x,r,err) if (!(r=PyLong_FromVoidPtr(x))) CFAIL(err) -#define OP_HASH(x,r,err) { \ - long __hash = PyObject_Hash(x); \ - if (__hash == -1 && PyErr_Occurred()) CFAIL(err) \ - if (!(r = PyInt_FromLong(__hash))) CFAIL(err) \ - } - -#define OP_HEX(x,r,err) { \ - PyNumberMethods *__nb; \ - if ((__nb = x->ob_type->tp_as_number) == NULL || \ - __nb->nb_hex == NULL) { \ - PyErr_SetString(PyExc_TypeError, \ - "hex() argument can't be converted to hex"); \ - CFAIL(err) \ - } \ - if (!(r = (*__nb->nb_hex)(x))) CFAIL(err) \ - } -#define OP_OCT(x,r,err) { \ - PyNumberMethods *__nb; \ - if ((__nb = x->ob_type->tp_as_number) == NULL || \ - __nb->nb_oct == NULL) { \ - PyErr_SetString(PyExc_TypeError, \ - "oct() argument can't be converted to oct"); \ - CFAIL(err) \ - } \ - if (!(r = (*__nb->nb_oct)(x))) CFAIL(err) \ - } - -#define OP_INT(x,r,err) { \ - long __val = PyInt_AsLong(x); \ - if (__val == -1 && PyErr_Occurred()) CFAIL(err) \ - if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ - } -#define OP_FLOAT(x,r,err) { \ - double __val = PyFloat_AsDouble(x); \ - if (PyErr_Occurred()) CFAIL(err) \ - if (!(r = PyFloat_FromDouble(__val))) CFAIL (err) \ - } - -#define OP_CMP(x,y,r,err) { \ - int __val = PyObject_Compare(x, y); \ - if (PyErr_Occurred()) CFAIL(err) \ - if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ - } - - -#define OP_SIMPLE_CALL(args,r,err) if (!(r=PyObject_CallFunctionObjArgs args)) \ - CFAIL(err) -#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) CFAIL(err) - -/* Needs to act like getattr(x, '__class__', type(x)) */ -#define OP_TYPE(x,r,err) { \ - PyObject *o = x; \ - if (PyInstance_Check(o)) { \ - r = (PyObject*)(((PyInstanceObject*)o)->in_class); \ - } else { \ - r = (PyObject*)o->ob_type; \ - } \ - Py_INCREF(r); \ - } - -/* Needs to act like instance(x,y) */ -#define OP_ISSUBTYPE(x,y,r,err) \ - op_bool(r,err,PyObject_IsSubclass(x, y)) - - -/*** operations with a variable number of arguments ***/ - -#define OP_NEWLIST0(r,err) if (!(r=PyList_New(0))) CFAIL(err) -#define OP_NEWLIST(args,r,err) if (!(r=PyList_Pack args)) CFAIL(err) -#define OP_NEWDICT0(r,err) if (!(r=PyDict_New())) CFAIL(err) -#define OP_NEWDICT(args,r,err) if (!(r=PyDict_Pack args)) CFAIL(err) -#define OP_NEWTUPLE(args,r,err) if (!(r=PyTuple_Pack args)) CFAIL(err) - -/*** argument parsing ***/ - -#define OP_DECODE_ARG(fname, pos, name, vargs, vkwds, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, NULL))) CFAIL(err) -#define OP_DECODE_ARG_DEF(fname, pos, name, vargs, vkwds, def, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) CFAIL(err) -#define OP_CHECK_NO_MORE_ARG(fname, n, vargs, r, err) \ - if (check_no_more_arg(fname, n, vargs) < 0) CFAIL(err) Copied: pypy/dist/pypy/translator/c/src/g_include.h (from r14486, pypy/dist/pypy/translator/c/g_include.h) ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/src/g_include.h Mon Jul 11 12:24:42 2005 @@ -10,15 +10,21 @@ #include "marshal.h" #include "eval.h" -#include "g_exception.h" -#include "g_trace.h" -#include "g_support.h" -#include "g_module.h" +#include "src/exception.h" +#include "src/trace.h" +#include "src/support.h" +#include "src/module.h" -#include "int_include.h" -#include "char_include.h" -#include "unichar_include.h" -#include "float_include.h" -#include "ll_include.h" -#include "pyobj_include.h" -#include "extfunc_include.h" +#include "src/mem.h" +#include "src/int.h" +#include "src/char.h" +#include "src/unichar.h" +#include "src/float.h" +#include "src/pyobj.h" + +/*** modules ***/ +#ifdef HAVE_RTYPER /* only if we have an RTyper */ +# include "src/rtyper.h" +# include "src/ll_os.h" +# include "src/ll_time.h" +#endif Copied: pypy/dist/pypy/translator/c/src/ll_os.h (from r14486, pypy/dist/pypy/translator/c/extfunc_include.h) ============================================================================== --- pypy/dist/pypy/translator/c/extfunc_include.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Mon Jul 11 12:24:42 2005 @@ -1,36 +1,23 @@ /************************************************************/ - /*** C header subsection: external functions ***/ - -/******************************************************************/ -#ifdef HAVE_RTYPER /* not defined if we don't have an RTyper */ -/******************************************************************/ - + /*** C header subsection: os module ***/ #include #include #include #include -#include #ifndef PATH_MAX /* assume windows */ - #define PATH_MAX 254 +# define PATH_MAX 254 #endif /* The functions below are mapped to functions from pypy.rpython.module.* - by the pypy.translator.c.fixedname.EXTERNALS dictionary. + by the pypy.translator.c.extfunc.EXTERNALS dictionary. They should correspond to the functions with the suggested_primitive flag set, and NOT necessarily directly to the ll_os_*() functions. See for example ll_read_into(), which is called by ll_os_read(). The latter would be messy to write here, but LL_read_into() is quite easy. */ -#define RPyString_Size(rps) ((rps)->rs_chars.length) -#define RPyString_AsString(rps) ((rps)->rs_chars.items) - - -/************************************************************/ - /*** os module ***/ - int LL_os_open(RPyString *filename, int flag, int mode) { @@ -71,18 +58,3 @@ if (close(fd) == -1) RAISE_OSERROR(errno); } - - -/************************************************************/ - /*** time module ***/ - - -double LL_time_clock(void) -{ - return ((double) clock()) / CLOCKS_PER_SEC; -} - - -/******************************************************************/ -#endif /* HAVE_RTYPER */ -/******************************************************************/ Added: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/ll_time.h Mon Jul 11 12:24:42 2005 @@ -0,0 +1,11 @@ +/************************************************************/ + /*** C header subsection: time module ***/ + +#include + + +double LL_time_clock(void) +{ + /* XXX gives imprecise results on some systems */ + return ((double) clock()) / CLOCKS_PER_SEC; +} Added: pypy/dist/pypy/translator/c/src/rtyper.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/rtyper.h Mon Jul 11 12:24:42 2005 @@ -0,0 +1,6 @@ +/************************************************************/ + /*** C header subsection: tools for RTyper-aware code ***/ + + +#define RPyString_Size(rps) ((rps)->rs_chars.length) +#define RPyString_AsString(rps) ((rps)->rs_chars.items) Deleted: /pypy/dist/pypy/translator/c/unichar_include.h ============================================================================== --- /pypy/dist/pypy/translator/c/unichar_include.h Mon Jul 11 12:24:42 2005 +++ (empty file) @@ -1,11 +0,0 @@ -/************************************************************/ -/*** C header subsection: operations between chars ***/ - -/*** unary operations ***/ - -/*** binary operations ***/ - -/* typedef unsigned pypy_unichar; */ -#define OP_UNICHAR_EQ(x,y,r,err) r = ((x) == (y)); -#define OP_UNICHAR_NE(x,y,r,err) r = ((x) != (y)); - From arigo at codespeak.net Mon Jul 11 13:35:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 13:35:15 +0200 (CEST) Subject: [pypy-svn] r14491 - in pypy/dist/pypy: rpython translator/c translator/c/src translator/c/test Message-ID: <20050711113515.4481F27B3E@code1.codespeak.net> Author: arigo Date: Mon Jul 11 13:35:10 2005 New Revision: 14491 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/pyobj.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/src/ll_time.h pypy/dist/pypy/translator/c/src/rtyper.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: - a new annotate_helper() utility to be called from extfunc.py, to make a given low-level function available for the C code to call. - implemented os.dup() and os.getcwd() in C. - use the Windows equivalent of time.clock() on Windows. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Mon Jul 11 13:35:10 2005 @@ -387,6 +387,20 @@ return self.bindingrepr(v).lowleveltype return getfunctionptr(self.annotator.translator, graphfunc, getconcretetype) + def annotate_helper(self, ll_function, arglltypes): + """Annotate the given low-level helper function + and return it as a function pointer object. + """ + args_s = [annmodel.lltype_to_annotation(T) for T in arglltypes] + was_frozen = self.annotator.translator.frozen + self.annotator.translator.frozen = False # oh well + try: + ignored, spec_function = annotate_lowlevel_helper(self.annotator, + ll_function, args_s) + finally: + self.annotator.translator.frozen = was_frozen + return self.getfunctionptr(spec_function) + def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): self.call_all_setups() # compute ForwardReferences now if ARG_GCSTRUCT is None: Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Mon Jul 11 13:35:10 2005 @@ -1,5 +1,5 @@ import types -from pypy.rpython.lltype import Ptr, pyobjectptr, LowLevelType, _ptr, typeOf +from pypy.rpython import lltype from pypy.translator.c.support import cdecl from pypy.rpython.rmodel import getfunctionptr from pypy.rpython.rstr import STR @@ -12,6 +12,8 @@ ll_os .ll_read_into: 'LL_read_into', ll_os .ll_os_write: 'LL_os_write', ll_os .ll_os_close: 'LL_os_close', + ll_os .ll_os_dup: 'LL_os_dup', + ll_os .ll_os_getcwd: 'LL_os_getcwd', ll_time.ll_time_clock: 'LL_time_clock', } @@ -21,10 +23,22 @@ yield ('RPyString', STR) +def predeclare_utility_functions(db, rtyper): + # Common utility functions + def RPyString_New(length=lltype.Signed): + return lltype.malloc(STR, length) + + for fname, f in locals().items(): + if isinstance(f, types.FunctionType): + # hack: the defaults give the type of the arguments + fptr = rtyper.annotate_helper(f, f.func_defaults) + yield (fname, fptr) + + def predeclare_extfuncs(db, rtyper): for func, funcobj in db.externalfuncs.items(): c_name = EXTERNALS[func] - funcptr = _ptr(Ptr(typeOf(funcobj)), funcobj) # hum + funcptr = lltype._ptr(lltype.Ptr(lltype.typeOf(funcobj)), funcobj) # hum yield c_name, funcptr @@ -41,7 +55,8 @@ yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) for pyexccls in exceptiondata.standardexceptions: - exc_llvalue = exceptiondata.ll_pyexcclass2exc(pyobjectptr(pyexccls)) + exc_llvalue = exceptiondata.ll_pyexcclass2exc( + lltype.pyobjectptr(pyexccls)) # strange naming here because the macro name must be # a substring of PyExc_%s yield ('Exc_%s' % pyexccls.__name__, exc_llvalue) @@ -49,6 +64,7 @@ def predeclare_all(db, rtyper): for fn in [predeclare_common_types, + predeclare_utility_functions, predeclare_exception_data, predeclare_extfuncs, ]: @@ -76,8 +92,15 @@ return 'typedef %s;' % cdecl(typename, c_typename) yield '#define HAVE_RTYPER' - for c_name, obj in predeclare_all(db, rtyper): - if isinstance(obj, LowLevelType): + decls = list(predeclare_all(db, rtyper)) + + # the following line must be done after all predeclare_xxx(), to specialize + # the functions created by annotate_helper() above. But it must be done + # before db.get(), to ensure that the database only sees specialized blocks. + rtyper.specialize_more_blocks() + + for c_name, obj in decls: + if isinstance(obj, lltype.LowLevelType): yield predeclaretype(c_name, obj) elif isinstance(obj, types.FunctionType): yield predeclarefn(c_name, obj) Modified: pypy/dist/pypy/translator/c/pyobj.py ============================================================================== --- pypy/dist/pypy/translator/c/pyobj.py (original) +++ pypy/dist/pypy/translator/c/pyobj.py Mon Jul 11 13:35:10 2005 @@ -6,7 +6,7 @@ from pypy.translator.gensupp import builtin_base from pypy.rpython.rarithmetic import r_int, r_uint -from pypy.rpython.lltype import pyobjectptr +from pypy.rpython.lltype import pyobjectptr, LowLevelType # XXX maybe this can be done more elegantly: # needed to convince should_translate_attr @@ -214,6 +214,8 @@ def nameof_instance(self, instance): klass = instance.__class__ + if issubclass(klass, LowLevelType): + raise Exception, 'nameof_LowLevelType(%r)' % (instance,) name = self.uniquename('ginst_' + klass.__name__) cls = self.nameof(klass) if hasattr(klass, '__base__'): Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Mon Jul 11 13:35:10 2005 @@ -21,6 +21,7 @@ int LL_os_open(RPyString *filename, int flag, int mode) { + /* XXX unicode_file_names */ char buf[PATH_MAX]; int fd, error, namelen = RPyString_Size(filename); if (namelen >= PATH_MAX) { @@ -31,7 +32,7 @@ memcpy(buf, RPyString_AsString(filename), namelen); buf[namelen] = 0; fd = open(buf, flag, mode); - if (fd == -1) + if (fd < 0) RAISE_OSERROR(errno); return fd; } @@ -40,7 +41,7 @@ long LL_read_into(int fd, RPyString *buffer) { long n = read(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); - if (n == -1) + if (n < 0) RAISE_OSERROR(errno); return n; } @@ -48,13 +49,33 @@ long LL_os_write(int fd, RPyString *buffer) { long n = write(fd, RPyString_AsString(buffer), RPyString_Size(buffer)); - if (n == -1) + if (n < 0) RAISE_OSERROR(errno); return n; } void LL_os_close(int fd) { - if (close(fd) == -1) + if (close(fd) < 0) RAISE_OSERROR(errno); } + +int LL_os_dup(int fd) +{ + fd = dup(fd); + if (fd < 0) + RAISE_OSERROR(errno); + return fd; +} + +RPyString *LL_os_getcwd(void) +{ + char buf[PATH_MAX]; + char *res; + res = getcwd(buf, sizeof buf); + if (res == NULL) { + RAISE_OSERROR(errno); + return NULL; + } + return RPyString_FromString(buf); +} Modified: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_time.h (original) +++ pypy/dist/pypy/translator/c/src/ll_time.h Mon Jul 11 13:35:10 2005 @@ -4,8 +4,46 @@ #include +/****** clock() ******/ + +#if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__) +/* Win32 has better clock replacement + XXX Win64 does not yet, but might when the platform matures. */ + +double LL_time_clock(void) +{ + static LARGE_INTEGER ctrStart; + static double divisor = 0.0; + LARGE_INTEGER now; + double diff; + + if (divisor == 0.0) { + LARGE_INTEGER freq; + QueryPerformanceCounter(&ctrStart); + if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { + /* Unlikely to happen - this works on all intel + machines at least! Revert to clock() */ + return clock(); + } + divisor = (double)freq.QuadPart; + } + QueryPerformanceCounter(&now); + diff = (double)(now.QuadPart - ctrStart.QuadPart); + return diff / divisor; +} + +#else /* if !MS_WINDOWS */ + +#ifndef CLOCKS_PER_SEC +#ifdef CLK_TCK +#define CLOCKS_PER_SEC CLK_TCK +#else +#define CLOCKS_PER_SEC 1000000 +#endif +#endif + double LL_time_clock(void) { - /* XXX gives imprecise results on some systems */ - return ((double) clock()) / CLOCKS_PER_SEC; + return ((double)clock()) / CLOCKS_PER_SEC; } +#endif /* MS_WINDOWS */ Modified: pypy/dist/pypy/translator/c/src/rtyper.h ============================================================================== --- pypy/dist/pypy/translator/c/src/rtyper.h (original) +++ pypy/dist/pypy/translator/c/src/rtyper.h Mon Jul 11 13:35:10 2005 @@ -1,6 +1,16 @@ /************************************************************/ /*** C header subsection: tools for RTyper-aware code ***/ +#include + #define RPyString_Size(rps) ((rps)->rs_chars.length) #define RPyString_AsString(rps) ((rps)->rs_chars.items) + +RPyString *RPyString_FromString(char *buf) +{ + int length = strlen(buf); + RPyString *rps = RPyString_New(length); + memcpy(RPyString_AsString(rps), buf, length); + return rps; +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Mon Jul 11 13:35:10 2005 @@ -53,3 +53,10 @@ f1() assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) + +def test_getcwd(): + def does_stuff(): + return os.getcwd() + f1 = compile(does_stuff, []) + res = f1() + assert res == os.getcwd() From arigo at codespeak.net Mon Jul 11 13:36:38 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 13:36:38 +0200 (CEST) Subject: [pypy-svn] r14492 - pypy/dist/pypy/translator/goal Message-ID: <20050711113638.63B5327B3E@code1.codespeak.net> Author: arigo Date: Mon Jul 11 13:36:37 2005 New Revision: 14492 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/goal/unixcheckpoint.py Log: With -fork, don't wait for user input the first time, and don't show pdb when the user enters 'quit'. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Mon Jul 11 13:36:37 2005 @@ -110,7 +110,7 @@ a.simplify() if a and options['-fork']: from pypy.translator.goal import unixcheckpoint - unixcheckpoint.restartable_point() + unixcheckpoint.restartable_point(auto='run') if a and not options['-no-t']: print 'Specializing...' t.specialize() @@ -540,6 +540,8 @@ if not options['-o']: print 'Running!' targetspec_dic['run'](c_entry_point) + except SystemExit: + raise except: debug(True) else: Modified: pypy/dist/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- pypy/dist/pypy/translator/goal/unixcheckpoint.py (original) +++ pypy/dist/pypy/translator/goal/unixcheckpoint.py Mon Jul 11 13:36:37 2005 @@ -1,14 +1,18 @@ import os -def restartable_point(): +def restartable_point(auto=None): while True: while True: print '---> Checkpoint: run / quit / pdb ?' - try: - line = raw_input().strip().lower() - except (KeyboardInterrupt, EOFError), e: - print '(%s ignored)' % e.__class__.__name__ - continue + if auto: + line = auto + auto = None + else: + try: + line = raw_input().strip().lower() + except (KeyboardInterrupt, EOFError), e: + print '(%s ignored)' % e.__class__.__name__ + continue if line == 'run': break if line == 'quit': From arigo at codespeak.net Mon Jul 11 13:48:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 13:48:57 +0200 (CEST) Subject: [pypy-svn] r14494 - pypy/dist/pypy/rpython Message-ID: <20050711114857.5D85C27B41@code1.codespeak.net> Author: arigo Date: Mon Jul 11 13:48:55 2005 New Revision: 14494 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rpbc.py Log: Issue warnings instead of crashing when prebuilt instances are missing an attribute that the annotator says should be there. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jul 11 13:48:55 2005 @@ -2,7 +2,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef -from pypy.rpython.rmodel import Repr, TyperError, inputconst +from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning from pypy.rpython.lltype import ForwardReference, GcForwardReference from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc from pypy.rpython.lltype import cast_pointer, castable, nullptr @@ -404,7 +404,12 @@ if r.lowleveltype == Void: llattrvalue = None else: - attrvalue = getattr(value, name) + try: + attrvalue = getattr(value, name) + except AttributeError: + warning("prebuilt instance %r has no attribute %r" % ( + value, name)) + continue llattrvalue = r.convert_const(attrvalue) setattr(result, mangled_name, llattrvalue) else: Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Mon Jul 11 13:48:55 2005 @@ -4,6 +4,7 @@ from pypy.rpython.lltype import Void, Bool, Float, Signed, Char, UniChar from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject from pypy.rpython.lltype import FuncType, functionptr +from pypy.tool.ansi_print import ansi_print class Repr: @@ -235,3 +236,5 @@ _callable = getattr(graphfunc, '_specializedversionof_', graphfunc) return functionptr(FT, graphfunc.func_name, graph = graph, _callable = _callable) +def warning(msg): + ansi_print("*** WARNING: %s" % (msg,), esc="31") # RED Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 11 13:48:55 2005 @@ -5,7 +5,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct, Bool from pypy.rpython.lltype import Ptr, malloc, nullptr -from pypy.rpython.rmodel import Repr, TyperError, inputconst +from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning from pypy.rpython import rclass from pypy.rpython.rtyper import HighLevelOp from pypy.rpython import robject @@ -191,8 +191,12 @@ for attr, (mangled_name, r_value) in self.llfieldmap.items(): try: thisattrvalue = self.access_set.values[(pbc, attr)] - except KeyError: - thisattrvalue = getattr(pbc, attr) + except KeyError: + try: + thisattrvalue = getattr(pbc, attr) + except AttributeError: + warning("PBC %r has no attribute %r" % (pbc, name)) + continue llvalue = r_value.convert_const(thisattrvalue) setattr(result, mangled_name, llvalue) return result From arigo at codespeak.net Mon Jul 11 13:53:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 13:53:16 +0200 (CEST) Subject: [pypy-svn] r14495 - pypy/dist/pypy/translator/goal Message-ID: <20050711115316.BB41227B46@code1.codespeak.net> Author: arigo Date: Mon Jul 11 13:53:15 2005 New Revision: 14495 Modified: pypy/dist/pypy/translator/goal/unixcheckpoint.py Log: Added a 'restart' option that restarts the whole process. Meant as a way to discourage us from quitting when we think we will need to restart it all anyway, and then figure out after all that we didn't have to quit. Modified: pypy/dist/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- pypy/dist/pypy/translator/goal/unixcheckpoint.py (original) +++ pypy/dist/pypy/translator/goal/unixcheckpoint.py Mon Jul 11 13:53:15 2005 @@ -1,10 +1,15 @@ import os +def restart_process(): + import sys + os.execv(sys.executable, [sys.executable] + sys.argv) + def restartable_point(auto=None): while True: while True: - print '---> Checkpoint: run / quit / pdb ?' + print '---> Checkpoint: run / restart / quit / pdb ?' if auto: + print 'auto-%s' % (auto,) line = auto auto = None else: @@ -19,6 +24,8 @@ raise SystemExit if line == 'pdb': import pdb; pdb.set_trace() + if line == 'restart': + restart_process() pid = os.fork() if pid != 0: From arigo at codespeak.net Mon Jul 11 13:54:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 13:54:45 +0200 (CEST) Subject: [pypy-svn] r14496 - pypy/dist/pypy/rpython Message-ID: <20050711115445.6D7CE27B4A@code1.codespeak.net> Author: arigo Date: Mon Jul 11 13:54:44 2005 New Revision: 14496 Modified: pypy/dist/pypy/rpython/rpbc.py Log: Typo. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 11 13:54:44 2005 @@ -195,7 +195,7 @@ try: thisattrvalue = getattr(pbc, attr) except AttributeError: - warning("PBC %r has no attribute %r" % (pbc, name)) + warning("PBC %r has no attribute %r" % (pbc, attr)) continue llvalue = r_value.convert_const(thisattrvalue) setattr(result, mangled_name, llvalue) From arigo at codespeak.net Mon Jul 11 14:06:41 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 14:06:41 +0200 (CEST) Subject: [pypy-svn] r14498 - in pypy/dist/pypy/rpython: . test Message-ID: <20050711120641.3EA4227B4B@code1.codespeak.net> Author: arigo Date: Mon Jul 11 14:06:39 2005 New Revision: 14498 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Generally allow None in PBC sets in rpbc.py. Support for None in FunctionsPBCRepr. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 11 14:06:39 2005 @@ -35,6 +35,9 @@ x, classdef)) choice = MethodsPBCRepr + elif x is None: + continue # skipped, a None is allowed implicitely anywhere + elif isinstance(x, (type, types.ClassType)): # classes if x in userclasses: @@ -66,6 +69,8 @@ if len(choices) > 1: raise TyperError("mixed kinds of PBC in the set %r" % ( self.prebuiltinstances,)) + if len(choices) < 1: + return none_frozen_pbc_repr # prebuiltinstances == {None: True} reprcls, = choices return reprcls(rtyper, self) @@ -82,8 +87,8 @@ def getFrozenPBCRepr(rtyper, s_pbc): if len(s_pbc.prebuiltinstances) <= 1: - if s_pbc.const is None: - return none_frozen_pbc_repr + #if s_pbc.const is None: -- take care of by rtyper_makerepr() above + # return none_frozen_pbc_repr return single_frozen_pbc_repr else: pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys() @@ -195,7 +200,7 @@ try: thisattrvalue = getattr(pbc, attr) except AttributeError: - warning("PBC %r has no attribute %r" % (pbc, attr)) + warning("PBC %r has no attribute %r" % (pbc, name)) continue llvalue = r_value.convert_const(thisattrvalue) setattr(result, mangled_name, llvalue) @@ -298,10 +303,15 @@ if self._function_signatures is None: self._function_signatures = {} for func in self.s_pbc.prebuiltinstances: - self._function_signatures[func] = getsignature(self.rtyper,func) + if func is not None: + self._function_signatures[func] = getsignature(self.rtyper, + func) + assert self._function_signatures return self._function_signatures def convert_const(self, value): + if value is None: + return nullptr(self.lowleveltype.TO) if isinstance(value, types.MethodType) and value.im_self is None: value = value.im_func # unbound method -> bare function if value not in self.function_signatures(): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jul 11 14:06:39 2005 @@ -291,3 +291,22 @@ assert res == 123 res = interpret(f, [1]) assert res == 456 + +def test_function_or_None(): + def g1(): + return 42 + def f(i): + g = None + if i > 5: + g = g1 + if i > 6: + return g() + else: + return 12 + + res = interpret(f, [0]) + assert res == 12 + res = interpret(f, [6]) + assert res == 12 + res = interpret(f, [7]) + assert res == 42 From arigo at codespeak.net Mon Jul 11 14:10:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 14:10:20 +0200 (CEST) Subject: [pypy-svn] r14499 - pypy/dist/pypy/rpython Message-ID: <20050711121020.14A5A27B4E@code1.codespeak.net> Author: arigo Date: Mon Jul 11 14:10:19 2005 New Revision: 14499 Modified: pypy/dist/pypy/rpython/rpbc.py Log: Typo, re. Oups, lost this fix somehow. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 11 14:10:19 2005 @@ -200,7 +200,7 @@ try: thisattrvalue = getattr(pbc, attr) except AttributeError: - warning("PBC %r has no attribute %r" % (pbc, name)) + warning("PBC %r has no attribute %r" % (pbc, attr)) continue llvalue = r_value.convert_const(thisattrvalue) setattr(result, mangled_name, llvalue) From arigo at codespeak.net Mon Jul 11 14:17:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Jul 2005 14:17:55 +0200 (CEST) Subject: [pypy-svn] r14500 - in pypy/dist/pypy/rpython: . test Message-ID: <20050711121755.116A227B5C@code1.codespeak.net> Author: arigo Date: Mon Jul 11 14:17:52 2005 New Revision: 14500 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Allow lists to be None (null) in the rtyper. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jul 11 14:17:52 2005 @@ -8,7 +8,7 @@ from pypy.rpython.rclass import InstanceRepr from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive -from pypy.rpython.lltype import Bool +from pypy.rpython.lltype import Bool, nullptr from pypy.rpython import rstr # ____________________________________________________________ @@ -62,6 +62,8 @@ def convert_const(self, listobj): # get object from bound list method #listobj = getattr(listobj, '__self__', listobj) + if listobj is None: + return nullptr(self.LIST) if not isinstance(listobj, list): raise TyperError("expected a list: %r" % (listobj,)) try: @@ -89,6 +91,10 @@ v_lst, = hop.inputargs(self) return hop.gendirectcall(ll_len, v_lst) + def rtype_is_true(self, hop): + v_lst, = hop.inputargs(self) + return hop.gendirectcall(ll_list_is_true, v_lst) + def rtype_method_append(self, hop): v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) @@ -259,6 +265,10 @@ def ll_len(l): return len(l.items) +def ll_list_is_true(l): + # check if a list is True, allowing for None + return bool(l) and len(l.items) != 0 + def ll_append(l, newitem): length = len(l.items) newitems = malloc(typeOf(l).TO.items.TO, length+1) 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 Jul 11 14:17:52 2005 @@ -315,3 +315,20 @@ res = interpret(fn, []) assert ''.join(res.chars) == fn() + +def test_list_or_None(): + empty_list = [] + nonempty_list = [1, 2] + def fn(i): + test = [None, empty_list, nonempty_list][i] + if test: + return 1 + else: + return 0 + + res = interpret(fn, [0]) + assert res == 0 + res = interpret(fn, [1]) + assert res == 0 + res = interpret(fn, [2]) + assert res == 1 From pedronis at codespeak.net Mon Jul 11 18:06:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 11 Jul 2005 18:06:57 +0200 (CEST) Subject: [pypy-svn] r14506 - pypy/branch/pypy-translation-snapshot/module/sys Message-ID: <20050711160657.2DE5C27B41@code1.codespeak.net> Author: pedronis Date: Mon Jul 11 18:06:56 2005 New Revision: 14506 Modified: pypy/branch/pypy-translation-snapshot/module/sys/state.py Log: move to use 2.4.1 library and modifications. Avoid sys.getdefaultenconding (this has been fixed more properly on the trunk with larger changes). Modified: pypy/branch/pypy-translation-snapshot/module/sys/state.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/sys/state.py (original) +++ pypy/branch/pypy-translation-snapshot/module/sys/state.py Mon Jul 11 18:06:56 2005 @@ -59,9 +59,9 @@ from pypy.interpreter import autopath srcdir = os.path.dirname(autopath.pypydir) python_std_lib = os.path.normpath( - os.path.join(autopath.pypydir, os.pardir,'lib-python', '2.3.4')) + os.path.join(autopath.pypydir, os.pardir,'lib-python', '2.4.1')) python_std_lib_modified = os.path.normpath( - os.path.join(autopath.pypydir, os.pardir,'lib-python', 'modified-2.3.4')) + os.path.join(autopath.pypydir, os.pardir,'lib-python', 'modified-2.4.1')) pypy_lib = os.path.join(autopath.pypydir, 'lib') assert os.path.exists(python_std_lib) @@ -89,4 +89,4 @@ return _pypy_getudir(space) def getdefaultencoding(space): - return space.wrap(sys.getdefaultencoding()) + return space.wrap("ascii") From hpk at codespeak.net Tue Jul 12 11:54:19 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 12 Jul 2005 11:54:19 +0200 (CEST) Subject: [pypy-svn] r14535 - pypy/dist/pypy/documentation Message-ID: <20050712095419.5844A27B41@code1.codespeak.net> Author: hpk Date: Tue Jul 12 11:54:18 2005 New Revision: 14535 Added: pypy/dist/pypy/documentation/interpreter.txt (contents, props changed) Modified: pypy/dist/pypy/documentation/architecture.txt pypy/dist/pypy/documentation/parser-design.txt (props changed) Log: issue66: in-progress - a start in providing interpreter-documentation. (only a rough overview-chapter is written for now) - fixeol - I think we should talk about the "bytecode interpreter" to denote the pure bytecode dispatching (but including frame creation, code objects, gatewaying etc.pp.). Modified: pypy/dist/pypy/documentation/architecture.txt ============================================================================== --- pypy/dist/pypy/documentation/architecture.txt (original) +++ pypy/dist/pypy/documentation/architecture.txt Tue Jul 12 11:54:18 2005 @@ -140,11 +140,11 @@ .. _`plain interpreter`: -The Interpreter -=============== +The Bytecode Interpreter +========================= -The *plain interpreter* handles python code objects. The interpreter can build -code objects from Python sources, when needed, by invoking Python's +The *plain bytecode interpreter* handles python code objects. The interpreter can +build code objects from Python sources, when needed, by invoking Python's builtin compiler (we also have a way of constructing those code objects from python source only, but we have not integrated it yet). Code objects are a nicely preprocessed, structured representation of source code, and @@ -342,6 +342,7 @@ .. _`translation process in more details`: .. _`later in this document`: +.. _`initialization time`: RPython, the Flow Object Space and translation ============================================== Added: pypy/dist/pypy/documentation/interpreter.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/interpreter.txt Tue Jul 12 11:54:18 2005 @@ -0,0 +1,104 @@ +=================================== +PyPy - Bytecode Interpreter +=================================== + +.. contents:: +.. sectnum:: + +.. _`Bytecode Interpreter`: architecture.html#the-bytecode-interpreter + + +Introduction +============ + +This document describes the implementation of PyPy's +`Bytecode Interpreter`_ and related basic VM functionalities. + +Overview +============ + +PyPy's bytecode interpreter has a structure reminiscent of +CPython's VM implementation: Source code is parsed and +compiled into code objects which encapsulate information about +their respective functions, class and module body source +codes. Interpreting such code objects means instantiating and +initializing a `Frame class`_ and then calling its +``frame.eval()`` method. This entry point then interprets +each bytecode. + +The bytecode interpreter is only responsible for implementing +control flow and putting and pulling black box objects to and +from the value stack. It does not know how to perform +operations on those black box (`wrapped`_) objects for which +it defers to the `object space`_. In order to implement a +branch in a program's execution, however, it needs to gain +minimal knowledge about a wrapped object. Thus, each object +space offers a ``is_true(w_obj)`` method which returns an +interpreter-level boolean value. + +For the understanding of the interpreter's inner workings it +is crucial to recognize the concepts of `interpreter-level and +application-level`_ code. In short, interpreter-level is executed +directly on the machine and invoking application-level functions +leads to the full prescribed bytecode interpretation indirection. + +The interpreter implementation offers mechanisms to allow a +caller to be unaware if a particular function invocation leads +to bytecode interpretation or is executed directly at +intepreter-level. The two basic kinds of `Gateway classes`_ +expose either an interpreter-level function to +application-level execution (``interp2app``) or allow +transparent invocation of application-level helpers +(``app2interp``) at interpreter-level. + +Another task of the interpreter is to expose its basic +code, frame, module and function objects to application-level +code. Such runtime introspection and modification abilities are +implemented via descriptors. + +A significant complexity lies in the `argument parsing`_ +implementation. Python as a language offers very flexible +ways of providing and receiving arguments for a particular +function invocation. Not only does it take care to get this +right, it also presents difficulties for the `annotation +pass`_ which performs a whole-program analysis on the +bytecode interpreter, argument parsing and gateway-code +in order to infer the types of all values. + +It is for this reason that PyPy sometimes resorts to generate +specialized frame classes and functions at `initialization +time`_ in order to let the annotator only see static program +flows with homogenous name-value assignments on e.g. function +invocations. + +.. _`annotation pass`: translation.html#the-annotation-pass +.. _`initialization time`: architecture.html#initialization-time +.. _`interpreter-level and application-level`: architecture.html#interpreter-level +.. _`wrapped`: coding-guide.html#wrapping-rules +.. _`object space`: architecture.html#objectspace + + +.. _`Frame class`: + +Frame classes +======================== +XXX + +the eval loop +--------------------- + +.. _`argument parsing`: + +Argument Parsing +======================= + +XXX + +.. _`Gateway classes`: + +Gateway classes +======================= + +XXX + + From arigo at codespeak.net Tue Jul 12 12:28:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 12:28:57 +0200 (CEST) Subject: [pypy-svn] r14539 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712102857.9BE2E27B44@code1.codespeak.net> Author: arigo Date: Tue Jul 12 12:28:55 2005 New Revision: 14539 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Handle classes that are never instantiated as plain frozen PBCs. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 12:28:55 2005 @@ -47,7 +47,9 @@ # special case for built-in types, seen in faking choice = getPyObjRepr else: - raise TyperError("don't known about class %r" % (x,)) + # classes that are never instantiated => consider them + # as plain frozen objects + choice = getFrozenPBCRepr elif (classdef, x) in call_families: # other kind of callable 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 Tue Jul 12 12:28:55 2005 @@ -279,15 +279,14 @@ res = interpret(fn, [0]) assert res is False -def INPROGRESS_test_classpbc_getattr(): +def test_classpbc_getattr(): class A: myvalue = 123 class B(A): myvalue = 456 def f(i): - B() # force B and A to have a ClassDef return [A,B][i].myvalue - res = interpret(f, [0], view=True) + res = interpret(f, [0]) assert res == 123 res = interpret(f, [1]) assert res == 456 From arigo at codespeak.net Tue Jul 12 13:31:04 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 13:31:04 +0200 (CEST) Subject: [pypy-svn] r14541 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712113104.C04AC27B3E@code1.codespeak.net> Author: arigo Date: Tue Jul 12 13:31:01 2005 New Revision: 14541 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: This is a bit difficult to describe. See the new test. For a hint about the difficulty see the comments of merge_classpbc_getattr_into_classdef(): # code like 'some_class.attr' will record an attribute access in the # 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. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Tue Jul 12 13:31:01 2005 @@ -198,10 +198,45 @@ value = memo_table.table[(pbc,)] access_set.values[(pbc, fieldname)] = value -def perform_normalizations(annotator): - annotator.frozen += 1 +def merge_classpbc_getattr_into_classdef(rtyper): + # code like 'some_class.attr' will record an attribute access in the + # 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.getpbcaccesssets() + userclasses = rtyper.annotator.getuserclasses() + for access_set in access_sets.infos(): + if len(access_set.objects) <= 1: + continue + count = 0 + for obj in access_set.objects: + if obj in userclasses: + count += 1 + if count == 0: + continue + if count != len(access_set.objects): + raise TyperError("reading attributes %r: mixing instantiated " + "classes with something else in %r" % ( + access_set.attrs.keys(), access_set.objects.keys())) + classdefs = [userclasses[obj] for obj in access_set.objects] + 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(), access_set.objects.keys())) + access_set.commonbase = commonbase + extra_access_sets = rtyper.class_pbc_attributes.setdefault(commonbase, + {}) + extra_access_sets[access_set] = len(extra_access_sets) + + +def perform_normalizations(rtyper): + rtyper.annotator.frozen += 1 try: - normalize_function_signatures(annotator) - specialize_pbcs_by_memotables(annotator) + normalize_function_signatures(rtyper.annotator) + specialize_pbcs_by_memotables(rtyper.annotator) + merge_classpbc_getattr_into_classdef(rtyper) finally: - annotator.frozen -= 1 + rtyper.annotator.frozen -= 1 Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 13:31:01 2005 @@ -120,6 +120,7 @@ # of recursion where other code would uses these # partially-initialized dicts. clsfields = {} + pbcfields = {} allmethods = {} if self.classdef is not None: # class attributes @@ -134,6 +135,15 @@ mangled_name = 'cls_' + name clsfields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) + # 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 = 'pbc%d_%s' % (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() @@ -143,6 +153,7 @@ self.vtable_type.become(vtable_type) allmethods.update(self.rbase.allmethods) self.clsfields = clsfields + self.pbcfields = pbcfields self.allmethods = allmethods self.vtable = None self.initialized = True @@ -224,8 +235,7 @@ # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls mro = list(rsubcls.classdef.getmro()) - for fldname in self.clsfields: - mangled_name, r = self.clsfields[fldname] + for fldname, (mangled_name, r) in self.allclasslevelfields(): if r.lowleveltype == Void: continue for clsdef in mro: @@ -237,6 +247,12 @@ # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls) + def allclasslevelfields(self): + for attr, info in self.clsfields.items(): + yield attr, info + for (access_set, attr), info in self.pbcfields.items(): + yield attr, info + #def fromparentpart(self, v_vtableptr, llops): # """Return the vtable pointer cast from the parent vtable's type # to self's vtable type.""" @@ -281,6 +297,14 @@ raise MissingRTypeAttribute(attr) self.rbase.setclsfield(vcls, attr, vvalue, llops) + def getpbcfield(self, vcls, access_set, attr, llops): + if (access_set, attr) not in self.pbcfields: + raise TyperError("internal error: missing PBC field") + mangled_name, r = self.pbcfields[access_set, attr] + v_vtable = self.fromtypeptr(vcls, llops) + cname = inputconst(Void, mangled_name) + return llops.genop('getfield', [v_vtable, cname], resulttype=r) + def rtype_issubtype(self, hop): class_repr = get_type_repr(self.rtyper) v_cls1, v_cls2 = hop.inputargs(class_repr, class_repr) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 13:31:01 2005 @@ -444,20 +444,32 @@ def __init__(self, rtyper, s_pbc): self.rtyper = rtyper self.s_pbc = s_pbc - assert s_pbc.is_constant() # XXX not implemented - self.lowleveltype = Void -## self.classdefs = {} -## for cls in s_pbc.prebuiltinstances: -## self.classdefs[cls] = rtyper.annotator.getuserclasses()[cls] -## classdefslist = self.classdefs.values() -## commonbase = classdefslist[0] -## for cdef in classdefslist[1:]: -## commonbase = cdef.commonbase(commonbase) -## if commonbase is None: -## raise TyperError("no common base class in PBC set %r" % ( -## s_pbc.prebuiltinstances,)) + assert None not in s_pbc.prebuiltinstances, "XXX not implemented" + if s_pbc.is_constant(): + self.lowleveltype = Void + self.class_repr = None + else: + self.lowleveltype = rclass.TYPEPTR + access_sets = rtyper.annotator.getpbcaccesssets() + classes = s_pbc.prebuiltinstances.keys() + _, _, access = access_sets.find(classes[0]) + for obj in classes[1:]: + _, _, access1 = access_sets.find(obj) + assert access1 is access # XXX not implemented + commonbase = access.commonbase + self.class_repr = rclass.getclassrepr(rtyper, commonbase) + self.access_set = access + + def convert_const(self, cls): + if cls not in self.s_pbc.prebuiltinstances: + raise TyperError("%r not in %r" % (cls, self)) + if self.lowleveltype == Void: + return cls + return self.class_repr.convert_const(cls) def rtype_simple_call(self, hop): + if self.class_repr is not None: + raise NotImplementedError, "XXX" klass = self.s_pbc.const v_instance = rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) try: @@ -479,6 +491,15 @@ hop2.dispatch() return v_instance + def rtype_getattr(self, hop): + if hop.s_result.is_constant(): + return hop.inputconst(hop.r_result, hop.s_result.const) + else: + attr = hop.args_s[1].const + vcls, vattr = hop.inputargs(self, Void) + return self.class_repr.getpbcfield(vcls, self.access_set, attr, + hop.llops) + # ____________________________________________________________ def rtype_call_memo(hop): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 12 13:31:01 2005 @@ -43,6 +43,7 @@ self.class_reprs = {} self.instance_reprs = {} self.pbc_reprs = {} + self.class_pbc_attributes = {} self.typererror = None # make the primitive_to_repr constant mapping self.primitive_to_repr = {} @@ -91,7 +92,7 @@ self.annotator.simplify() # first make sure that all functions called in a group have exactly # the same signature, by hacking their flow graphs if needed - perform_normalizations(self.annotator) + perform_normalizations(self) # new blocks can be created as a result of specialize_block(), so # we need to be careful about the loop here. self.already_seen = {} 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 Tue Jul 12 13:31:01 2005 @@ -309,3 +309,16 @@ assert res == 12 res = interpret(f, [7]) assert res == 42 + +def test_classdef_getattr(): + class A: + myvalue = 123 + class B(A): + myvalue = 456 + def f(i): + B() # for A and B to have classdefs + return [A,B][i].myvalue + res = interpret(f, [0]) + assert res == 123 + res = interpret(f, [1]) + assert res == 456 From arigo at codespeak.net Tue Jul 12 14:59:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 14:59:14 +0200 (CEST) Subject: [pypy-svn] r14543 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712125914.D48C127B44@code1.codespeak.net> Author: arigo Date: Tue Jul 12 14:59:12 2005 New Revision: 14543 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: See the new tests. This code is even more insane than the previous check-in. Well, it does the job. (arigo, pedronis) (PS: we are not too happy with this insanity either -- not happy at all even) Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Tue Jul 12 14:59:12 2005 @@ -1,4 +1,6 @@ +import py import types +import inspect from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, checkgraph from pypy.annotation import model as annmodel @@ -32,20 +34,6 @@ pattern = (argcount+1,) + pattern[1:] func_family.patterns[pattern] = True - # for classes that appear in families, unify their __init__ as well. - for family in call_families.infos(): - prevkey = None - for _, klass in family.objects: - if isinstance(klass, (type, types.ClassType)): - try: - initfunc = klass.__init__.im_func - except AttributeError: - continue - if prevkey is None: - prevkey = (None, initfunc) - else: - call_families.union((None, initfunc), prevkey) - # for bound method objects, make sure the im_func shows up too. for family in call_families.infos(): first = family.objects.keys()[0][1] @@ -72,7 +60,7 @@ # collect functions in this family, ignoring: # - methods: taken care of above # - bound methods: their im_func will also show up - # - classes: their __init__ unbound methods are also families + # - classes: already handled by create_class_constructors() functions = [func for classdef, func in family.objects if classdef is None and not isinstance(func, (type, types.ClassType, types.MethodType))] @@ -231,8 +219,96 @@ {}) extra_access_sets[access_set] = len(extra_access_sets) +def create_class_constructors(rtyper): + # for classes that appear in families, make a __new__ PBC attribute. + call_families = rtyper.annotator.getpbccallfamilies() + access_sets = rtyper.annotator.getpbcaccesssets() + + for family in call_families.infos(): + if len(family.objects) <= 1: + continue + count = 0 + for _, klass in family.objects: + if isinstance(klass, (type, types.ClassType)): + count += 1 + if count == 0: + continue + if count != len(family.objects): + raise TyperError("calls to mixed class/non-class objects in the " + "family %r" % family.objects.keys()) + + klasses = [klass for (_, klass) in family.objects.keys()] + functions = {} + function_values = {} + for klass in klasses: + try: + initfunc = klass.__init__.im_func + except AttributeError: + initfunc = None + # XXX AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH + # bouh. + if initfunc: + args, varargs, varkw, defaults = inspect.getargspec(initfunc) + else: + args, varargs, varkw, defaults = ('self',), None, None, () + args = list(args) + args2 = args[:] + if defaults: + for i in range(-len(defaults), 0): + args[i] += '=None' + if varargs: + args.append('*%s' % varargs) + args2.append('*%s' % varargs) + if varkw: + args.append('**%s' % varkw) + args2.append('**%s' % varkw) + args.pop(0) # 'self' + args2.pop(0) # 'self' + funcsig = ', '.join(args) + callsig = ', '.join(args2) + source = py.code.Source(''' + def %s__new__(%s): + return ____class(%s) + ''' % ( + klass.__name__, funcsig, callsig)) + miniglobals = { + '____class': klass, + } + exec source.compile() in miniglobals + klass__new__ = miniglobals['%s__new__' % klass.__name__] + if initfunc: + klass__new__.func_defaults = initfunc.func_defaults + graph = rtyper.annotator.translator.getflowgraph(initfunc) + args_s = [rtyper.annotator.binding(v) for v in graph.getargs()] + args_s.pop(0) # 'self' + else: + args_s = [] + rtyper.annotator.build_types(klass__new__, args_s) + functions[klass__new__] = True + function_values[klass, '__new__'] = klass__new__ + + _, _, access_set = access_sets.find(klasses[0]) + for klass in klasses[1:]: + _, _, access_set = access_sets.union(klasses[0], klass) + if '__new__' in access_set.attrs: + raise TyperError("PBC access set for classes %r already contains " + "a __new__" % (klasses,)) + access_set.attrs['__new__'] = annmodel.SomePBC(functions) + access_set.values.update(function_values) + + # make a call family for 'functions', copying the call family for + # 'klasses' + functionslist = functions.keys() + key0 = None, functionslist[0] + _, _, new_call_family = call_families.find(key0) + for klass__new__ in functionslist[1:]: + _, _, new_call_family = call_families.union(key0, + (None, klass__new__)) + new_call_family.patterns = family.patterns + def perform_normalizations(rtyper): + create_class_constructors(rtyper) rtyper.annotator.frozen += 1 try: normalize_function_signatures(rtyper.annotator) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 14:59:12 2005 @@ -235,7 +235,8 @@ # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls mro = list(rsubcls.classdef.getmro()) - for fldname, (mangled_name, r) in self.allclasslevelfields(): + for fldname in self.clsfields: + mangled_name, r = self.clsfields[fldname] if r.lowleveltype == Void: continue for clsdef in mro: @@ -244,15 +245,24 @@ llvalue = r.convert_const(value) setattr(vtable, mangled_name, llvalue) break + # extra PBC attributes + for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): + if r.lowleveltype == Void: + continue + for clsdef in mro: + try: + thisattrvalue = access_set.values[clsdef.cls, attr] + except KeyError: + if attr not in clsdef.cls.__dict__: + continue + thisattrvalue = clsdef.cls.__dict__[attr] + llvalue = r.convert_const(thisattrvalue) + setattr(vtable, mangled_name, llvalue) + break + # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls) - def allclasslevelfields(self): - for attr, info in self.clsfields.items(): - yield attr, info - for (access_set, attr), info in self.pbcfields.items(): - yield attr, info - #def fromparentpart(self, v_vtableptr, llops): # """Return the vtable pointer cast from the parent vtable's type # to self's vtable type.""" Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 14:59:12 2005 @@ -469,7 +469,15 @@ def rtype_simple_call(self, hop): if self.class_repr is not None: - raise NotImplementedError, "XXX" + vcls = hop.inputarg(self, arg=0) + vnewfn = self.class_repr.getpbcfield(vcls, self.access_set, + '__new__', hop.llops) + hop2 = hop.copy() + hop2.r_s_popfirstarg() # discard the class pointer argument + hop2.v_s_insertfirstarg(vnewfn, self.access_set.attrs['__new__']) + # now hop2 looks like simple_call(klass__new__, args...) + return hop2.dispatch() + klass = self.s_pbc.const v_instance = rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) try: Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Tue Jul 12 14:59:12 2005 @@ -322,3 +322,39 @@ assert res == 123 res = interpret(f, [1]) assert res == 456 + +def test_call_classes(): + class A: pass + class B(A): pass + def f(i): + if i == 1: + cls = B + else: + cls = A + return cls() + res = interpret(f, [0]) + assert res.super.typeptr.name[0] == 'A' + res = interpret(f, [1]) + assert res.super.typeptr.name[0] == 'B' + +def test_call_classes_with_init(): + class A: + def __init__(self, z): + self.z = z + class B(A): + def __init__(self, z): + A.__init__(self, z) + self.extra = 42 + def f(i, z): + if i == 1: + cls = B + else: + cls = A + return cls(z) + res = interpret(f, [0, 5]) + assert res.super.typeptr.name[0] == 'A' + assert res.inst_z == 5 + res = interpret(f, [1, -7645]) + assert res.super.typeptr.name[0] == 'B' + assert res.inst_z == -7645 + assert res._obj._parentstructure().inst_extra == 42 From pedronis at codespeak.net Tue Jul 12 16:00:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 12 Jul 2005 16:00:53 +0200 (CEST) Subject: [pypy-svn] r14545 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712140053.2DFA227B46@code1.codespeak.net> Author: pedronis Date: Tue Jul 12 16:00:51 2005 New Revision: 14545 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: fixes & test Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Tue Jul 12 16:00:51 2005 @@ -4,7 +4,7 @@ from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, checkgraph from pypy.annotation import model as annmodel -from pypy.tool.sourcetools import has_varargs +from pypy.tool.sourcetools import has_varargs, valid_identifier from pypy.rpython.rmodel import TyperError @@ -237,6 +237,8 @@ raise TyperError("calls to mixed class/non-class objects in the " "family %r" % family.objects.keys()) + patterns = family.patterns.copy() + klasses = [klass for (_, klass) in family.objects.keys()] functions = {} function_values = {} @@ -266,16 +268,17 @@ args2.pop(0) # 'self' funcsig = ', '.join(args) callsig = ', '.join(args2) + klass_name = valid_identifier(klass.__name__) source = py.code.Source(''' def %s__new__(%s): return ____class(%s) ''' % ( - klass.__name__, funcsig, callsig)) + klass_name, funcsig, callsig)) miniglobals = { '____class': klass, } exec source.compile() in miniglobals - klass__new__ = miniglobals['%s__new__' % klass.__name__] + klass__new__ = miniglobals['%s__new__' % klass_name] if initfunc: klass__new__.func_defaults = initfunc.func_defaults graph = rtyper.annotator.translator.getflowgraph(initfunc) @@ -304,7 +307,7 @@ for klass__new__ in functionslist[1:]: _, _, new_call_family = call_families.union(key0, (None, klass__new__)) - new_call_family.patterns = family.patterns + new_call_family.patterns = patterns def perform_normalizations(rtyper): 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 Tue Jul 12 16:00:51 2005 @@ -337,14 +337,14 @@ res = interpret(f, [1]) assert res.super.typeptr.name[0] == 'B' -def test_call_classes_with_init(): +def test_call_classes_with_init2(): class A: def __init__(self, z): self.z = z class B(A): - def __init__(self, z): + def __init__(self, z, x=42): A.__init__(self, z) - self.extra = 42 + self.extra = x def f(i, z): if i == 1: cls = B @@ -358,3 +358,4 @@ assert res.super.typeptr.name[0] == 'B' assert res.inst_z == -7645 assert res._obj._parentstructure().inst_extra == 42 + From arigo at codespeak.net Tue Jul 12 18:38:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 18:38:22 +0200 (CEST) Subject: [pypy-svn] r14550 - pypy/dist/pypy/translator/c/src Message-ID: <20050712163822.53AB427B46@code1.codespeak.net> Author: arigo Date: Tue Jul 12 18:38:20 2005 New Revision: 14550 Modified: pypy/dist/pypy/translator/c/src/ll_os.h Log: Don't need to #include these headers for now, because they come with . This allows the file to compile under Windows and other platforms. Will have to be re-enabled, by copying CPython's #ifdefs and possibly 'configure'-based build system. Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Tue Jul 12 18:38:20 2005 @@ -1,9 +1,9 @@ /************************************************************/ /*** C header subsection: os module ***/ -#include -#include -#include +/*#include -- XXX re-enable with lots of #ifdefs */ +/*#include */ +/*#include */ #include #ifndef PATH_MAX /* assume windows */ From arigo at codespeak.net Tue Jul 12 19:20:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 19:20:57 +0200 (CEST) Subject: [pypy-svn] r14551 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712172057.6823227B4B@code1.codespeak.net> Author: arigo Date: Tue Jul 12 19:20:56 2005 New Revision: 14551 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: staticmethod support in the rtyper. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 19:20:56 2005 @@ -234,6 +234,12 @@ else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls + def assign(mangled_name, value): + if isinstance(value, staticmethod): + value = value.__get__(42) # staticmethod => bare function + llvalue = r.convert_const(value) + setattr(vtable, mangled_name, llvalue) + mro = list(rsubcls.classdef.getmro()) for fldname in self.clsfields: mangled_name, r = self.clsfields[fldname] @@ -242,8 +248,7 @@ for clsdef in mro: if fldname in clsdef.cls.__dict__: value = clsdef.cls.__dict__[fldname] - llvalue = r.convert_const(value) - setattr(vtable, mangled_name, llvalue) + assign(mangled_name, value) break # extra PBC attributes for (access_set, attr), (mangled_name, r) in self.pbcfields.items(): @@ -256,8 +261,7 @@ if attr not in clsdef.cls.__dict__: continue thisattrvalue = clsdef.cls.__dict__[attr] - llvalue = r.convert_const(thisattrvalue) - setattr(vtable, mangled_name, llvalue) + assign(mangled_name, thisattrvalue) break # then initialize the 'super' portion of the vtable 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 Tue Jul 12 19:20:56 2005 @@ -168,3 +168,12 @@ assert interpret(g, [0], view=False, viewbefore=False) == True assert interpret(g, [1], view=False, viewbefore=False) == True +def test_staticmethod(): + class A(object): + f = staticmethod(lambda x, y: x*y) + def f(): + a = A() + return a.f(6, 7) + res = interpret(f, []) + assert res == 42 + From arigo at codespeak.net Tue Jul 12 19:32:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 19:32:09 +0200 (CEST) Subject: [pypy-svn] r14553 - pypy/dist/pypy/rpython Message-ID: <20050712173209.5620727B4B@code1.codespeak.net> Author: arigo Date: Tue Jul 12 19:32:07 2005 New Revision: 14553 Modified: pypy/dist/pypy/rpython/rpbc.py Log: Pass strange faking-related objects through rpbc to GenC as plain PyObjects. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 19:32:07 2005 @@ -17,6 +17,7 @@ # and methods. call_families = rtyper.annotator.getpbccallfamilies() userclasses = rtyper.annotator.getuserclasses() + access_sets = rtyper.annotator.getpbcaccesssets() choices = {} for x, classdef in self.prebuiltinstances.items(): cdefflag = isclassdef(classdef) @@ -62,6 +63,10 @@ else: raise TyperError("don't know about callable %r" % (x,)) + elif isinstance(x, builtin_descriptor_type): + # strange built-in functions, method objects, etc. from fake.py + choice = getPyObjRepr + else: # otherwise, just assume it's a plain frozen object choice = getFrozenPBCRepr @@ -81,6 +86,14 @@ lst.sort() return tuple(lst) +builtin_descriptor_type = ( + type(len), # type 'builtin_function_or_method' + type(list.append), # type 'method_descriptor' + type(type(None).__repr__), # type 'wrapper_descriptor' + type(type.__dict__['__dict__']), # type 'getset_descriptor' + type(type.__dict__['__basicsize__']), # type 'member_descriptor' + ) + # ____________________________________________________________ def getPyObjRepr(rtyper, s_pbc): From arigo at codespeak.net Tue Jul 12 19:38:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 19:38:59 +0200 (CEST) Subject: [pypy-svn] r14557 - in pypy/dist/pypy: rpython translator translator/goal Message-ID: <20050712173859.6EC4F27B4F@code1.codespeak.net> Author: arigo Date: Tue Jul 12 19:38:56 2005 New Revision: 14557 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/translator.py Log: Trying to make specialize() not run a.simplify() again... (messy) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 12 19:38:56 2005 @@ -86,10 +86,11 @@ def bindingrepr(self, var): return self.getrepr(self.binding(var)) - def specialize(self): + def specialize(self, dont_simplify_again=False): """Main entry point: specialize all annotated blocks of the program.""" # specialize depends on annotator simplifications - self.annotator.simplify() + if not dont_simplify_again: + self.annotator.simplify() # first make sure that all functions called in a group have exactly # the same signature, by hacking their flow graphs if needed perform_normalizations(self) Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Tue Jul 12 19:38:56 2005 @@ -13,7 +13,6 @@ defaults to targetpypymain. The .py suffix is optional. -text Don't start the Pygame viewer -no-a Don't infer annotations, just translate everything - -no-s Don't simplify the graph after annotation -no-t Don't type-specialize the graph operations with the C typer -no-o Don't do backend-oriented optimizations -no-c Don't generate the C code @@ -105,7 +104,7 @@ sanity_check_exceptblocks(t) worstblocks_topten(a, 3) find_someobjects(t) - if a and not options['-no-s']: + if a: #and not options['-no-s']: print 'Simplifying...' a.simplify() if a and options['-fork']: @@ -113,7 +112,7 @@ unixcheckpoint.restartable_point(auto='run') if a and not options['-no-t']: print 'Specializing...' - t.specialize() + t.specialize(dont_simplify_again=True) if not options['-no-o']: print 'Back-end optimizations...' t.backend_optimizations() @@ -257,7 +256,6 @@ '-o': False, '-no-mark-some-objects': False, '-no-a': False, - '-no-s': False, '-no-t': False, '-no-o': False, '-tcc': False, @@ -498,7 +496,7 @@ targetspec_dic = loaded_dic['targetspec_dic'] targetspec = loaded_dic['targetspec'] old_options = loaded_dic['options'] - for name in '-no-a -no-s -no-t -no-o'.split(): + for name in '-no-a -no-t -no-o'.split(): # if one of these options has not been set, before, # then the action has been done and must be prevented, now. if not old_options[name]: Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Tue Jul 12 19:38:56 2005 @@ -138,14 +138,14 @@ for graph in self.flowgraphs.itervalues(): checkgraph(graph) - def specialize(self): + def specialize(self, dont_simplify_again=False): if self.annotator is None: raise ValueError("you need to call annotate() first") if self.rtyper is not None: raise ValueError("cannot specialize() several times") from pypy.rpython.rtyper import RPythonTyper self.rtyper = RPythonTyper(self.annotator) - self.rtyper.specialize() + self.rtyper.specialize(dont_simplify_again=dont_simplify_again) def backend_optimizations(self): from pypy.translator.backendoptimization import backend_optimizations From arigo at codespeak.net Tue Jul 12 19:44:52 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 19:44:52 +0200 (CEST) Subject: [pypy-svn] r14558 - pypy/dist/pypy/rpython Message-ID: <20050712174452.3657027B4F@code1.codespeak.net> Author: arigo Date: Tue Jul 12 19:44:49 2005 New Revision: 14558 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py Log: Moved some logic out of HighLevelOp.__init__() into a method setup() that can be called from the proper TyperError-catching context. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 19:44:49 2005 @@ -7,7 +7,6 @@ from pypy.rpython.lltype import Ptr, malloc, nullptr from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning from pypy.rpython import rclass -from pypy.rpython.rtyper import HighLevelOp from pypy.rpython import robject class __extend__(annmodel.SomePBC): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 12 19:44:49 2005 @@ -190,6 +190,7 @@ for hop in self.highlevelops(block, newops): try: + hop.setup() # this is called from here to catch TyperErrors... self.translate_hl_to_ll(hop, varmapping) except TyperError, e: self.gottypererror(e, block, hop.spaceop, newops) @@ -423,20 +424,25 @@ class HighLevelOp(object): def __init__(self, rtyper, spaceop, exceptionlinks, llops): - self.rtyper = rtyper - self.spaceop = spaceop + self.rtyper = rtyper + self.spaceop = spaceop + self.exceptionlinks = exceptionlinks + self.llops = llops + + def setup(self): + rtyper = self.rtyper + spaceop = self.spaceop self.nb_args = len(spaceop.args) - self.llops = llops self.args_v = list(spaceop.args) self.args_s = [rtyper.binding(a) for a in spaceop.args] self.s_result = rtyper.binding(spaceop.result) self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] self.r_result = rtyper.getrepr(self.s_result) rtyper.call_all_setups() # compute ForwardReferences now - self.exceptionlinks = exceptionlinks def copy(self): - result = HighLevelOp.__new__(HighLevelOp) + result = HighLevelOp(self.rtyper, self.spaceop, + self.exceptionlinks, self.llops) for key, value in self.__dict__.items(): if type(value) is list: # grunt value = value[:] From arigo at codespeak.net Tue Jul 12 19:52:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 19:52:43 +0200 (CEST) Subject: [pypy-svn] r14561 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712175243.112B727B4F@code1.codespeak.net> Author: arigo Date: Tue Jul 12 19:52:42 2005 New Revision: 14561 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Calling memo functions with a PBC argument that is a ClassesPBCRepr (as opposed to a MultipleFrozenPBCRepr). Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 19:52:42 2005 @@ -517,8 +517,10 @@ else: attr = hop.args_s[1].const vcls, vattr = hop.inputargs(self, Void) - return self.class_repr.getpbcfield(vcls, self.access_set, attr, - hop.llops) + return self.getfield(vcls, attr, hop.llops) + + def getfield(self, vcls, attr, llops): + return self.class_repr.getpbcfield(vcls, self.access_set, attr, llops) # ____________________________________________________________ @@ -528,6 +530,6 @@ assert hop.nb_args == 2, "XXX" r_pbc = hop.args_r[1] - assert isinstance(r_pbc, MultipleFrozenPBCRepr) + assert isinstance(r_pbc, (MultipleFrozenPBCRepr, ClassesPBCRepr)) v_table, v_pbc = hop.inputargs(Void, r_pbc) return r_pbc.getfield(v_pbc, fieldname, hop.llops) 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 Tue Jul 12 19:52:42 2005 @@ -250,6 +250,25 @@ res = interpret(f1, [1]) assert res == 7 +def test_call_memo_with_class(): + class A: pass + class FooBar(A): pass + def memofn(cls): + return len(cls.__name__) + memofn._annspecialcase_ = "specialize:memo" + + def f1(i): + if i == 1: + cls = A + else: + cls = FooBar + FooBar() # make sure we have ClassDefs + return memofn(cls) + res = interpret(f1, [1]) + assert res == 1 + res = interpret(f1, [2]) + assert res == 6 + def test_rpbc_bound_method_static_call(): class R: def meth(self): From arigo at codespeak.net Tue Jul 12 20:06:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 20:06:27 +0200 (CEST) Subject: [pypy-svn] r14563 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712180627.3D88E27B55@code1.codespeak.net> Author: arigo Date: Tue Jul 12 20:06:25 2005 New Revision: 14563 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: get_unique_interplevel_subclass() is specialized in PyPy. This has the result that the memo calls are only given a single possible argument! Needs to support this in the rtyper. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 20:06:25 2005 @@ -526,6 +526,8 @@ def rtype_call_memo(hop): memo_table = hop.args_v[0].value + if memo_table.s_result.is_constant(): + return hop.inputconst(hop.r_result, memo_table.s_result.const) fieldname = memo_table.fieldname assert hop.nb_args == 2, "XXX" 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 Tue Jul 12 20:06:25 2005 @@ -269,6 +269,18 @@ res = interpret(f1, [2]) assert res == 6 +def test_call_memo_with_single_value(): + class A: pass + def memofn(cls): + return len(cls.__name__) + memofn._annspecialcase_ = "specialize:memo" + + def f1(): + A() # make sure we have a ClassDef + return memofn(A) + res = interpret(f1, []) + assert res == 1 + def test_rpbc_bound_method_static_call(): class R: def meth(self): From arigo at codespeak.net Tue Jul 12 21:47:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 21:47:39 +0200 (CEST) Subject: [pypy-svn] r14566 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712194739.49ADF27B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 21:47:34 2005 New Revision: 14566 Added: pypy/dist/pypy/rpython/objectmodel.py (contents, props changed) Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rspecialcase.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/rpython/test/test_rspecialcase.py Log: More strangeness, more progress: test_rbuiltin.test_instantiate_multiple(). instantiate() is now a "built-in" from the point of view of the annotator, which is progress. All vtables have an entry 'instantiate' that points to a function that instantiates the corresponding class. Building this function is actually "a bit" messy. Then instantiate() can just be implemented by calling it. We are reusing a trick we already used in the previous check-in: here, the function that instantiate a class are defined (in normalizecalls) as def my_instantiate(): return instantiate(cls) which means that instantiate() is actually implemented as follows: if the argument is a known constant class, we instantiate it in the normal way (rclass.py, rtype_new_instance()). Otherwise, we load and call the appropriate version of my_instantiate(), which itself contains again a call to instantiate() -- but this time with a constant 'cls'... For reference, the previous check-in used the same trick for calling classes. A call to a constant class was already implemented some time ago, so a call to a non-constant class can be done by calling a helper function __new__() that is defined as calling a constant class. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Tue Jul 12 21:47:34 2005 @@ -5,7 +5,9 @@ from pypy.objspace.flow.model import SpaceOperation, checkgraph from pypy.annotation import model as annmodel from pypy.tool.sourcetools import has_varargs, valid_identifier +from pypy.tool.sourcetools import func_with_new_name from pypy.rpython.rmodel import TyperError +from pypy.rpython.objectmodel import instantiate def normalize_function_signatures(annotator): @@ -310,6 +312,24 @@ new_call_family.patterns = patterns +def create_instantiate_functions(annotator): + # build the 'instantiate() -> instance of C' functions for the vtables + for cls, classdef in annotator.getuserclasses().items(): + create_instantiate_function(annotator, cls, classdef) + +def create_instantiate_function(annotator, cls, classdef): + def my_instantiate(): + return instantiate(cls) + my_instantiate = func_with_new_name(my_instantiate, + valid_identifier('instantiate_'+cls.__name__)) + annotator.build_types(my_instantiate, []) + # force the result to be converted to a generic OBJECTPTR + generalizedresult = annmodel.SomeInstance(classdef=None) + graph = annotator.translator.getflowgraph(my_instantiate) + annotator.setbinding(graph.getreturnvar(), generalizedresult) + classdef.my_instantiate = my_instantiate + + def perform_normalizations(rtyper): create_class_constructors(rtyper) rtyper.annotator.frozen += 1 @@ -319,3 +339,4 @@ merge_classpbc_getattr_into_classdef(rtyper) finally: rtyper.annotator.frozen -= 1 + create_instantiate_functions(rtyper.annotator) Added: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/objectmodel.py Tue Jul 12 21:47:34 2005 @@ -0,0 +1,14 @@ +""" +This file defines utilities for manipulating objects in an +RPython-compliant way. +""" + +import new + + +def instantiate(cls): + "Create an empty instance of 'cls'." + if isinstance(cls, type): + return object.__new__(cls) + else: + return new.instance(cls) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 12 21:47:34 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython import lltype -from pypy.rpython import rarithmetic +from pypy.rpython import rarithmetic, objectmodel from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, Constant @@ -180,6 +180,23 @@ vlist = hop.inputargs(lltype.Float, lltype.Float) return hop.genop('float_fmod', vlist, resulttype=lltype.Float) +def ll_instantiate(typeptr, RESULT): + my_instantiate = typeptr.instantiate + return lltype.cast_pointer(RESULT, my_instantiate()) + +def rtype_instantiate(hop): + s_class = hop.args_s[0] + assert isinstance(s_class, annmodel.SomePBC) + if len(s_class.prebuiltinstances) != 1: + # instantiate() on a variable class + vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper)) + cresult = hop.inputconst(lltype.Void, hop.r_result.lowleveltype) + return hop.gendirectcall(ll_instantiate, vtypeptr, cresult) + + klass = s_class.const + return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) + + import math ##def ll_floor(f1): ## return float(int((f1) @@ -234,6 +251,7 @@ BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint +BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate import time Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 21:47:34 2005 @@ -8,6 +8,7 @@ from pypy.rpython.lltype import cast_pointer, castable, nullptr from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo +from pypy.rpython.lltype import FuncType # # There is one "vtable" per user class, with the following structure: @@ -17,6 +18,7 @@ # struct object_vtable* parenttypeptr; # RuntimeTypeInfo * rtti; # array { char } * name; +# struct object * instantiate(); # } # # Every other class X, with parent Y, has the structure: @@ -40,13 +42,13 @@ OBJECT_VTABLE = ForwardReference() TYPEPTR = Ptr(OBJECT_VTABLE) +OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) +OBJECTPTR = Ptr(OBJECT) OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR), ('rtti', Ptr(RuntimeTypeInfo)), - ('name', Ptr(Array(Char))))) - -OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) -OBJECTPTR = Ptr(OBJECT) + ('name', Ptr(Array(Char))), + ('instantiate', Ptr(FuncType([], OBJECTPTR))))) def getclassrepr(rtyper, classdef): try: @@ -231,6 +233,11 @@ for i in range(len(name)): vtable.name[i] = name[i] vtable.name[len(name)] = '\x00' + if hasattr(rsubcls.classdef, 'my_instantiate'): + fn = rsubcls.classdef.my_instantiate + vtable.instantiate = self.rtyper.getfunctionptr(fn) + #else: the classdef was created recently, so no instantiate() + # could reach it else: # setup class attributes: for each attribute name at the level # of 'self', look up its value in the subclass rsubcls Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 21:47:34 2005 @@ -459,37 +459,49 @@ assert None not in s_pbc.prebuiltinstances, "XXX not implemented" if s_pbc.is_constant(): self.lowleveltype = Void - self.class_repr = None else: self.lowleveltype = rclass.TYPEPTR - access_sets = rtyper.annotator.getpbcaccesssets() - classes = s_pbc.prebuiltinstances.keys() + self._access_set = None + self._class_repr = None + + def get_access_set(self): + if self._access_set is None: + access_sets = self.rtyper.annotator.getpbcaccesssets() + classes = self.s_pbc.prebuiltinstances.keys() _, _, access = access_sets.find(classes[0]) for obj in classes[1:]: _, _, access1 = access_sets.find(obj) assert access1 is access # XXX not implemented commonbase = access.commonbase - self.class_repr = rclass.getclassrepr(rtyper, commonbase) - self.access_set = access + self._class_repr = rclass.getclassrepr(self.rtyper, commonbase) + self._access_set = access + return self._access_set + + def get_class_repr(self): + self.get_access_set() + return self._class_repr def convert_const(self, cls): if cls not in self.s_pbc.prebuiltinstances: raise TyperError("%r not in %r" % (cls, self)) if self.lowleveltype == Void: return cls - return self.class_repr.convert_const(cls) + return rclass.get_type_repr(self.rtyper).convert_const(cls) def rtype_simple_call(self, hop): - if self.class_repr is not None: + if self.lowleveltype != Void: + # instantiating a class from multiple possible classes vcls = hop.inputarg(self, arg=0) - vnewfn = self.class_repr.getpbcfield(vcls, self.access_set, - '__new__', hop.llops) + access_set = self.get_access_set() + vnewfn = self.get_class_repr().getpbcfield(vcls, access_set, + '__new__', hop.llops) hop2 = hop.copy() hop2.r_s_popfirstarg() # discard the class pointer argument - hop2.v_s_insertfirstarg(vnewfn, self.access_set.attrs['__new__']) + hop2.v_s_insertfirstarg(vnewfn, access_set.attrs['__new__']) # now hop2 looks like simple_call(klass__new__, args...) return hop2.dispatch() + # instantiating a single class klass = self.s_pbc.const v_instance = rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) try: @@ -520,7 +532,15 @@ return self.getfield(vcls, attr, hop.llops) def getfield(self, vcls, attr, llops): - return self.class_repr.getpbcfield(vcls, self.access_set, attr, llops) + access_set = self.get_access_set() + class_repr = self.get_class_repr() + return class_repr.getpbcfield(vcls, access_set, attr, llops) + +class __extend__(pairtype(ClassesPBCRepr, rclass.ClassRepr)): + def convert_from_to((r_clspbc, r_cls), v, llops): + if r_cls.lowleveltype != r_clspbc.lowleveltype: + return NotImplemented # good enough for now + return v # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/rspecialcase.py (original) +++ pypy/dist/pypy/rpython/rspecialcase.py Tue Jul 12 21:47:34 2005 @@ -2,6 +2,7 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython import rclass +from pypy.rpython.rmodel import TyperError def rtype_call_specialcase(hop): @@ -22,11 +23,4 @@ return rtype_override_fn(hop2) -def rtype_override_instantiate(hop): - s_class = hop.args_s[0] - assert isinstance(s_class, annmodel.SomePBC) - if len(s_class.prebuiltinstances) != 1: - raise TyperError("instantiate() on a variable class") - - klass = s_class.const - return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) +# def rtype_override_XXX to be added later Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 12 21:47:34 2005 @@ -1,5 +1,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test import test_llinterp +from pypy.rpython.objectmodel import instantiate from pypy.objspace.flow import model as flowmodel from pypy.tool import udir @@ -132,4 +133,27 @@ c = None return g(c) assert not interpret(fn, [True]) - + +def test_instantiate(): + class A: + pass + def f(): + return instantiate(A) + res = interpret(f, []) + assert res.super.typeptr.name[0] == 'A' + +def test_instantiate_multiple(): + class A: + pass + class B(A): + pass + def f(i): + if i == 1: + cls = A + else: + cls = B + return instantiate(cls) + res = interpret(f, [1]) + assert res.super.typeptr.name[0] == 'A' + res = interpret(f, [2]) + assert res.super.typeptr.name[0] == 'B' Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rspecialcase.py (original) +++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Tue Jul 12 21:47:34 2005 @@ -2,13 +2,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.translator.ann_override import PyPyAnnotatorPolicy -from pypy.interpreter.typedef import instantiate -def test_instantiate(): - class A: - pass - def f(): - return instantiate(A) - res = interpret(f, [], policy=PyPyAnnotatorPolicy()) - assert res.super.typeptr.name[0] == 'A' +# nothing to test here at the moment From arigo at codespeak.net Tue Jul 12 21:51:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 21:51:14 +0200 (CEST) Subject: [pypy-svn] r14569 - in pypy/dist/pypy: annotation interpreter translator Message-ID: <20050712195114.C62EA27B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 21:51:08 2005 New Revision: 14569 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/translator/ann_override.py Log: Forgot these changes in the previous check-in. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Tue Jul 12 21:51:08 2005 @@ -471,10 +471,14 @@ class __extend__(pairtype(SomeInstance, SomeInstance)): def union((ins1, ins2)): - basedef = ins1.classdef.commonbase(ins2.classdef) - if basedef is None: - # print warning? - return SomeObject() + if ins1.classdef is None or ins2.classdef is None: + # special case only + basedef = None + else: + basedef = ins1.classdef.commonbase(ins2.classdef) + if basedef is None: + # print warning? + return SomeObject() return SomeInstance(basedef, can_be_None=ins1.can_be_None or ins2.can_be_None) class __extend__(pairtype(SomeIterator, SomeIterator)): Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 12 21:51:08 2005 @@ -9,11 +9,13 @@ from pypy.annotation.model import SomeList, SomeString, SomeTuple, SomeSlice from pypy.annotation.model import SomeUnicodeCodePoint from pypy.annotation.model import SomeFloat, unionof +from pypy.annotation.model import SomePBC, SomeInstance from pypy.annotation.model import annotation_to_lltype from pypy.annotation.model import add_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper from pypy.objspace.flow.model import Constant import pypy.rpython.rarithmetic +import pypy.rpython.objectmodel # convenience only! def immutablevalue(x): @@ -226,6 +228,17 @@ def rarith_intmask(s_obj): return SomeInteger() +def robjmodel_instantiate(s_clspbc): + assert isinstance(s_clspbc, SomePBC) + clsdef = None + for cls, v in s_clspbc.prebuiltinstances.items(): + if not clsdef: + clsdef = getbookkeeper().getclassdef(cls) + else: + clsdef = clsdef.commonbase(getbookkeeper().getclassdef(cls)) + return SomeInstance(clsdef) + + ##def rarith_ovfcheck(s_obj): ## if isinstance(s_obj, SomeInteger) and s_obj.unsigned: ## getbookkeeper().warning("ovfcheck on unsigned") @@ -263,6 +276,7 @@ ##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck ##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask +BUILTIN_ANALYZERS[pypy.rpython.objectmodel.instantiate] = robjmodel_instantiate BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init BUILTIN_ANALYZERS[OSError.__init__.im_func] = exception_init Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Tue Jul 12 21:51:08 2005 @@ -280,12 +280,16 @@ "Stands for an instance of a (user-defined) class." def __init__(self, classdef, can_be_None=False): self.classdef = classdef - self.knowntype = classdef.cls + if classdef is not None: # XXX should never really be None + self.knowntype = classdef.cls self.can_be_None = can_be_None def fmt_knowntype(self, kt): return None def fmt_classdef(self, cd): - return cd.cls.__name__ + if cd is None: + return 'object' + else: + return cd.cls.__name__ def can_be_none(self): return self.can_be_None Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Tue Jul 12 21:51:08 2005 @@ -7,7 +7,7 @@ from pypy.interpreter.error import OperationError from pypy.tool.cache import Cache from pypy.tool.sourcetools import compile2 -import new +from pypy.rpython.objectmodel import instantiate class TypeDef: def __init__(self, __name, __base=None, **rawdict): @@ -132,14 +132,6 @@ return subcls -def instantiate(cls): - "Create an empty instance of 'cls'." - if isinstance(cls, type): - return object.__new__(cls) - else: - return new.instance(cls) -instantiate._annspecialcase_ = "override:instantiate" - def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): if func is None: return None Modified: pypy/dist/pypy/translator/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/ann_override.py (original) +++ pypy/dist/pypy/translator/ann_override.py Tue Jul 12 21:51:08 2005 @@ -8,16 +8,6 @@ class PyPyAnnotatorPolicy(AnnotatorPolicy): - def override__instantiate(pol, clspbc): - assert isinstance(clspbc, annmodel.SomePBC) - clsdef = None - for cls, v in clspbc.prebuiltinstances.items(): - if not clsdef: - clsdef = getbookkeeper().getclassdef(cls) - else: - clsdef = clsdef.commonbase(getbookkeeper().getclassdef(cls)) - return annmodel.SomeInstance(clsdef) - def override__wrap_exception_cls(pol, space, x): import pypy.objspace.std.typeobject as typeobject clsdef = getbookkeeper().getclassdef(typeobject.W_TypeObject) From arigo at codespeak.net Tue Jul 12 21:52:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 21:52:22 +0200 (CEST) Subject: [pypy-svn] r14570 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050712195222.25D6D27B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 21:52:18 2005 New Revision: 14570 Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Log: Merged revision 14569 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Tue Jul 12 21:52:18 2005 @@ -7,7 +7,7 @@ from pypy.interpreter.error import OperationError from pypy.tool.cache import Cache from pypy.tool.sourcetools import compile2 -import new +from pypy.rpython.objectmodel import instantiate class TypeDef: def __init__(self, __name, __base=None, **rawdict): @@ -132,14 +132,6 @@ return subcls -def instantiate(cls): - "Create an empty instance of 'cls'." - if isinstance(cls, type): - return object.__new__(cls) - else: - return new.instance(cls) -instantiate._annspecialcase_ = "override:instantiate" - def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): if func is None: return None From arigo at codespeak.net Tue Jul 12 22:14:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 22:14:03 +0200 (CEST) Subject: [pypy-svn] r14573 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712201403.74C5627B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 22:14:01 2005 New Revision: 14573 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Implement is_ for two instances (which can have a slightly different annotation). Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 22:14:01 2005 @@ -1,5 +1,5 @@ import types -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning @@ -591,6 +591,14 @@ else: return NotImplemented + def rtype_is_((r_ins1, r_ins2), hop): + if r_ins1.classdef is None or r_ins2.classdef is None: + basedef = None + else: + basedef = r_ins1.classdef.commonbase(r_ins2.classdef) + r_ins = getinstancerepr(r_ins1.rtyper, basedef) + return pairtype(Repr, Repr).rtype_is_(pair(r_ins, r_ins), hop) + # ____________________________________________________________ def rtype_new_instance(rtyper, cls, llops): 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 Tue Jul 12 22:14:01 2005 @@ -177,3 +177,31 @@ res = interpret(f, []) assert res == 42 +def test_is(): + class A: pass + class B(A): pass + class C: pass + def f(i): + a = A() + b = B() + c = C() + d = None + e = None + if i == 0: + d = a + elif i == 1: + d = b + elif i == 2: + e = c + return (0x0001*(a is b) | 0x0002*(a is c) | 0x0004*(a is d) | + 0x0008*(a is e) | 0x0010*(b is c) | 0x0020*(b is d) | + 0x0040*(b is e) | 0x0080*(c is d) | 0x0100*(c is e) | + 0x0200*(d is e)) + res = interpret(f, [0]) + assert res == 0x0004 + res = interpret(f, [1]) + assert res == 0x0020 + res = interpret(f, [2]) + assert res == 0x0100 + res = interpret(f, [3]) + assert res == 0x0200 From arigo at codespeak.net Tue Jul 12 22:23:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 22:23:20 +0200 (CEST) Subject: [pypy-svn] r14576 - pypy/dist/pypy/rpython Message-ID: <20050712202320.2847527B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 22:23:18 2005 New Revision: 14576 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Print a progress report while rtyping. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 12 22:23:18 2005 @@ -118,6 +118,12 @@ for block in pending: self.specialize_block(block) self.already_seen[block] = True + # progress bar + n = len(self.already_seen) + if n % 100 == 0: + total = len(self.annotator.annotated) + print 'specializing: %d / %d blocks (%d%%)' % ( + n, total, 100 * n // total) # make sure all reprs so far have had their setup() called self.call_all_setups() From arigo at codespeak.net Tue Jul 12 22:59:48 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 22:59:48 +0200 (CEST) Subject: [pypy-svn] r14587 - in pypy/dist/pypy/rpython: . test Message-ID: <20050712205948.DD72F27B53@code1.codespeak.net> Author: arigo Date: Tue Jul 12 22:59:46 2005 New Revision: 14587 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Support for call to functions taking *args. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 22:59:46 2005 @@ -1,4 +1,5 @@ import types +import sys from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef @@ -8,6 +9,8 @@ from pypy.rpython.rmodel import Repr, TyperError, inputconst, warning from pypy.rpython import rclass from pypy.rpython import robject +from pypy.rpython import rtuple +from pypy.tool.sourcetools import has_varargs class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): @@ -336,25 +339,44 @@ def rtype_simple_call(self, hop): f, rinputs, rresult = self.function_signatures().itervalues().next() - defaultclist = [] - if len(rinputs) != hop.nb_args-1: # argument count mismatch - assert not getattr(f._obj.graph, 'normalized_for_calls', False), ( - "normalization bug") - assert len(self.function_signatures()) == 1, "normalization bug too" + extravlist = [] + if getattr(f._obj.graph, 'normalized_for_calls', False): + # should not have an argument count mismatch + assert len(rinputs) == hop.nb_args-1, "normalization bug" + else: + # if not normalized, should be a call to a known function + assert len(self.function_signatures()) == 1, "normalization bug" func, = self.function_signatures().keys() + if has_varargs(func): + # collect the arguments for '*arg' into a tuple + rstar = rinputs[-1] + rinputs = rinputs[:-1] + assert isinstance(rstar, rtuple.TupleRepr) + tupleitems_v = [] + for i in range(1+len(rinputs), hop.nb_args): + v = hop.inputarg(rstar.items_r[len(tupleitems_v)], arg=i) + tupleitems_v.append(v) + vtuple = rtuple.newtuple(hop.llops, rstar, tupleitems_v) + extravlist.append(vtuple) + hop = hop.copy() + del hop.args_v[1+len(rinputs):] + del hop.args_s[1+len(rinputs):] + del hop.args_r[1+len(rinputs):] + hop.nb_args = len(hop.args_v) + defaults = func.func_defaults or () if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs): rinputs = list(rinputs) defaults = list(defaults) - while len(rinputs) != hop.nb_args-1: + while len(rinputs) > hop.nb_args-1: c = hop.inputconst(rinputs.pop(), defaults.pop()) - defaultclist.insert(0, c) + extravlist.insert(0, c) else: if hop.nb_args-1 > len(rinputs): - raise RTyperError("too many arguments in function call") + raise TyperError("too many arguments in function call") else: - raise RTyperError("not enough arguments in function call") - vlist = hop.inputargs(self, *rinputs) + defaultclist + raise TyperError("not enough arguments in function call") + vlist = hop.inputargs(self, *rinputs) + extravlist if self.lowleveltype == Void: assert len(self.function_signatures()) == 1 vlist[0] = hop.inputconst(typeOf(f), f) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Tue Jul 12 22:59:46 2005 @@ -390,3 +390,27 @@ assert res.inst_z == -7645 assert res._obj._parentstructure().inst_extra == 42 +def test_call_starargs(): + def g(x=-100, *arg): + return x + len(arg) + def f(i): + if i == -1: + return g() + elif i == 0: + return g(4) + elif i == 1: + return g(5, 15) + elif i == 2: + return g(7, 17, 27) + else: + return g(10, 198, 1129, 13984) + res = interpret(f, [-1]) + assert res == -100 + res = interpret(f, [0]) + assert res == 4 + res = interpret(f, [1]) + assert res == 6 + res = interpret(f, [2]) + assert res == 9 + res = interpret(f, [3]) + assert res == 13 From arigo at codespeak.net Tue Jul 12 23:13:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 23:13:33 +0200 (CEST) Subject: [pypy-svn] r14591 - pypy/dist/pypy/objspace/std Message-ID: <20050712211333.AA66727B52@code1.codespeak.net> Author: arigo Date: Tue Jul 12 23:13:32 2005 New Revision: 14591 Modified: pypy/dist/pypy/objspace/std/listsort.py Log: hint for the annotator: the argument 'rightmost' is always passed in as a constant (either True or False), so we can specialize the function for the two cases. (This is actually needed for technical reasons: the variable 'lower' must contain a known method, which is the case in each specialized version but not in the unspecialized one.) Modified: pypy/dist/pypy/objspace/std/listsort.py ============================================================================== --- pypy/dist/pypy/objspace/std/listsort.py (original) +++ pypy/dist/pypy/objspace/std/listsort.py Tue Jul 12 23:13:32 2005 @@ -185,6 +185,13 @@ assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] return ofs + # hint for the annotator: the argument 'rightmost' is always passed in as + # a constant (either True or False), so we can specialize the function for + # the two cases. (This is actually needed for technical reasons: the + # variable 'lower' must contain a known method, which is the case in each + # specialized version but not in the unspecialized one.) + gallop._annspecialcase_ = "specialize:arg4" + # ____________________________________________________________ # When we get into galloping mode, we stay there until both runs win less From arigo at codespeak.net Tue Jul 12 23:14:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 23:14:13 +0200 (CEST) Subject: [pypy-svn] r14592 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050712211413.1B61727B4E@code1.codespeak.net> Author: arigo Date: Tue Jul 12 23:14:11 2005 New Revision: 14592 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py Log: Merge of rev 14590 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py Tue Jul 12 23:14:11 2005 @@ -185,6 +185,13 @@ assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] return ofs + # hint for the annotator: the argument 'rightmost' is always passed in as + # a constant (either True or False), so we can specialize the function for + # the two cases. (This is actually needed for technical reasons: the + # variable 'lower' must contain a known method, which is the case in each + # specialized version but not in the unspecialized one.) + gallop._annspecialcase_ = "specialize:arg4" + # ____________________________________________________________ # When we get into galloping mode, we stay there until both runs win less From arigo at codespeak.net Tue Jul 12 23:18:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Jul 2005 23:18:05 +0200 (CEST) Subject: [pypy-svn] r14594 - pypy/dist/pypy/annotation Message-ID: <20050712211805.4AF3527B4E@code1.codespeak.net> Author: arigo Date: Tue Jul 12 23:18:02 2005 New Revision: 14594 Modified: pypy/dist/pypy/annotation/policy.py Log: Oups, forgot this. Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Tue Jul 12 23:18:02 2005 @@ -76,6 +76,14 @@ specialize__argtype0 = staticmethod(argtype(0)) specialize__arg1 = staticmethod(argvalue(1)) specialize__argtype1 = staticmethod(argtype(1)) + specialize__arg2 = staticmethod(argvalue(2)) + specialize__argtype2 = staticmethod(argtype(2)) + specialize__arg3 = staticmethod(argvalue(3)) + specialize__argtype3 = staticmethod(argtype(3)) + specialize__arg4 = staticmethod(argvalue(4)) + specialize__argtype4 = staticmethod(argtype(4)) + specialize__arg5 = staticmethod(argvalue(5)) + specialize__argtype5 = staticmethod(argtype(5)) def override__ignore(pol, *args): bk = getbookkeeper() From arigo at codespeak.net Wed Jul 13 00:20:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 00:20:19 +0200 (CEST) Subject: [pypy-svn] r14598 - in pypy/dist/pypy: annotation interpreter objspace/std Message-ID: <20050712222019.4DB2727B52@code1.codespeak.net> Author: arigo Date: Wed Jul 13 00:20:13 2005 New Revision: 14598 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/interpreter/pycode.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/listsort.py pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/objspace/std/typeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: Minor annotator hints to help it figure out which numbers are non-negative. This is needed for slicing in the rtyper. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Jul 13 00:20:13 2005 @@ -230,7 +230,7 @@ def lshift((int1, int2)): if int1.unsigned: return SomeInteger(unsigned=True) - return SomeInteger() + return SomeInteger(nonneg = int1.nonneg) lshift.can_only_throw = [ValueError] rshift = lshift lshift_ovf = _clone(lshift, [ValueError, OverflowError]) @@ -238,7 +238,7 @@ def pow((int1, int2), obj3): if int1.unsigned or int2.unsigned or getattr(obj3, 'unsigned', False): return SomeInteger(unsigned=True) - return SomeInteger() + return SomeInteger(nonneg = int1.nonneg) pow.can_only_throw = [ZeroDivisionError] pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError]) Modified: pypy/dist/pypy/interpreter/pycode.py ============================================================================== --- pypy/dist/pypy/interpreter/pycode.py (original) +++ pypy/dist/pypy/interpreter/pycode.py Wed Jul 13 00:20:13 2005 @@ -31,6 +31,7 @@ def cpython_code_signature(code): "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)." argcount = code.co_argcount + assert argcount >= 0 # annotator hint argnames = list(code.co_varnames[:argcount]) if code.co_flags & CO_VARARGS: varargname = code.co_varnames[argcount] Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Wed Jul 13 00:20:13 2005 @@ -314,8 +314,8 @@ if step == 1: # Support list resizing for non-extended slices oldsize = w_list.ob_size delta = len2 - slicelength - newsize = oldsize + delta if delta >= 0: + newsize = oldsize + delta _list_resize(w_list, newsize) w_list.ob_size = newsize items = w_list.ob_item Modified: pypy/dist/pypy/objspace/std/listsort.py ============================================================================== --- pypy/dist/pypy/objspace/std/listsort.py (original) +++ pypy/dist/pypy/objspace/std/listsort.py Wed Jul 13 00:20:13 2005 @@ -183,6 +183,7 @@ ofs = m # key <= a[m] assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] + assert ofs >= 0 # annotator hint return ofs # hint for the annotator: the argument 'rightmost' is always passed in as @@ -553,6 +554,8 @@ "A sublist of a list." def __init__(self, list, base, len): + assert base >= 0 + assert len >= 0 self.list = list self.base = base self.len = len @@ -563,17 +566,23 @@ def advance(self, n): self.base += n - self.len -= n + len = self.len - n + assert len >= 0 # annotator hint, don't remove + self.len = len def popleft(self): result = self.list[self.base] self.base += 1 - self.len -= 1 + len = self.len - 1 + assert len >= 0 # annotator hint, don't remove + self.len = len return result def popright(self): - self.len -= 1 - return self.list[self.base + self.len] + len = self.len - 1 + assert len >= 0 # annotator hint, don't remove + self.len = len + return self.list[self.base + len] def reverse(self): "Reverse the slice in-place." Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 13 00:20:13 2005 @@ -74,7 +74,9 @@ def longval(self): #YYYYYY l = 0 - for d in self.digits[::-1]: + digits = list(self.digits) + digits.reverse() + for d in digits: l = l << SHIFT l += long(d) return l * self.sign Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Wed Jul 13 00:20:13 2005 @@ -599,6 +599,7 @@ while rpos > lpos and u_self[rpos - 1] in u_chars: rpos -= 1 + assert rpos >= lpos # annotator hint, don't remove return space.wrap(u_self[lpos:rpos]) def _strip_none(space, w_self, left, right): @@ -617,6 +618,7 @@ while rpos > lpos and _isspace(u_self[rpos - 1]): rpos -= 1 + assert rpos >= lpos # annotator hint, don't remove return space.wrap(u_self[lpos:rpos]) def str_strip__String_String(space, w_self, w_chars): Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Wed Jul 13 00:20:13 2005 @@ -15,6 +15,7 @@ p += 1 while p < q and s[q-1] in ' \f\n\r\t\v': q -= 1 + assert q >= p # annotator hint, don't remove return s[p:q] class ParseStringError(Exception): Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Wed Jul 13 00:20:13 2005 @@ -29,7 +29,11 @@ tlen = len(klass) + len(name) if tlen > MANGLE_LEN: - klass = klass[:MANGLE_LEN-tlen] + end = len(klass) + MANGLE_LEN-tlen + if end < 0: + klass = '' # annotator hint + else: + klass = klass[:end] return "_%s%s" % (klass, name) Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Wed Jul 13 00:20:13 2005 @@ -232,7 +232,11 @@ uni = w_uni._value length = len(uni) start, stop, step, sl = slicetype.indices4(space, w_slice, length) - return W_UnicodeObject(space, uni[start:stop]) + if start > stop: + return W_UnicodeObject(space, []) + else: + assert 0 <= start <= stop + return W_UnicodeObject(space, uni[start:stop]) def mul__Unicode_ANY(space, w_uni, w_times): chars = w_uni._value From arigo at codespeak.net Wed Jul 13 00:20:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 00:20:57 +0200 (CEST) Subject: [pypy-svn] r14599 - in pypy/branch/pypy-translation-snapshot: interpreter objspace/std Message-ID: <20050712222057.C2D3F27B52@code1.codespeak.net> Author: arigo Date: Wed Jul 13 00:20:53 2005 New Revision: 14599 Modified: pypy/branch/pypy-translation-snapshot/interpreter/pycode.py pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py pypy/branch/pypy-translation-snapshot/objspace/std/typeobject.py pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py Log: Merged rev 14598 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/interpreter/pycode.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pycode.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pycode.py Wed Jul 13 00:20:53 2005 @@ -31,6 +31,7 @@ def cpython_code_signature(code): "([list-of-arg-names], vararg-name-or-None, kwarg-name-or-None)." argcount = code.co_argcount + assert argcount >= 0 # annotator hint argnames = list(code.co_varnames[:argcount]) if code.co_flags & CO_VARARGS: varargname = code.co_varnames[argcount] Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Wed Jul 13 00:20:53 2005 @@ -314,8 +314,8 @@ if step == 1: # Support list resizing for non-extended slices oldsize = w_list.ob_size delta = len2 - slicelength - newsize = oldsize + delta if delta >= 0: + newsize = oldsize + delta _list_resize(w_list, newsize) w_list.ob_size = newsize items = w_list.ob_item Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py Wed Jul 13 00:20:53 2005 @@ -183,6 +183,7 @@ ofs = m # key <= a[m] assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] + assert ofs >= 0 # annotator hint return ofs # hint for the annotator: the argument 'rightmost' is always passed in as @@ -553,6 +554,8 @@ "A sublist of a list." def __init__(self, list, base, len): + assert base >= 0 + assert len >= 0 self.list = list self.base = base self.len = len @@ -563,17 +566,23 @@ def advance(self, n): self.base += n - self.len -= n + len = self.len - n + assert len >= 0 # annotator hint, don't remove + self.len = len def popleft(self): result = self.list[self.base] self.base += 1 - self.len -= 1 + len = self.len - 1 + assert len >= 0 # annotator hint, don't remove + self.len = len return result def popright(self): - self.len -= 1 - return self.list[self.base + self.len] + len = self.len - 1 + assert len >= 0 # annotator hint, don't remove + self.len = len + return self.list[self.base + len] def reverse(self): "Reverse the slice in-place." Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Wed Jul 13 00:20:53 2005 @@ -34,7 +34,9 @@ def longval(self): #YYYYYY l = 0 - for d in self.digits[::-1]: + digits = list(self.digits) + digits.reverse() + for d in digits: l = l << LONG_BIT l += long(d) return l * self.sign Modified: pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py Wed Jul 13 00:20:53 2005 @@ -535,6 +535,7 @@ while rpos > lpos and u_self[rpos - 1] in u_chars: rpos -= 1 + assert rpos >= lpos # annotator hint, don't remove return space.wrap(u_self[lpos:rpos]) def _strip_none(space, w_self, left, right): @@ -553,6 +554,7 @@ while rpos > lpos and _isspace(u_self[rpos - 1]): rpos -= 1 + assert rpos >= lpos # annotator hint, don't remove return space.wrap(u_self[lpos:rpos]) def str_strip__String_String(space, w_self, w_chars): Modified: pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py Wed Jul 13 00:20:53 2005 @@ -15,6 +15,7 @@ p += 1 while p < q and s[q-1] in ' \f\n\r\t\v': q -= 1 + assert q >= p # annotator hint, don't remove return s[p:q] class ParseStringError(Exception): Modified: pypy/branch/pypy-translation-snapshot/objspace/std/typeobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/typeobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/typeobject.py Wed Jul 13 00:20:53 2005 @@ -29,7 +29,11 @@ tlen = len(klass) + len(name) if tlen > MANGLE_LEN: - klass = klass[:MANGLE_LEN-tlen] + end = len(klass) + MANGLE_LEN-tlen + if end < 0: + klass = '' # annotator hint + else: + klass = klass[:end] return "_%s%s" % (klass, name) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py Wed Jul 13 00:20:53 2005 @@ -231,7 +231,11 @@ uni = w_uni._value length = len(uni) start, stop, step, sl = slicetype.indices4(space, w_slice, length) - return W_UnicodeObject(space, uni[start:stop]) + if start > stop: + return W_UnicodeObject(space, []) + else: + assert 0 <= start <= stop + return W_UnicodeObject(space, uni[start:stop]) def mul__Unicode_ANY(space, w_uni, w_times): chars = w_uni._value From arigo at codespeak.net Wed Jul 13 01:02:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:02:37 +0200 (CEST) Subject: [pypy-svn] r14600 - in pypy/dist/pypy: objspace/std translator translator/test Message-ID: <20050712230237.180B427B53@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:02:33 2005 New Revision: 14600 Modified: pypy/dist/pypy/objspace/std/listsort.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/test/test_annrpython.py Log: Preserve a meaningful knowntypedata across links, by renaming the variables. Gave up on nonneg in listsort.py, and added an explicit assert just before the slicing. Modified: pypy/dist/pypy/objspace/std/listsort.py ============================================================================== --- pypy/dist/pypy/objspace/std/listsort.py (original) +++ pypy/dist/pypy/objspace/std/listsort.py Wed Jul 13 01:02:33 2005 @@ -183,7 +183,6 @@ ofs = m # key <= a[m] assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] - assert ofs >= 0 # annotator hint return ofs # hint for the annotator: the argument 'rightmost' is always passed in as @@ -554,35 +553,30 @@ "A sublist of a list." def __init__(self, list, base, len): - assert base >= 0 - assert len >= 0 self.list = list self.base = base self.len = len def copyitems(self): "Make a copy of the slice of the original list." - return ListSlice(self.list[self.base:self.base+self.len], 0, self.len) + start = self.base + stop = self.base + self.len + assert 0 <= start <= stop # annotator hint + return ListSlice(self.list[start:stop], 0, self.len) def advance(self, n): self.base += n - len = self.len - n - assert len >= 0 # annotator hint, don't remove - self.len = len + self.len -= n def popleft(self): result = self.list[self.base] self.base += 1 - len = self.len - 1 - assert len >= 0 # annotator hint, don't remove - self.len = len + self.len -= 1 return result def popright(self): - len = self.len - 1 - assert len >= 0 # annotator hint, don't remove - self.len = len - return self.list[self.base + len] + self.len -= 1 + return self.list[self.base + self.len] def reverse(self): "Reverse the slice in-place." Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Wed Jul 13 01:02:33 2005 @@ -532,6 +532,20 @@ newcell.const = cell.const cell = newcell cell.is_type_of = renamed_is_type_of + + if hasattr(cell, 'knowntypedata'): + renamed_knowntypedata = {} + for (value, v), s in cell.knowntypedata.items(): + new_vs = renaming.get(v, []) + for new_v in new_vs: + renamed_knowntypedata[value, new_v] = s + assert isinstance(cell, annmodel.SomeBool) + newcell = annmodel.SomeBool() + if cell.is_constant(): + newcell.const = cell.const + cell = newcell + cell.knowntypedata = renamed_knowntypedata + cells.append(cell) if in_except_block: Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jul 13 01:02:33 2005 @@ -1264,6 +1264,14 @@ s = a.build_types(f, [int]*8) assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8) + def test_more_nonneg_cleverness(self): + def f(start, stop): + assert 0 <= start <= stop + return start, stop + a = self.RPythonAnnotator() + s = a.build_types(f, [int, int]) + assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 2) + def test_attr_moving_into_parent(self): class A: pass class B(A): pass From arigo at codespeak.net Wed Jul 13 01:03:02 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:03:02 +0200 (CEST) Subject: [pypy-svn] r14601 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050712230302.CAEC927B53@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:03:02 2005 New Revision: 14601 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py Log: Merge trunk rev 14600. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listsort.py Wed Jul 13 01:03:02 2005 @@ -183,7 +183,6 @@ ofs = m # key <= a[m] assert lastofs == ofs # so a[ofs-1] < key <= a[ofs] - assert ofs >= 0 # annotator hint return ofs # hint for the annotator: the argument 'rightmost' is always passed in as @@ -554,35 +553,30 @@ "A sublist of a list." def __init__(self, list, base, len): - assert base >= 0 - assert len >= 0 self.list = list self.base = base self.len = len def copyitems(self): "Make a copy of the slice of the original list." - return ListSlice(self.list[self.base:self.base+self.len], 0, self.len) + start = self.base + stop = self.base + self.len + assert 0 <= start <= stop # annotator hint + return ListSlice(self.list[start:stop], 0, self.len) def advance(self, n): self.base += n - len = self.len - n - assert len >= 0 # annotator hint, don't remove - self.len = len + self.len -= n def popleft(self): result = self.list[self.base] self.base += 1 - len = self.len - 1 - assert len >= 0 # annotator hint, don't remove - self.len = len + self.len -= 1 return result def popright(self): - len = self.len - 1 - assert len >= 0 # annotator hint, don't remove - self.len = len - return self.list[self.base + len] + self.len -= 1 + return self.list[self.base + self.len] def reverse(self): "Reverse the slice in-place." From arigo at codespeak.net Wed Jul 13 01:08:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:08:57 +0200 (CEST) Subject: [pypy-svn] r14602 - pypy/dist/pypy/objspace/std Message-ID: <20050712230857.BC1C827B53@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:08:55 2005 New Revision: 14602 Modified: pypy/dist/pypy/objspace/std/listobject.py Log: More efforts to make w_list.ob_size known to be non-negative. Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Wed Jul 13 01:08:55 2005 @@ -271,7 +271,9 @@ items[j-slicelength] = items[j] j += 1 # make sure entries after ob_size are None, to avoid keeping references - w_list.ob_size -= slicelength + n -= slicelength + assert n >= 0 # annotator hint + w_list.ob_size = n for i in range(w_list.ob_size, n): items[i] = None # now we can destruct recycle safely, regardless of @@ -465,26 +467,29 @@ def _del_slice(w_list, ilow, ihigh): """ similar to the deletion part of list_ass_slice in CPython """ + n = w_list.ob_size if ilow < 0: ilow = 0 - elif ilow > w_list.ob_size: - ilow = w_list.ob_size + elif ilow > n: + ilow = n if ihigh < ilow: ihigh = ilow - elif ihigh > w_list.ob_size: - ihigh = w_list.ob_size + elif ihigh > n: + ihigh = n items = w_list.ob_item d = ihigh-ilow # keep a reference to the objects to be removed, # preventing side effects during destruction recycle = [items[i] for i in range(ilow, ihigh)] - for i in range(ilow, w_list.ob_size - d): + for i in range(ilow, n - d): items[i] = items[i+d] items[i+d] = None # make sure entries after ob_size-d are None, to avoid keeping references # (the above loop already set to None all items[ilow+d:old_style]) - w_list.ob_size -= d - for i in range(w_list.ob_size, ilow + d): + n -= d + assert n >= 0 # annotator hint + w_list.ob_size = n + for i in range(n, ilow + d): items[i] = None # now we can destruct recycle safely, regardless of # side-effects to the list From arigo at codespeak.net Wed Jul 13 01:09:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:09:27 +0200 (CEST) Subject: [pypy-svn] r14603 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050712230927.36ABB27B53@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:09:26 2005 New Revision: 14603 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Log: Merge rev 14602 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Wed Jul 13 01:09:26 2005 @@ -271,7 +271,9 @@ items[j-slicelength] = items[j] j += 1 # make sure entries after ob_size are None, to avoid keeping references - w_list.ob_size -= slicelength + n -= slicelength + assert n >= 0 # annotator hint + w_list.ob_size = n for i in range(w_list.ob_size, n): items[i] = None # now we can destruct recycle safely, regardless of @@ -465,26 +467,29 @@ def _del_slice(w_list, ilow, ihigh): """ similar to the deletion part of list_ass_slice in CPython """ + n = w_list.ob_size if ilow < 0: ilow = 0 - elif ilow > w_list.ob_size: - ilow = w_list.ob_size + elif ilow > n: + ilow = n if ihigh < ilow: ihigh = ilow - elif ihigh > w_list.ob_size: - ihigh = w_list.ob_size + elif ihigh > n: + ihigh = n items = w_list.ob_item d = ihigh-ilow # keep a reference to the objects to be removed, # preventing side effects during destruction recycle = [items[i] for i in range(ilow, ihigh)] - for i in range(ilow, w_list.ob_size - d): + for i in range(ilow, n - d): items[i] = items[i+d] items[i+d] = None # make sure entries after ob_size-d are None, to avoid keeping references # (the above loop already set to None all items[ilow+d:old_style]) - w_list.ob_size -= d - for i in range(w_list.ob_size, ilow + d): + n -= d + assert n >= 0 # annotator hint + w_list.ob_size = n + for i in range(n, ilow + d): items[i] = None # now we can destruct recycle safely, regardless of # side-effects to the list From arigo at codespeak.net Wed Jul 13 01:30:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:30:13 +0200 (CEST) Subject: [pypy-svn] r14604 - pypy/dist/pypy/translator/goal Message-ID: <20050712233013.614CE27B53@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:30:09 2005 New Revision: 14604 Added: pypy/dist/pypy/translator/goal/ISSUES.txt (contents, props changed) Log: Adding a text file to log the known issues of running translate_pypy.py. It's useful to track them because we have seen most of them in the past; then they go away because it crashes somewhere else first, and some time later they show up again. Added: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Wed Jul 13 01:30:09 2005 @@ -0,0 +1,20 @@ +Known RTyper issues +------------------- + +Let's list and update here the issues that will show up, or have shown up +already sometime ago, while running translate_pypy:: + + * we need slicing of the form [:-1]. + + * the PBCReprs generally lack a convert_from_to() to convert from a small PBC + set to a larger one. + + * 'call_args' needs to be implemented in rpbc.py. + + * how to implement the three overrides of translator/ann_override.py ? + + * we get tons of warnings about attributes like 'co_code' that seem to be + erroneously attached to the base 'Code' class, instead of staying on + 'PyCode'. + + * the pypy trunk is still not annotable. From arigo at codespeak.net Wed Jul 13 01:58:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 01:58:25 +0200 (CEST) Subject: [pypy-svn] r14605 - in pypy/dist/pypy: rpython rpython/test translator/goal Message-ID: <20050712235825.65D0327B51@code1.codespeak.net> Author: arigo Date: Wed Jul 13 01:58:21 2005 New Revision: 14605 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rslice.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: Support for [:-1] in getitem for lists. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Wed Jul 13 01:58:21 2005 @@ -5,6 +5,7 @@ from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.rslice import minusone_slice_repr from pypy.rpython.rclass import InstanceRepr from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive @@ -205,6 +206,9 @@ if r_slic == startstop_slice_repr: v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr) return hop.gendirectcall(ll_listslice, v_lst, v_slice) + if r_slic == minusone_slice_repr: + v_lst, v_ignored = hop.inputargs(r_lst, minusone_slice_repr) + return hop.gendirectcall(ll_listslice_minusone, v_lst) raise TyperError(r_slic) def rtype_delitem((r_lst, r_slic), hop): @@ -445,6 +449,18 @@ l.items = newitems return l +def ll_listslice_minusone(l1): + newlen = len(l1.items) - 1 + assert newlen >= 0 + newitems = malloc(typeOf(l1).TO.items.TO, newlen) + j = 0 + while j < newlen: + newitems[j] = l1.items[j] + j += 1 + l = malloc(typeOf(l1).TO) + l.items = newitems + return l + def ll_listdelslice_startonly(l1, start): newitems = malloc(typeOf(l1).TO.items.TO, start) j = 0 Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Wed Jul 13 01:58:21 2005 @@ -25,6 +25,9 @@ def rtyper_makerepr(self, rtyper): if not self.step.is_constant() or self.step.const not in (None, 1): raise TyperError("only supports slices with step 1") + if (self.start.is_constant() and self.start.const in (None, 0) and + self.stop.is_constant() and self.stop.const == -1): + return minusone_slice_repr # [:-1] if isinstance(self.start, annmodel.SomeInteger): if not self.start.nonneg: raise TyperError("slice start must be proved non-negative") @@ -36,7 +39,9 @@ else: return startstop_slice_repr def rtyper_makekey(self): - return self.stop.rtyper_makekey(), self.step.rtyper_makekey() + return (self.start.rtyper_makekey(), + self.stop.rtyper_makekey(), + self.step.rtyper_makekey()) class SliceRepr(Repr): @@ -46,6 +51,8 @@ startstop_slice_repr.lowleveltype = Ptr(SLICE) startonly_slice_repr = SliceRepr() startonly_slice_repr.lowleveltype = Signed +minusone_slice_repr = SliceRepr() +minusone_slice_repr.lowleveltype = Void # only for [:-1] # ____________________________________________________________ @@ -66,6 +73,10 @@ assert isinstance(v_step, Constant) and v_step.value in (None, 1) if isinstance(v_start, Constant) and v_start.value is None: v_start = hop.inputconst(Signed, 0) + if (isinstance(v_start, Constant) and v_start.value == 0 and + isinstance(v_stop, Constant) and v_stop.value == -1): + # [:-1] slice + return hop.inputconst(Void, slice(None,-1)) if isinstance(v_stop, Constant) and v_stop.value is None: # start-only slice # NB. cannot just return v_start in case it is a constant 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 Jul 13 01:58:21 2005 @@ -332,3 +332,11 @@ assert res == 0 res = interpret(fn, [2]) assert res == 1 + +def test_list_slice_minusone(): + def fn(i): + lst = [i, i+1, i+2] + lst2 = lst[:-1] + return lst[-1] * lst2[-1] + res = interpret(fn, [5]) + assert res == 42 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Wed Jul 13 01:58:21 2005 @@ -4,8 +4,6 @@ Let's list and update here the issues that will show up, or have shown up already sometime ago, while running translate_pypy:: - * we need slicing of the form [:-1]. - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From arigo at codespeak.net Wed Jul 13 02:06:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Jul 2005 02:06:39 +0200 (CEST) Subject: [pypy-svn] r14606 - in pypy/dist/pypy/rpython: . test Message-ID: <20050713000639.7454C27B5C@code1.codespeak.net> Author: arigo Date: Wed Jul 13 02:06:36 2005 New Revision: 14606 Modified: pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: Iteration over tuples of length 1 (!). This is needed by os.path.join()... Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Wed Jul 13 02:06:36 2005 @@ -4,6 +4,7 @@ from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed, malloc +from pypy.rpython.lltype import typeOf, nullptr # ____________________________________________________________ # @@ -64,6 +65,11 @@ hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem) return vlist + def make_iterator_repr(self): + if len(self.items_r) == 1: + return Length1TupleIteratorRepr(self) + raise TyperError("can only iterate over tuples of length 1 for now") + class __extend__(pairtype(TupleRepr, Repr)): def rtype_contains((r_tup, r_item), hop): v_tup = hop.args_v[0] @@ -155,3 +161,37 @@ llops.gencapicall('PyTuple_SetItem_WithIncref', [v_result, ci, v_converted]) return v_result + +# ____________________________________________________________ +# +# Iteration. + +class Length1TupleIteratorRepr(Repr): + + def __init__(self, r_tuple): + self.r_tuple = r_tuple + self.lowleveltype = Ptr(GcStruct('tuple1iter', + ('tuple', r_tuple.lowleveltype))) + + def newiter(self, hop): + v_tuple, = hop.inputargs(self.r_tuple) + citerptr = hop.inputconst(Void, self.lowleveltype) + return hop.gendirectcall(ll_tupleiter, citerptr, v_tuple) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + return hop.gendirectcall(ll_tuplenext, v_iter) + +def ll_tupleiter(ITERPTR, tuple): + iter = malloc(ITERPTR.TO) + iter.tuple = tuple + return iter + +def ll_tuplenext(iter): + # for iterating over length 1 tuples only! + t = iter.tuple + if t: + iter.tuple = nullptr(typeOf(t).TO) + return t.item0 + else: + raise StopIteration 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 Jul 13 02:06:36 2005 @@ -77,3 +77,12 @@ assert res is True res = interpret(f, [0]) assert res is False + +def test_tuple_iterator_length1(): + def f(i): + total = 0 + for x in (i,): + total += x + return total + res = interpret(f, [93813]) + assert res == 93813 From pedronis at codespeak.net Wed Jul 13 02:15:04 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 02:15:04 +0200 (CEST) Subject: [pypy-svn] r14607 - pypy/dist/pypy/rpython Message-ID: <20050713001504.BACD927B5C@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 02:15:03 2005 New Revision: 14607 Modified: pypy/dist/pypy/rpython/rpbc.py Log: fix check. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 13 02:15:03 2005 @@ -387,7 +387,7 @@ f, rinputs, rresult = self.function_signatures().itervalues().next() # the function arguments may have been normalized by normalizecalls() # already - if not f._obj.graph.normalized_for_calls: + if not getattr(f._obj.graph, 'normalized_for_calls', False): assert False, "XXX do stuff here" vlist = hop.inputargs(self, Void, *rinputs) return hop.genop('direct_call', vlist[:1] + vlist[2:], From pedronis at codespeak.net Wed Jul 13 02:15:49 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 02:15:49 +0200 (CEST) Subject: [pypy-svn] r14608 - in pypy/dist/pypy/rpython: . test Message-ID: <20050713001549.D854227B5C@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 02:15:48 2005 New Revision: 14608 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: [:-1] slicing for strings, plus fixes about proper char -> str conversion before slicing Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jul 13 02:15:48 2005 @@ -9,6 +9,7 @@ from pypy.rpython import rint from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.rslice import minusone_slice_repr from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf from pypy.rpython.rclass import InstanceRepr @@ -187,13 +188,16 @@ class __extend__(pairtype(StringRepr, SliceRepr)): - def rtype_getitem((r_str, r_slic), hop): + def rtype_getitem((_, r_slic), hop): if r_slic == startonly_slice_repr: - v_str, v_start = hop.inputargs(r_str, startonly_slice_repr) + v_str, v_start = hop.inputargs(string_repr, startonly_slice_repr) return hop.gendirectcall(ll_stringslice_startonly, v_str, v_start) if r_slic == startstop_slice_repr: - v_str, v_slice = hop.inputargs(r_str, startstop_slice_repr) + v_str, v_slice = hop.inputargs(string_repr, startstop_slice_repr) return hop.gendirectcall(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) raise TyperError(r_slic) @@ -761,6 +765,16 @@ 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(LISTPTR, s, c): chars = s.chars strlen = len(chars) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Wed Jul 13 02:15:48 2005 @@ -281,6 +281,15 @@ 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 hpk at codespeak.net Wed Jul 13 12:09:25 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 13 Jul 2005 12:09:25 +0200 (CEST) Subject: [pypy-svn] r14612 - pypy/dist/pypy/documentation/website Message-ID: <20050713100925.50E2D27B5D@code1.codespeak.net> Author: hpk Date: Wed Jul 13 12:09:24 2005 New Revision: 14612 Modified: pypy/dist/pypy/documentation/website/news.txt Log: update the news-page to reflect the fact that the EP sprints have finished, actually. Still no full report :-( Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Wed Jul 13 12:09:24 2005 @@ -9,18 +9,25 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: ../architecture.html#mission-statement -Next Sprint after EuroPython 2005 1st-7th July +EuroPython 2005 sprints finished ====================================================== -The next sprint is scheduled right after EuroPython_ 2005 in -G?teborg, Sweden. We take a day of break after the conference -and start sprinting from 1st-7th of July 2005. See the -`sprint announcement`_ and the `list of people coming`_. The -sprint theme is related strongly to `translation`_ and working -towards getting a first self-contained PyPy version. -Additionally there will be a four day Pre-EuroPython sprint -for people who already are familiar with the PyPy code base. -*(05/04/2005, 12/06/2005, 22/06/2005)* +We had two sprints around EuroPython, one more internal core +developer one and a public one. Both sprints were quite +successful. Regarding the Pre-EuroPython sprint Michael Hudson +has posted summaries of `day 1`_, `day 2`_ and `day 3`_ on +the `pypy-dev`_ mailing list. The larger public sprint +has not been summarized yet but it went very well. We had +20 people initially attending to hear the tutorials and +work a bit. Later with around 13-14 people we made the +move to Python-2.4.1, integrated the parser, improved +the LLVM backends and type inference in general. +*(07/13/2005)* + +.. _`day 1`: http://codespeak.net/pipermail/pypy-dev/2005q2/002169.html +.. _`day 2`: http://codespeak.net/pipermail/pypy-dev/2005q2/002171.html +.. _`day 3`: http://codespeak.net/pipermail/pypy-dev/2005q2/002172.html +.. _`pypy-dev`: http://codespeak.net/mailman/listinfo/pypy-dev .. _EuroPython: http://europython.org .. _`translation`: ../translation.html From ac at codespeak.net Wed Jul 13 13:51:34 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 13 Jul 2005 13:51:34 +0200 (CEST) Subject: [pypy-svn] r14616 - pypy/dist/pypy/rpython Message-ID: <20050713115134.6E44327B5E@code1.codespeak.net> Author: ac Date: Wed Jul 13 13:51:33 2005 New Revision: 14616 Modified: pypy/dist/pypy/rpython/rrange.py Log: Add missing import Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Wed Jul 13 13:51:33 2005 @@ -2,6 +2,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void +from pypy.objspace.flow.model import Constant # ____________________________________________________________ # From ac at codespeak.net Wed Jul 13 16:05:11 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 13 Jul 2005 16:05:11 +0200 (CEST) Subject: [pypy-svn] r14617 - pypy/dist/pypy/module/unicodedata Message-ID: <20050713140511.3E72E27B5E@code1.codespeak.net> Author: ac Date: Wed Jul 13 16:05:10 2005 New Revision: 14617 Modified: pypy/dist/pypy/module/unicodedata/function.py Log: Avoid frequent reallocations when normalizing unicode. Modified: pypy/dist/pypy/module/unicodedata/function.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/function.py (original) +++ pypy/dist/pypy/module/unicodedata/function.py Wed Jul 13 16:05:10 2005 @@ -100,6 +100,7 @@ NCount = (VCount*TCount) SCount = (LCount*NCount) + def normalize(space, w_form, w_unistr): form = space.str_w(w_form) if not space.is_true(space.isinstance(w_unistr, space.w_unicode)): @@ -121,7 +122,9 @@ space.wrap('invalid normalization form')) strlen = space.int_w(space.len(w_unistr)) - result = [] + result = [0] * (strlen + strlen / 10 + 10) + j = 0 + resultlen = len(result) # Expand the character for i in range(strlen): ch = space.int_w(space.ord(space.getitem(w_unistr, space.wrap(i)))) @@ -132,33 +135,57 @@ V = VBase + (SIndex % NCount) / TCount; T = TBase + SIndex % TCount; if T == TBase: - result.extend([L, V]) + if j + 2 > resultlen: + result.extend([0 * (j + 2 - resultlen + 10)]) + resultlen = len(result) + result[j] = L + result[j + 1] = V + j += 2 else: - result.extend([L, V, T]) + if j + 3 > resultlen: + result.extend([0 * (j + 3 - resultlen + 10)]) + resultlen = len(result) + result[j] = L + result[j + 1] = V + result[j + 2] = T + j += 3 continue - - result.extend(decomposition.get(ch, [ch])) + decomp = decomposition.get(ch) + if decomp: + decomplen = len(decomp) + if j + decomplen > resultlen: + result.extend([0 * (j + decomplen - resultlen + 10)]) + resultlen = len(result) + for ch in decomp: + result[j] = ch + j += 1 + else: + if j + 1 > resultlen: + result.extend([0 * (j + 1 - resultlen + 10)]) + resultlen = len(result) + result[j] = ch + j += 1 # Sort all combining marks - for i in range(len(result)): + for i in range(j): ch = result[i] comb = unicodedb.combining(ch) if comb == 0: continue - for j in range(i, 0, -1): - if unicodedb.combining(result[j - 1]) <= comb: - result[j] = ch + for k in range(i, 0, -1): + if unicodedb.combining(result[k - 1]) <= comb: + result[k] = ch break - result[j] = result[j - 1] + result[k] = result[k - 1] else: result[0] = ch if not composed: # If decomposed normalization we are done - return space.newunicode(result) + return space.newunicode(result[:j]) - if len(result) <= 1: - return space.newunicode(result) + if j <= 1: + return space.newunicode(result[:j]) current = result[0] starter_pos = 0 @@ -166,8 +193,8 @@ prev_combining = 0 if unicodedb.combining(current): prev_combining = 256 - for j in range(1, len(result)): - next = result[j] + for k in range(1, j): + next = result[k] next_combining = unicodedb.combining(next) if next_insert == starter_pos + 1 or prev_combining < next_combining: # Combine if not blocked From pedronis at codespeak.net Wed Jul 13 16:50:59 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 16:50:59 +0200 (CEST) Subject: [pypy-svn] r14619 - pypy/dist/pypy/objspace/std Message-ID: <20050713145059.B2B7F27B5E@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 16:50:58 2005 New Revision: 14619 Modified: pypy/dist/pypy/objspace/std/fake.py Log: avoid .name to be lifted improperly to BaseWrappable. Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Wed Jul 13 16:50:58 2005 @@ -190,13 +190,13 @@ def __init__(self, space, d): self.name = d.__name__ - def descr_descriptor_get(space, w_descriptor, w_obj, w_cls=None): + def descr_descriptor_get(space, descr, w_obj, w_cls=None): # XXX HAAAAAAAAAAAACK (but possibly a good one) if w_obj == space.w_None and not space.is_true(space.is_(w_cls, space.type(space.w_None))): - #print w_descriptor, w_obj, w_cls - return w_descriptor + #print descr, w_obj, w_cls + return space.wrap(descr) else: - name = space.unwrap(w_descriptor).name + name = descr.name obj = space.unwrap(w_obj) try: val = getattr(obj, name) # this gives a "not RPython" warning @@ -205,8 +205,8 @@ raise return space.wrap(val) - def descr_descriptor_set(space, w_descriptor, w_obj, w_value): - name = space.unwrap(w_descriptor).name + def descr_descriptor_set(space, descr, w_obj, w_value): + name = descr.name obj = space.unwrap(w_obj) val = space.unwrap(w_value) try: @@ -214,19 +214,28 @@ except: wrap_exception(space) - def descr_descriptor_del(space, w_descriptor, w_obj): - name = space.unwrap(w_descriptor).name + def descr_descriptor_del(space, descr, w_obj): + name = descr.name obj = space.unwrap(w_obj) try: delattr(obj, name) except: wrap_exception(space) - typedef = TypeDef("FakeDescriptor", - __get__ = interp2app(descr_descriptor_get), - __set__ = interp2app(descr_descriptor_set), - __delete__ = interp2app(descr_descriptor_del), - ) + +W_FakeDescriptor.typedef = TypeDef( + "FakeDescriptor", + __get__ = interp2app(W_FakeDescriptor.descr_descriptor_get.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root, + baseobjspace.W_Root]), + __set__ = interp2app(W_FakeDescriptor.descr_descriptor_set.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root, baseobjspace.W_Root]), + __delete__ = interp2app(W_FakeDescriptor.descr_descriptor_del.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root]), + ) _fake_type_cache[type(file.softspace)] = W_FakeDescriptor _fake_type_cache[type(type.__dict__['__dict__'])] = W_FakeDescriptor From pedronis at codespeak.net Wed Jul 13 16:52:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 16:52:31 +0200 (CEST) Subject: [pypy-svn] r14620 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050713145231.6873127B5E@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 16:52:29 2005 New Revision: 14620 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Log: merge 14619 from trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/fake.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/fake.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Wed Jul 13 16:52:29 2005 @@ -190,13 +190,13 @@ def __init__(self, space, d): self.name = d.__name__ - def descr_descriptor_get(space, w_descriptor, w_obj, w_cls=None): + def descr_descriptor_get(space, descr, w_obj, w_cls=None): # XXX HAAAAAAAAAAAACK (but possibly a good one) if w_obj == space.w_None and not space.is_true(space.is_(w_cls, space.type(space.w_None))): - #print w_descriptor, w_obj, w_cls - return w_descriptor + #print descr, w_obj, w_cls + return space.wrap(descr) else: - name = space.unwrap(w_descriptor).name + name = descr.name obj = space.unwrap(w_obj) try: val = getattr(obj, name) # this gives a "not RPython" warning @@ -205,8 +205,8 @@ raise return space.wrap(val) - def descr_descriptor_set(space, w_descriptor, w_obj, w_value): - name = space.unwrap(w_descriptor).name + def descr_descriptor_set(space, descr, w_obj, w_value): + name = descr.name obj = space.unwrap(w_obj) val = space.unwrap(w_value) try: @@ -214,19 +214,28 @@ except: wrap_exception(space) - def descr_descriptor_del(space, w_descriptor, w_obj): - name = space.unwrap(w_descriptor).name + def descr_descriptor_del(space, descr, w_obj): + name = descr.name obj = space.unwrap(w_obj) try: delattr(obj, name) except: wrap_exception(space) - typedef = TypeDef("FakeDescriptor", - __get__ = interp2app(descr_descriptor_get), - __set__ = interp2app(descr_descriptor_set), - __delete__ = interp2app(descr_descriptor_del), - ) + +W_FakeDescriptor.typedef = TypeDef( + "FakeDescriptor", + __get__ = interp2app(W_FakeDescriptor.descr_descriptor_get.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root, + baseobjspace.W_Root]), + __set__ = interp2app(W_FakeDescriptor.descr_descriptor_set.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root, baseobjspace.W_Root]), + __delete__ = interp2app(W_FakeDescriptor.descr_descriptor_del.im_func, + unwrap_spec = [baseobjspace.ObjSpace, W_FakeDescriptor, + baseobjspace.W_Root]), + ) _fake_type_cache[type(file.softspace)] = W_FakeDescriptor _fake_type_cache[type(type.__dict__['__dict__'])] = W_FakeDescriptor From tismer at codespeak.net Wed Jul 13 17:23:32 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 17:23:32 +0200 (CEST) Subject: [pypy-svn] r14621 - pypy/dist/pypy/objspace/std Message-ID: <20050713152332.1E64B27B5E@code1.codespeak.net> Author: tismer Date: Wed Jul 13 17:23:30 2005 New Revision: 14621 Modified: pypy/dist/pypy/objspace/std/floatobject.py Log: reworked source code formatting a little. Added the relevant commentary from the C source. Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Wed Jul 13 17:23:30 2005 @@ -58,7 +58,7 @@ app = gateway.applevel(''' def repr__Float(f): - r = "%.17g"%f + r = "%.17g" % f for c in r: if c not in '-0123456789': return r @@ -66,12 +66,12 @@ return r + '.0' def str__Float(f): - r = "%.12g"%f + r = "%.12g" % f for c in r: if c not in '-0123456789': return r else: - return r + '.0' + return r + '.0' ''', filename=__file__) repr__Float = app.interphook('repr__Float') str__Float = app.interphook('str__Float') @@ -173,7 +173,7 @@ raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float modulo")) try: # this is a hack!!!! must be replaced by a real fmod function - mod = math.fmod(x,y) + mod = math.fmod(x, y) if (mod and ((y < 0.0) != (mod < 0.0))): mod += y except FloatingPointError: @@ -188,23 +188,35 @@ raise FailedToImplement(space.w_ZeroDivisionError, space.wrap("float modulo")) try: # XXX this is a hack!!!! must be replaced by a real fmod function - mod = math.fmod(x,y) - div = (x -mod) / y + mod = math.fmod(x, y) + # fmod is typically exact, so vx-mod is *mathematically* an + # exact multiple of wx. But this is fp arithmetic, and fp + # vx - mod is an approximation; the result is that div may + # not be an exact integral value after the division, although + # it will always be very close to one. + div = (x - mod) / y if (mod): + # ensure the remainder has the same sign as the denominator if ((y < 0.0) != (mod < 0.0)): mod += y div -= 1.0 else: - mod *= mod + # the remainder is zero, and in the presence of signed zeroes + # fmod returns different results across platforms; ensure + # it has the same sign as the denominator; we'd like to do + # "mod = wx * 0.0", but that may get optimized away + mod *= mod # hide "mod = +0" from optimizer if y < 0.0: mod = -mod + # snap quotient to nearest integral value if div: floordiv = math.floor(div) if (div - floordiv > 0.5): floordiv += 1.0 else: - div *= div; - floordiv = div * x / y + # div is zero - get the same sign as the true quotient + div *= div # hide "div = +0" from optimizers + floordiv = div * x / y # zero w/ sign of vx/wx except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) From tismer at codespeak.net Wed Jul 13 17:24:37 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 17:24:37 +0200 (CEST) Subject: [pypy-svn] r14622 - pypy/dist/pypy/objspace/std Message-ID: <20050713152437.743F227B5E@code1.codespeak.net> Author: tismer Date: Wed Jul 13 17:24:36 2005 New Revision: 14622 Modified: pypy/dist/pypy/objspace/std/floattype.py Log: added an overflow check to floattype. Our helpers in strutil.py *should* not raise Overflow, but if they do (and they did until I changed them :-) , then we don't want to crash the interpreter. Modified: pypy/dist/pypy/objspace/std/floattype.py ============================================================================== --- pypy/dist/pypy/objspace/std/floattype.py (original) +++ pypy/dist/pypy/objspace/std/floattype.py Wed Jul 13 17:24:36 2005 @@ -12,6 +12,10 @@ except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) + except OverflowError, e: + # this should not happen, but if it does, catch it! + raise OperationError(space.w_OverflowError, + space.wrap(str(e))) elif space.is_true(space.isinstance(w_value, space.w_unicode)): from unicodeobject import unicode_to_decimal_w strvalue = unicode_to_decimal_w(space, w_value) From tismer at codespeak.net Wed Jul 13 17:30:40 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 17:30:40 +0200 (CEST) Subject: [pypy-svn] r14624 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050713153040.7EE3F27B5E@code1.codespeak.net> Author: tismer Date: Wed Jul 13 17:30:39 2005 New Revision: 14624 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: a few enhancements which I allowed myself to do on the ferry and in Kiel at my parent's (blush) - removed all explicit typing, because this is the beginning of all evil! - upgraded all implementations to the latest C source in CVS. - implemented Karatsuba multiplication - added optimizations for a*a - added optimized pow() - added more comments - a lot of new tests this appears to be almost State of Python Art. XXX still to do at some time: I think we should re-adopt CPython's use of a signed length to store sign and size of the digit array. It is more efficient to carry explicit length than to really have to adjust a list. Also I think the list will get optimized away at some point, and we want an explicit length, anyway. But this isn't urgent. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 13 17:30:39 2005 @@ -3,60 +3,44 @@ from pypy.objspace.std.intobject import W_IntObject from pypy.objspace.std.floatobject import W_FloatObject from pypy.objspace.std.noneobject import W_NoneObject -from pypy.rpython.rarithmetic import intmask, r_uint, r_ushort, r_ulong -from pypy.rpython.rarithmetic import LONG_BIT +from pypy.rpython.rarithmetic import LONG_BIT, LONG_MASK, intmask, r_uint import math -# for now, we use r_uint as a digit. -# we may later switch to r_ushort, when it is supported by rtyper etc. - -Digit = r_uint # already works: r_ushort -Twodigits = r_uint +# after many days of debugging and testing, +# I (chris) finally found out about overflows +# and how to assign the correct types. +# But in the end, this really makes no sense at all. +# Finally I think thatr we should avoid to use anything +# but general integers. r_uint and friends should go away! +# Unsignedness can be completely deduced by back-propagation +# of masking. I will change the annotator to do this. +# remember: not typing at all is much stronger! +# +# my conclusion: +# having no special types at all, but describing everything +# in terms of operations and masks is the stronger way. -# the following describe a plain digit -# XXX at the moment we can't save this bit, -# or we would need a large enough type to hold -# the carry bits in _x_divrem -SHIFT = (Twodigits.BITS // 2) - 1 +SHIFT = (LONG_BIT // 2) - 1 MASK = int((1 << SHIFT) - 1) -# find the correct type for carry/borrow -if Digit.BITS - SHIFT >= 1: - # we have one more bit in Digit - Carryadd = Digit - Stwodigits = int -else: - # we need another Digit - Carryadd = Twodigits - raise ValueError, "need a large enough type for Stwodigits" -Carrymul = Twodigits # Debugging digit array access. # -# 0 == no check at all -# 1 == check correct type -# 2 == check for extra (ab)used bits -CHECK_DIGITS = 2 +# False == no checking at all +# True == check 0 <= value <= MASK + +CHECK_DIGITS = True if CHECK_DIGITS: class DigitArray(list): - if CHECK_DIGITS == 1: - def __setitem__(self, idx, value): - assert type(value) is Digit - list.__setitem__(self, idx, value) - elif CHECK_DIGITS == 2: - def __setitem__(self, idx, value): - assert type(value) is Digit - assert value <= MASK - list.__setitem__(self, idx, value) - else: - raise Exception, 'CHECK_DIGITS == %d not supported' % CHECK_DIGITS + def __setitem__(self, idx, value): + assert value >=0 + assert value <= MASK + list.__setitem__(self, idx, value) else: DigitArray = list -# XXX some operations below return one of their input arguments -# without checking that it's really of type long (and not a subclass). class W_LongObject(W_Object): """This is a reimplementation of longs using a list of digits.""" @@ -87,7 +71,7 @@ def _normalize(self): if len(self.digits) == 0: self.sign = 0 - self.digits = [Digit(0)] + self.digits = [0] return i = len(self.digits) - 1 while i != 0 and self.digits[i] == 0: @@ -99,9 +83,25 @@ registerimplementation(W_LongObject) +USE_KARATSUBA = True # set to False for comparison + +# For long multiplication, use the O(N**2) school algorithm unless +# both operands contain more than KARATSUBA_CUTOFF digits (this +# being an internal Python long digit, in base BASE). + +KARATSUBA_CUTOFF = 70 +KARATSUBA_SQUARE_CUTOFF = 2 * KARATSUBA_CUTOFF + +# For exponentiation, use the binary left-to-right algorithm +# unless the exponent contains more than FIVEARY_CUTOFF digits. +# In that case, do 5 bits at a time. The potential drawback is that +# a table of 2**5 intermediate results is computed. + +FIVEARY_CUTOFF = 8 + # bool-to-long def delegate_Bool2Long(w_bool): - return W_LongObject(w_bool.space, [Digit(w_bool.boolval)], + return W_LongObject(w_bool.space, [w_bool.boolval & MASK], int(w_bool.boolval)) # int-to-long delegation @@ -135,21 +135,21 @@ sign = 1 ival = w_intobj.intval else: - return W_LongObject(space, [Digit(0)], 0) + return W_LongObject(space, [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 # needed. - t = r_uint(ival) + t = ival ndigits = 0 while t: ndigits += 1 t >>= SHIFT - v = W_LongObject(space, [Digit(0)] * ndigits, sign) - t = r_uint(ival) + v = W_LongObject(space, [0] * ndigits, sign) + t = ival p = 0 while t: - v.digits[p] = Digit(t & MASK) + v.digits[p] = t & MASK t >>= SHIFT p += 1 return v @@ -184,16 +184,16 @@ if w_value.sign == -1: raise OperationError(space.w_ValueError, space.wrap( "cannot convert negative integer to unsigned int")) - x = r_uint(0) + x = 0 i = len(w_value.digits) - 1 while i >= 0: prev = x - x = (x << SHIFT) + w_value.digits[i] + x = ((x << SHIFT) + w_value.digits[i]) & LONG_MASK if (x >> SHIFT) != prev: raise OperationError(space.w_OverflowError, space.wrap( "long int too large to convert to unsigned int")) i -= 1 - return x + return r_uint(x) # XXX r_uint should go away def repr__Long(space, w_long): return space.wrap(_format(w_long, 10, True)) @@ -287,7 +287,10 @@ return result def mul__Long_Long(space, w_long1, w_long2): - result = _x_mul(w_long1, w_long2) + if USE_KARATSUBA: + result = _k_mul(w_long1, w_long2) + else: + result = _x_mul(w_long1, w_long2) result.sign = w_long1.sign * w_long2.sign return result @@ -322,9 +325,9 @@ space.w_None) if lz is not None: if lz.sign == 0: - raise OperationError(space.w_ValueError, - space.wrap("pow() 3rd argument cannot be 0")) - result = W_LongObject(space, [Digit(1)], 1) + raise OperationError(space.w_ValueError, space.wrap( + "pow() 3rd argument cannot be 0")) + result = W_LongObject(space, [1], 1) if lw.sign == 0: if lz is not None: result = mod__Long_Long(space, result, lz) @@ -337,7 +340,7 @@ # Treat the most significant digit specially to reduce multiplications while i < len(lw.digits) - 1: j = 0 - m = Digit(1) + m = 1 di = lw.digits[i] while j < SHIFT: if di & m: @@ -349,7 +352,7 @@ m = m << 1 j += 1 i += 1 - m = Digit(1) << (SHIFT - 1) + m = 1 << (SHIFT - 1) highest_set_bit = SHIFT j = SHIFT - 1 di = lw.digits[i] @@ -361,7 +364,7 @@ j -= 1 assert highest_set_bit != SHIFT, "long not normalized" j = 0 - m = Digit(1) + m = 1 while j <= highest_set_bit: if di & m: result = mul__Long_Long(space, result, temp) @@ -375,6 +378,106 @@ result = mod__Long_Long(space, result, lz) return result +def _impl_long_long_pow(space, a, b, c=None): + """ pow(a, b, c) """ + + negativeOutput = False # if x<0 return negative output + + # 5-ary values. If the exponent is large enough, table is + # precomputed so that table[i] == a**i % c for i in range(32). + # python translation: the table is computed when needed. + + if b.sign < 0: # if exponent is negative + if c is not None: + raise OperationError(space.w_TypeError, space.wrap( + "pow() 2nd argument " + "cannot be negative when 3rd argument specified")) + return space.pow(space.newfloat(_AsDouble(a)), + space.newfloat(_AsDouble(b)), + space.w_None) + + if c is not None: + # if modulus == 0: + # raise ValueError() + if c.sign == 0: + raise OperationError(space.w_ValueError, space.wrap( + "pow() 3rd argument cannot be 0")) + + # if modulus < 0: + # negativeOutput = True + # modulus = -modulus + if c.sign < 0: + negativeOutput = True + c = W_LongObject(space, 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) + + # 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 + + # 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) + + # python adaptation: moved macros REDUCE(X) and MULT(X, Y, result) + # into helper function result = _help_mult(x, y, c) + if len(b.digits) <= FIVEARY_CUTOFF: + # Left-to-right binary exponentiation (HAC Algorithm 14.79) + # http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf + i = len(b.digits) - 1 + while i >= 0: + bi = b.digits[i] + j = 1 << (SHIFT-1) + while j != 0: + z = _help_mult(z, z, c) + if bi & j: + z = _help_mult(z, a, c) + j >>= 1 + i -= 1 + else: + # Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) + # z still holds 1L + table = [z] * 32 + table[0] = z; + for i in range(1, 32): + table[i] = _help_mult(table[i-1], a, c) + i = len(b.digits) - 1 + while i >= 0: + bi = b.digits[i] + j = j = SHIFT - 5 + while j >= 0: + index = (bi >> j) & 0x1f + for k in range(5): + z = _help_mult(z, z, c) + if index: + z = _help_mult(z, table[index], c) + j -= 5 + i -= 1 + + if negativeOutput and z.sign != 0: + z = sub__Long_Long(z.space, z, c) + return z + +def _help_mult(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) + # 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 + return res def pow__Long_Long_Long(space, w_long1, w_long2, w_long3): return _impl_long_long_pow(space, w_long1, w_long2, w_long3) @@ -382,6 +485,7 @@ def pow__Long_Long_None(space, w_long1, w_long2, w_long3): return _impl_long_long_pow(space, w_long1, w_long2, None) + def neg__Long(space, w_long1): return W_LongObject(space, w_long1.digits[:], -w_long1.sign) @@ -395,7 +499,7 @@ 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, [Digit(1)], 1)) + w_lpp = add__Long_Long(space, w_long, W_LongObject(space, [1], 1)) return neg__Long(space, w_lpp) def lshift__Long_Long(space, w_long1, w_long2): @@ -419,21 +523,21 @@ newsize = oldsize + wordshift if remshift: newsize += 1 - z = W_LongObject(space, [Digit(0)] * newsize, a.sign) + z = W_LongObject(space, [0] * newsize, a.sign) # not sure if we will initialize things in the future? for i in range(wordshift): - z.digits[i] = Digit(0) - accum = Twodigits(0) + z.digits[i] = 0 + accum = 0 i = wordshift j = 0 while j < oldsize: - accum |= Twodigits(a.digits[j]) << remshift - z.digits[i] = Digit(accum & MASK) + accum |= a.digits[j] << remshift + z.digits[i] = accum & MASK accum >>= SHIFT i += 1 j += 1 if remshift: - z.digits[newsize-1] = Digit(accum) + z.digits[newsize-1] = accum else: assert not accum z._normalize() @@ -459,13 +563,13 @@ wordshift = shiftby // SHIFT newsize = len(a.digits) - wordshift if newsize <= 0: - return W_LongObject(space, [Digit(0)], 0) + return W_LongObject(space, [0], 0) loshift = shiftby % SHIFT hishift = SHIFT - loshift - lomask = (Digit(1) << hishift) - 1 + lomask = (1 << hishift) - 1 himask = MASK ^ lomask - z = W_LongObject(space, [Digit(0)] * newsize, a.sign) + z = W_LongObject(space, [0] * newsize, a.sign) i = 0 j = wordshift while i < newsize: @@ -548,10 +652,10 @@ digits = [] i = 0 while l: - digits.append(Digit(l & MASK)) + digits.append(l & MASK) l = l >> SHIFT if sign == 0: - digits = [Digit(0)] + digits = [0] return digits, sign @@ -564,20 +668,20 @@ if size_a < size_b: a, b = b, a size_a, size_b = size_b, size_a - z = W_LongObject(a.space, [Digit(0)] * (len(a.digits) + 1), 1) + z = W_LongObject(a.space, [0] * (len(a.digits) + 1), 1) i = 0 - carry = Carryadd(0) + carry = 0 while i < size_b: - carry += Carryadd(a.digits[i]) + b.digits[i] - z.digits[i] = Digit(carry & MASK) + carry += a.digits[i] + b.digits[i] + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 while i < size_a: carry += a.digits[i] - z.digits[i] = Digit(carry & MASK) + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 - z.digits[i] = Digit(carry) + z.digits[i] = carry z._normalize() return z @@ -586,7 +690,7 @@ size_a = len(a.digits) size_b = len(b.digits) sign = 1 - borrow = Carryadd(0) + borrow = 0 # Ensure a is the larger of the two: if size_a < size_b: @@ -599,24 +703,24 @@ while i >= 0 and a.digits[i] == b.digits[i]: i -= 1 if i < 0: - return W_LongObject(a.space, [Digit(0)], 0) + return W_LongObject(a.space, [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, [Digit(0)] * size_a, 1) + z = W_LongObject(a.space, [0] * size_a, 1) i = 0 while i < size_b: # The following assumes unsigned arithmetic # works modulo 2**N for some N>SHIFT. - borrow = Carryadd(a.digits[i]) - b.digits[i] - borrow - z.digits[i] = Digit(borrow & MASK) + borrow = a.digits[i] - b.digits[i] - borrow + z.digits[i] = borrow & MASK borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 while i < size_a: borrow = a.digits[i] - borrow - z.digits[i] = Digit(borrow & MASK) + z.digits[i] = borrow & MASK borrow >>= SHIFT borrow &= 1 # Keep only one sign bit i += 1 @@ -627,37 +731,317 @@ return z -#Multiply the absolute values of two longs def _x_mul(a, b): + """ + Grade school multiplication, ignoring the signs. + Returns the absolute value of the product, or NULL if error. + """ + size_a = len(a.digits) size_b = len(b.digits) - z = W_LongObject(a.space, [Digit(0)] * (size_a + size_b), 1) - i = 0 - while i < size_a: - carry = Carrymul(0) - f = Twodigits(a.digits[i]) - j = 0 - while j < size_b: - carry += z.digits[i + j] + b.digits[j] * f - z.digits[i + j] = Digit(carry & MASK) - carry >>= SHIFT - j += 1 - while carry != 0: - assert i + j < size_a + size_b - carry += z.digits[i + j] - z.digits[i + j] = Digit(carry & MASK) + z = W_LongObject(a.space, [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 + # Gives slightly less than a 2x speedup when a == b, + # via exploiting that each entry in the multiplication + # pyramid appears twice (except for the size_a squares). + i = 0 + while i < size_a: + f = a.digits[i] + pz = i << 1 + pa = i + 1 + paend = size_a + + carry = z.digits[pz] + f * f + z.digits[pz] = carry & MASK + pz += 1 carry >>= SHIFT - j += 1 - i += 1 + assert carry <= MASK + + # Now f is added in twice in each column of the + # pyramid it appears. Same as adding f<<1 once. + f <<= 1 + while pa < paend: + carry += z.digits[pz] + a.digits[pa] * f + pa += 1 + z.digits[pz] = carry & MASK + pz += 1 + carry >>= SHIFT + assert carry <= (MASK << 1) + if carry: + carry += z.digits[pz] + z.digits[pz] = carry & MASK + pz += 1 + carry >>= SHIFT + if carry: + z.digits[pz] += carry & MASK + assert (carry >> SHIFT) == 0 + i += 1 + else: + # a is not the same as b -- gradeschool long mult + i = 0 + while i < size_a: + carry = 0 + f = a.digits[i] + pz = i + pb = 0 + pbend = size_b + while pb < pbend: + carry += z.digits[pz] + b.digits[pb] * f + pb += 1 + z.digits[pz] = carry & MASK + pz += 1 + carry >>= SHIFT + assert carry <= MASK + if carry: + z.digits[pz] += carry & MASK + assert (carry >> SHIFT) == 0 + i += 1 z._normalize() return z + +def _kmul_split(n, size): + """ + A helper for Karatsuba multiplication (k_mul). + Takes a long "n" and an integer "size" representing the place to + split, and sets low and high such that abs(n) == (high << size) + low, + viewing the shift as being by digits. The sign bit is ignored, and + the return values are >= 0. + """ + 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._normalize() + hi._normalize() + return hi, lo + +def _k_mul(a, b): + """ + Karatsuba multiplication. Ignores the input signs, and returns the + absolute value of the product (or raises if error). + See Knuth Vol. 2 Chapter 4.3.3 (Pp. 294-295). + """ + asize = len(a.digits) + bsize = len(b.digits) + # (ah*X+al)(bh*X+bl) = ah*bh*X*X + (ah*bl + al*bh)*X + al*bl + # Let k = (ah+al)*(bh+bl) = ah*bl + al*bh + ah*bh + al*bl + # Then the original product is + # ah*bh*X*X + (k - ah*bh - al*bl)*X + al*bl + # By picking X to be a power of 2, "*X" is just shifting, and it's + # been reduced to 3 multiplies on numbers half the size. + + # We want to split based on the larger number; fiddle so that b + # is largest. + if asize > bsize: + a, b, asize, bsize = b, a, bsize, asize + + # Use gradeschool math when either number is too small. + if a == b: + i = KARATSUBA_SQUARE_CUTOFF + else: + i = KARATSUBA_CUTOFF + if asize <= i: + if a.sign == 0: + return W_LongObject(a.space, [0], 0) + else: + return _x_mul(a, b) + + # If a is small compared to b, splitting on b gives a degenerate + # case with ah==0, and Karatsuba may be (even much) less efficient + # than "grade school" then. However, we can still win, by viewing + # b as a string of "big digits", each of width a->ob_size. That + # leads to a sequence of balanced calls to k_mul. + if 2 * asize <= bsize: + return _k_lopsided_mul(a, b) + + # Split a & b into hi & lo pieces. + shift = bsize >> 1 + ah, al = _kmul_split(a, shift) + assert ah.sign == 1 # the split isn't degenerate + + if a == b: + bh = ah + bl = al + else: + bh, bl = _kmul_split(b, shift) + + # The plan: + # 1. Allocate result space (asize + bsize digits: that's always + # enough). + # 2. Compute ah*bh, and copy into result at 2*shift. + # 3. Compute al*bl, and copy into result at 0. Note that this + # can't overlap with #2. + # 4. Subtract al*bl from the result, starting at shift. This may + # underflow (borrow out of the high digit), but we don't care: + # we're effectively doing unsigned arithmetic mod + # BASE**(sizea + sizeb), and so long as the *final* result fits, + # borrows and carries out of the high digit can be ignored. + # 5. Subtract ah*bh from the result, starting at shift. + # 6. Compute (ah+al)*(bh+bl), and add it into the result starting + # at shift. + + # 1. Allocate result space. + ret = W_LongObject(a.space, [0] * (asize + bsize), 1) + + # 2. t1 <- ah*bh, and copy into high digits of result. + t1 = _k_mul(ah, bh) + assert t1.sign >= 0 + assert 2*shift + len(t1.digits) <= len(ret.digits) + ret.digits[2*shift : 2*shift + len(t1.digits)] = t1.digits + + # Zero-out the digits higher than the ah*bh copy. */ + ## ignored, assuming that we initialize to zero + ##i = ret->ob_size - 2*shift - t1->ob_size; + ##if (i) + ## memset(ret->ob_digit + 2*shift + t1->ob_size, 0, + ## i * sizeof(digit)); + + # 3. t2 <- al*bl, and copy into the low digits. + t2 = _k_mul(al, bl) + assert t2.sign >= 0 + assert len(t2.digits) <= 2*shift # no overlap with high digits + ret.digits[:len(t2.digits)] = t2.digits + + # Zero out remaining digits. + ## ignored, assuming that we initialize to zero + ##i = 2*shift - t2->ob_size; /* number of uninitialized digits */ + ##if (i) + ## memset(ret->ob_digit + t2->ob_size, 0, i * sizeof(digit)); + + # 4 & 5. Subtract ah*bh (t1) and al*bl (t2). We do al*bl first + # because it's fresher in cache. + i = len(ret.digits) - shift # # digits after shift + _v_isub(ret.digits, shift, i, t2.digits, len(t2.digits)) + _v_isub(ret.digits, shift, i, t1.digits, len(t1.digits)) + del t1, t2 + + # 6. t3 <- (ah+al)(bh+bl), and add into result. + t1 = _x_add(ah, al) + del ah, al + + if a == b: + t2 = t1 + else: + t2 = _x_add(bh, bl) + del bh, bl + + t3 = _k_mul(t1, t2) + del t1, t2 + assert t3.sign ==1 + + # Add t3. It's not obvious why we can't run out of room here. + # See the (*) comment after this function. + _v_iadd(ret.digits, shift, i, t3.digits, len(t3.digits)) + del t3 + + ret._normalize() + return ret + +""" (*) Why adding t3 can't "run out of room" above. + +Let f(x) mean the floor of x and c(x) mean the ceiling of x. Some facts +to start with: + +1. For any integer i, i = c(i/2) + f(i/2). In particular, + bsize = c(bsize/2) + f(bsize/2). +2. shift = f(bsize/2) +3. asize <= bsize +4. Since we call k_lopsided_mul if asize*2 <= bsize, asize*2 > bsize in this + routine, so asize > bsize/2 >= f(bsize/2) in this routine. + +We allocated asize + bsize result digits, and add t3 into them at an offset +of shift. This leaves asize+bsize-shift allocated digit positions for t3 +to fit into, = (by #1 and #2) asize + f(bsize/2) + c(bsize/2) - f(bsize/2) = +asize + c(bsize/2) available digit positions. + +bh has c(bsize/2) digits, and bl at most f(size/2) digits. So bh+hl has +at most c(bsize/2) digits + 1 bit. + +If asize == bsize, ah has c(bsize/2) digits, else ah has at most f(bsize/2) +digits, and al has at most f(bsize/2) digits in any case. So ah+al has at +most (asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 1 bit. + +The product (ah+al)*(bh+bl) therefore has at most + + c(bsize/2) + (asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 2 bits + +and we have asize + c(bsize/2) available digit positions. We need to show +this is always enough. An instance of c(bsize/2) cancels out in both, so +the question reduces to whether asize digits is enough to hold +(asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 2 bits. If asize < bsize, +then we're asking whether asize digits >= f(bsize/2) digits + 2 bits. By #4, +asize is at least f(bsize/2)+1 digits, so this in turn reduces to whether 1 +digit is enough to hold 2 bits. This is so since SHIFT=15 >= 2. If +asize == bsize, then we're asking whether bsize digits is enough to hold +c(bsize/2) digits + 2 bits, or equivalently (by #1) whether f(bsize/2) digits +is enough to hold 2 bits. This is so if bsize >= 2, which holds because +bsize >= KARATSUBA_CUTOFF >= 2. + +Note that since there's always enough room for (ah+al)*(bh+bl), and that's +clearly >= each of ah*bh and al*bl, there's always enough room to subtract +ah*bh and al*bl too. +""" + +def _k_lopsided_mul(a, b): + """ + b has at least twice the digits of a, and a is big enough that Karatsuba + would pay off *if* the inputs had balanced sizes. View b as a sequence + of slices, each with a->ob_size digits, and multiply the slices by a, + one at a time. This gives k_mul balanced inputs to work with, and is + also cache-friendly (we compute one double-width slice of the result + at a time, then move on, never bactracking except for the helpful + single-width slice overlap between successive partial sums). + """ + asize = len(a.digits) + bsize = len(b.digits) + # nbdone is # of b digits already multiplied + + assert asize > KARATSUBA_CUTOFF + assert 2 * asize <= bsize + + # Allocate result space, and zero it out. + ret = W_LongObject(a.space, [0] * (asize + bsize), 1) + + # Successive slices of b are copied into bslice. + #bslice = W_LongObject(a.space, [0] * asize, 1) + # XXX we cannot pre-allocate, see comments below! + bslice = W_LongObject(a.space, [0], 1) + + nbdone = 0; + while bsize > 0: + nbtouse = min(bsize, asize) + + # Multiply the next slice of b by a. + + #bslice.digits[:nbtouse] = b.digits[nbdone : nbdone + nbtouse] + # XXX: this would be more efficient if we adopted CPython's + # way to store the size, instead of resizing the list! + # XXX change the implementation, encoding length via the sign. + bslice.digits = b.digits[nbdone : nbdone + nbtouse] + product = _k_mul(a, bslice) + + # Add into result. + _v_iadd(ret.digits, nbdone, len(ret.digits) - nbdone, + product.digits, len(product.digits)) + del product + + bsize -= nbtouse + nbdone += nbtouse + + ret._normalize() + return ret + + def _inplace_divrem1(pout, pin, n, size=0): """ Divide long pin by non-zero digit n, storing quotient in pout, and returning the remainder. It's OK for pin == pout on entry. """ - rem = Twodigits(0) + rem = 0 assert n > 0 and n <= MASK if not size: size = len(pin.digits) @@ -665,7 +1049,7 @@ while size >= 0: rem = (rem << SHIFT) + pin.digits[size] hi = rem // n - pout.digits[size] = Digit(hi) + pout.digits[size] = hi rem -= hi * n size -= 1 return rem @@ -678,24 +1062,80 @@ """ assert n > 0 and n <= MASK size = len(a.digits) - z = W_LongObject(a.space, [Digit(0)] * size, 1) + z = W_LongObject(a.space, [0] * size, 1) rem = _inplace_divrem1(z, a, n) z._normalize() return z, rem +def _v_iadd(x, xofs, m, y, n): + """ + x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n] + is modified in place, by adding y to it. Carries are propagated as far as + x[m-1], and the remaining carry (0 or 1) is returned. + Python adaptation: x is addressed relative to xofs! + """ + carry = 0; + + assert m >= n + i = xofs + iend = xofs + n + while i < iend: + carry += x[i] + y[i-xofs] + x[i] = carry & MASK + carry >>= SHIFT + assert (carry & 1) == carry + i += 1 + iend = xofs + m + while carry and i < iend: + carry += x[i] + x[i] = carry & MASK + carry >>= SHIFT + assert (carry & 1) == carry + i += 1 + return carry + +def _v_isub(x, xofs, m, y, n): + """ + x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n] + is modified in place, by subtracting y from it. Borrows are propagated as + far as x[m-1], and the remaining borrow (0 or 1) is returned. + Python adaptation: x is addressed relative to xofs! + """ + borrow = 0 + + assert m >= n + i = xofs + iend = xofs + n + while i < iend: + borrow = x[i] - y[i-xofs] - borrow + x[i] = borrow & MASK + borrow >>= SHIFT + borrow &= 1 # keep only 1 sign bit + i += 1 + iend = xofs + m + while borrow and i < iend: + borrow = x[i] - borrow + x[i] = borrow & MASK + borrow >>= SHIFT + borrow &= 1 + i += 1 + return borrow + + def _muladd1(a, n, extra): """Multiply by a single digit and add a single digit, ignoring the sign. """ size_a = len(a.digits) - z = W_LongObject(a.space, [Digit(0)] * (size_a+1), 1) - carry = Carrymul(extra) + z = W_LongObject(a.space, [0] * (size_a+1), 1) + carry = extra + assert carry & MASK == carry i = 0 while i < size_a: - carry += Twodigits(a.digits[i]) * n - z.digits[i] = Digit(carry & MASK) + carry += a.digits[i] * n + z.digits[i] = carry & MASK carry >>= SHIFT i += 1 - z.digits[i] = Digit(carry) + z.digits[i] = carry z._normalize() return z @@ -703,69 +1143,66 @@ def _x_divrem(v1, w1): """ Unsigned long division with remainder -- the algorithm """ size_w = len(w1.digits) - d = Digit(Twodigits(MASK+1) // (w1.digits[size_w-1] + 1)) - v = _muladd1(v1, d, Digit(0)) - w = _muladd1(w1, d, Digit(0)) + d = (MASK+1) // (w1.digits[size_w-1] + 1) + v = _muladd1(v1, d, 0) + w = _muladd1(w1, d, 0) size_v = len(v.digits) size_w = len(w.digits) 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, [Digit(0)] * size_a, 1) + a = W_LongObject(v.space, [0] * size_a, 1) j = size_v k = size_a - 1 while k >= 0: if j >= size_v: - vj = Digit(0) + vj = 0 else: vj = v.digits[j] - carry = Stwodigits(0) # note: this must hold two digits and a sign! + carry = 0 if vj == w.digits[size_w-1]: - q = Twodigits(MASK) + q = MASK else: - q = ((Twodigits(vj) << SHIFT) + v.digits[j-1]) // w.digits[size_w-1] + q = ((vj << SHIFT) + v.digits[j-1]) // w.digits[size_w-1] - # notabene! - # this check needs a signed two digits result - # or we get an overflow. while (w.digits[size_w-2] * q > (( - (Stwodigits(vj) << SHIFT) # this one dominates - + Stwodigits(v.digits[j-1]) - - Stwodigits(q) * Stwodigits(w.digits[size_w-1]) + (vj << SHIFT) + + v.digits[j-1] + - q * w.digits[size_w-1] ) << SHIFT) - + Stwodigits(v.digits[j-2])): + + v.digits[j-2]): q -= 1 i = 0 while i < size_w and i+k < size_v: - z = Stwodigits(w.digits[i] * q) + z = w.digits[i] * q zz = z >> SHIFT - carry += Stwodigits(v.digits[i+k]) - z + (zz << SHIFT) - v.digits[i+k] = Digit(carry & MASK) + carry += v.digits[i+k] - z + (zz << SHIFT) + v.digits[i+k] = carry & MASK carry >>= SHIFT carry -= zz i += 1 if i+k < size_v: - carry += Stwodigits(v.digits[i+k]) - v.digits[i+k] = Digit(0) + carry += v.digits[i+k] + v.digits[i+k] = 0 if carry == 0: - a.digits[k] = Digit(q & MASK) + a.digits[k] = q & MASK assert not q >> SHIFT else: assert carry == -1 q -= 1 - a.digits[k] = Digit(q & MASK) + a.digits[k] = q & MASK assert not q >> SHIFT - carry = Stwodigits(0) + carry = 0 i = 0 while i < size_w and i+k < size_v: - carry += Stwodigits(v.digits[i+k]) + Stwodigits(w.digits[i]) - v.digits[i+k] = Digit(carry & MASK) + carry += v.digits[i+k] + w.digits[i] + v.digits[i+k] = carry & MASK carry >>= SHIFT i += 1 j -= 1 @@ -789,7 +1226,7 @@ (size_a == size_b and a.digits[size_a-1] < b.digits[size_b-1])): # |a| < |b| - z = W_LongObject(a.space, [Digit(0)], 0) + z = W_LongObject(a.space, [0], 0) rem = a return z, rem if size_b == 1: @@ -846,12 +1283,12 @@ ##def ldexp(x, exp): ## assert type(x) is float ## lb1 = LONG_BIT - 1 -## multiplier = float(Digit(1) << lb1) +## multiplier = float(1 << lb1) ## while exp >= lb1: ## x *= multiplier ## exp -= lb1 ## if exp: -## x *= float(Digit(1) << exp) +## x *= float(1 << exp) ## return x # note that math.ldexp checks for overflows, @@ -904,13 +1341,13 @@ dval = -dval frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 if expo <= 0: - return W_LongObject(space, [Digit(0)], 0) + return W_LongObject(space, [0], 0) ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result - v = W_LongObject(space, [Digit(0)] * ndig, 1) + v = W_LongObject(space, [0] * ndig, 1) frac = math.ldexp(frac, (expo-1) % SHIFT + 1) for i in range(ndig-1, -1, -1): - bits = int(frac) - v.digits[i] = Digit(bits) + bits = int(frac) & MASK # help the future annotator? + v.digits[i] = bits frac -= float(bits) frac = math.ldexp(frac, SHIFT) if neg: @@ -937,7 +1374,7 @@ div, mod = _divrem(v, w) if mod.sign * w.sign == -1: mod = add__Long_Long(v.space, mod, w) - one = W_LongObject(v.space, [Digit(1)], 1) + one = W_LongObject(v.space, [1], 1) div = sub__Long_Long(v.space, div, one) return div, mod @@ -974,7 +1411,7 @@ s[p] = '0' elif (base & (base - 1)) == 0: # JRH: special case for power-of-2 bases - accum = Twodigits(0) + accum = 0 accumbits = 0 # # of bits in accum basebits = 1 # # of bits in base-1 i = base @@ -985,7 +1422,7 @@ basebits += 1 for i in range(size_a): - accum |= Twodigits(a.digits[i]) << accumbits + accum |= a.digits[i] << accumbits accumbits += SHIFT assert accumbits >= basebits while 1: @@ -1012,17 +1449,17 @@ size = size_a pin = a # just for similarity to C source which uses the array # powbase <- largest power of base that fits in a digit. - powbase = Digit(base) # powbase == base ** power + powbase = base # powbase == base ** power power = 1 while 1: - newpow = Twodigits(powbase) * Digit(base) + newpow = powbase * base if newpow >> SHIFT: # doesn't fit in a digit break - powbase = Digit(newpow) + powbase = newpow power += 1 # Get a scratch area for repeated division. - scratch = W_LongObject(a.space, [Digit(0)] * size, 1) + scratch = W_LongObject(a.space, [0] * size, 1) # Repeatedly divide by powbase. while 1: @@ -1086,14 +1523,14 @@ if a.sign < 0: a = invert__Long(a.space, a) - maska = Digit(MASK) + maska = MASK else: - maska = Digit(0) + maska = 0 if b.sign < 0: b = invert__Long(b.space, b) - maskb = Digit(MASK) + maskb = MASK else: - maskb = Digit(0) + maskb = 0 negz = 0 if op == '^': @@ -1135,7 +1572,7 @@ else: size_z = max(size_a, size_b) - z = W_LongObject(a.space, [Digit(0)] * size_z, 1) + z = W_LongObject(a.space, [0] * size_z, 1) for i in range(size_z): if i < size_a: @@ -1161,17 +1598,17 @@ def _AsLong(v): """ Get an integer from a long int object. - Returns -1 and sets an error condition if overflow occurs. + Raises OverflowError if overflow occurs. """ # This version by Tim Peters i = len(v.digits) - 1 sign = v.sign if not sign: return 0 - x = r_uint(0) + x = 0 while i >= 0: prev = x - x = (x << SHIFT) + v.digits[i] + x = ((x << SHIFT) + v.digits[i]) & LONG_MASK if (x >> SHIFT) != prev: raise OverflowError i -= 1 @@ -1180,7 +1617,7 @@ # trouble *unless* this is the min negative number. So, # trouble iff sign bit set && (positive || some bit set other # than the sign bit). - if int(x) < 0 and (sign > 0 or (x << 1) != 0): + if intmask(x) < 0 and (sign > 0 or (x << 1) & LONG_MASK != 0): raise OverflowError return intmask(int(x) * sign) 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 Wed Jul 13 17:30:39 2005 @@ -3,8 +3,8 @@ from random import random, randint from pypy.objspace.std import longobject as lobj from pypy.objspace.std.objspace import FailedToImplement -from pypy.rpython.rarithmetic import r_uint from pypy.interpreter.error import OperationError +from pypy.rpython.rarithmetic import r_uint # will go away objspacename = 'std' @@ -40,7 +40,7 @@ assert result.longval() == x * i - y * j def test_subzz(self): - w_l0 = lobj.W_LongObject(self.space, [r_uint(0)]) + w_l0 = lobj.W_LongObject(self.space, [0]) assert self.space.sub(w_l0, w_l0).longval() == 0 def test_mul(self): @@ -50,13 +50,16 @@ f2 = lobj.W_LongObject(self.space, *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 + result = lobj.mul__Long_Long(self.space, f1, f1) + assert result.longval() == x * x def test__inplace_divrem1(self): # signs are not handled in the helpers! x = 1238585838347L y = 3 f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = r_uint(y) + f2 = y remainder = lobj._inplace_divrem1(f1, f1, f2) assert (f1.longval(), remainder) == divmod(x, y) @@ -65,7 +68,7 @@ x = 1238585838347L y = 3 f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = r_uint(y) + f2 = y div, rem = lobj._divrem1(f1, f2) assert (div.longval(), rem) == divmod(x, y) @@ -74,8 +77,8 @@ y = 3 z = 42 f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = r_uint(y) - f3 = r_uint(z) + f2 = y + f3 = z prod = lobj._muladd1(f1, f2, f3) assert prod.longval() == x * y + z @@ -125,6 +128,45 @@ except OperationError, e: assert e.w_type is self.space.w_OverflowError + # 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) + 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) + 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 + + def test__kmul_split(self): + split = 5 + diglo = [0] * split + dighi = [lobj.MASK] * split + f1 = lobj.W_LongObject(self.space, 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)) + 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) + ret = lobj._k_lopsided_mul(f1, f2) + assert ret.longval() == f1.longval() * f2.longval() + def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L @@ -157,7 +199,7 @@ u = lobj.uint_w__Long(self.space, f2) assert u == 12332 - assert isinstance(u, r_uint) + assert type(u) is r_uint def test_conversions(self): space = self.space @@ -170,10 +212,10 @@ assert space.is_true(space.isinstance(lobj.int__Long(space, w_lv), space.w_int)) assert space.eq_w(lobj.int__Long(space, w_lv), w_v) - if v>=0: + if v >= 0: u = lobj.uint_w__Long(space, w_lv) assert u == v - assert isinstance(u, r_uint) + assert type(u) is r_uint else: space.raises_w(space.w_ValueError, lobj.uint_w__Long, space, w_lv) @@ -193,8 +235,7 @@ u = lobj.uint_w__Long(space, w_lmaxuint) assert u == 2*sys.maxint+1 - assert isinstance(u, r_uint) - + space.raises_w(space.w_ValueError, lobj.uint_w__Long, space, w_toobig_lv3) space.raises_w(space.w_OverflowError, lobj.uint_w__Long, space, w_toobig_lv4) @@ -229,10 +270,10 @@ assert v.longval() == x ** y def test_normalize(self): - f1 = lobj.W_LongObject(self.space, [lobj.r_uint(1), lobj.r_uint(0)], 1) + f1 = lobj.W_LongObject(self.space, [1, 0], 1) f1._normalize() assert len(f1.digits) == 1 - f0 = lobj.W_LongObject(self.space, [lobj.r_uint(0)], 0) + f0 = lobj.W_LongObject(self.space, [0], 0) assert self.space.is_true( self.space.eq(lobj.sub__Long_Long(self.space, f1, f1), f0)) From tismer at codespeak.net Wed Jul 13 17:53:24 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 17:53:24 +0200 (CEST) Subject: [pypy-svn] r14625 - pypy/dist/pypy/objspace/std Message-ID: <20050713155324.9060327B5E@code1.codespeak.net> Author: tismer Date: Wed Jul 13 17:53:23 2005 New Revision: 14625 Modified: pypy/dist/pypy/objspace/std/strutil.py Log: another less urgent optimization from the train Kiel-Berlin: refactored string_to_float quite a lot. The issue was raised by Python 2.4's test_long, which caused an overflow in strutil instead of an 1.#inf. I took the chance to rework this quite a little, with the result of - less rounding errors - smaller code - much faster in extreme cases - able to eval float('1.'+10000*'0'+'e-10000') and friends - seems to produce exactly the same as builtin float as far as tested. Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Wed Jul 13 17:53:23 2005 @@ -100,14 +100,14 @@ digit = p.next_digit() if digit == -1: try: - result = ovfcheck(p.sign*result) + result = ovfcheck(p.sign * result) except OverflowError: raise ParseStringOverflowError(p) else: return result try: - result = ovfcheck(result*base) - result = ovfcheck(result+digit) + result = ovfcheck(result * base) + result = ovfcheck(result + digit) except OverflowError: raise ParseStringOverflowError(p) @@ -244,3 +244,135 @@ r = -r return r + +# old version temporarily left here for comparison +old_string_to_float = string_to_float + +# 57 bits are more than needed in any case. +# to allow for some rounding, we take one +# digit more. +MANTISSA_DIGITS = len(str( (1L << 57)-1 )) + 1 + +def string_to_float(s): + """ + Conversion of string to float. + This version tries to only raise on invalid literals. + Overflows should be converted to infinity whenever possible. + """ + # this version was triggered by Python 2.4 which adds + # a test that breaks on overflow. + # XXX The test still breaks for a different reason: + # float must implement rich comparisons, where comparison + # between infinity and a too large long does not overflow! + + # The problem: + # there can be extreme notations of floats which are not + # infinity. + # For instance, this works in CPython: + # float('1' + '0'*1000 + 'e-1000') + # should evaluate to 1.0. + # note: float('1' + '0'*10000 + 'e-10000') + # does not work in CPython, but PyPy can do it, now. + + # The idea: + # in order to compensate between very long digit strings + # and extreme exponent numbers, we try to avoid overflows + # by adjusting the exponent by the number of mantissa + # digits. Exponent computation is done in integer, unless + # we get an overflow, where we fall back to float. + # Usage of long numbers is explicitly avoided, because + # we want to be able to work without longs as a PyPy option. + + # Observations: + # because we are working on a 10-basis, which leads to + # precision loss when multiplying by a power of 10, we need to be + # careful about order of operation: + # additions must be made starting with the lowest digits + # powers of 10.0 should be calculated using **, because this is + # more exact than multiplication. + # avoid division/multiplication as much as possible. + + # The plan: + # 1) parse the string into pieces. + # 2) pre-calculate digit exponent dexp. + # 3) truncate and adjust dexp. + # 4) compute the exponent. + # add the number of digits before the point to the exponent. + # if we get an overflow here, we try to compute the exponent + # by intermediate floats. + # 5) check the exponent for overflow and truncate to +-400. + # 6) add/multiply the digits in, adjusting e. + + # XXX: limitations: + # the algorithm is probably not optimum concerning the resulting + # bit pattern, but very close to it. pre-computing to binary + # numbers would give less rounding in the last digit. But this is + # quite hard to do without longs. + + s = strip_spaces(s) + + if not s: + raise ParseStringError("empty string for float()") + + # 1) parse the string into pieces. + sign, before_point, after_point, exponent = break_up_float(s) + + if not before_point and not after_point: + raise ParseStringError("invalid string literal for float()") + + # 2) pre-calculate digit exponent dexp. + dexp = len(before_point) + + # 3) truncate and adjust dexp. + digits = before_point + after_point + p = 0 + plim = dexp + len(after_point) + while p < plim and digits[p] == '0': + p += 1 + dexp -= 1 + digits = digits[p : p + MANTISSA_DIGITS] + p = len(digits) - 1 + while p >= 0 and digits[p] == '0': + p -= 1 + dexp -= p + 1 + + # 4) compute the exponent. + if not exponent: + exponent = '0' + try: + e = string_to_int(exponent) + e = ovfcheck(e + dexp) + except (ParseStringOverflowError, OverflowError): + fe = string_to_float(exponent) + dexp + try: + e = ovfcheck(int(fe)) + except OverflowError: + # 4) check the exponent for overflow and truncate to +-400. + if exponent[0] == '-': + e = -400 + else: + e = 400 + # 5) check the exponent for overflow and truncate to +-400. + if e >= 400: + e = 400 + elif e <= -400: + e = -400 + # e is now in a range that does not overflow on additions. + + # 6) add/multiply the digits in, adjusting e. + r = 0.0 + try: + while p >= 0: + # note: exponentiation is intentionally used for + # exactness. If time is an issue, this can easily + # be kept in a cache for every digit value. + r += (ord(digits[p]) - ord('0')) * 10.0 ** e + p -= 1 + e += 1 + except OverflowError: + r =1e200 * 1e200 + + if sign == '-': + r = -r + + return r From tismer at codespeak.net Wed Jul 13 17:54:33 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 17:54:33 +0200 (CEST) Subject: [pypy-svn] r14626 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050713155433.A112027B5E@code1.codespeak.net> Author: tismer Date: Wed Jul 13 17:54:32 2005 New Revision: 14626 Modified: pypy/dist/pypy/objspace/std/floatobject.py pypy/dist/pypy/objspace/std/test/test_strutil.py Log: small cosmetic cleanup Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Wed Jul 13 17:54:32 2005 @@ -227,7 +227,8 @@ def pow__Float_Float_ANY(space, w_float1, w_float2, thirdArg): if not space.is_w(thirdArg, space.w_None): - raise FailedToImplement(space.w_TypeError, space.wrap("pow() 3rd argument not allowed unless all arguments are integers")) + raise FailedToImplement(space.w_TypeError, space.wrap( + "pow() 3rd argument not allowed unless all arguments are integers")) x = w_float1.floatval y = w_float2.floatval try: Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Wed Jul 13 17:54:32 2005 @@ -94,7 +94,7 @@ str(sys.maxint*17)) def test_string_to_int_base_error(self): - space = self.space + space = self.space cases = [('1', 1), ('1', 37), ('a', 0), From tismer at codespeak.net Wed Jul 13 18:09:07 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 18:09:07 +0200 (CEST) Subject: [pypy-svn] r14627 - pypy/dist/pypy/objspace/std Message-ID: <20050713160907.16FA027B60@code1.codespeak.net> Author: tismer Date: Wed Jul 13 18:09:06 2005 New Revision: 14627 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: rworked commentary a little, dropped a superseded helper function. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 13 18:09:06 2005 @@ -7,20 +7,27 @@ import math -# after many days of debugging and testing, -# I (chris) finally found out about overflows -# and how to assign the correct types. -# But in the end, this really makes no sense at all. -# Finally I think thatr we should avoid to use anything -# but general integers. r_uint and friends should go away! +# It took many days of debugging and testing, until +# I (chris) finally understood how things work and where +# to expect overflows in the division code. +# In the end, I decided to throw this all out and to use +# plain integer expressions. r_uint and friends should go away! # Unsignedness can be completely deduced by back-propagation # of masking. I will change the annotator to do this. -# remember: not typing at all is much stronger! -# -# my conclusion: -# having no special types at all, but describing everything +# Having no special types at all, but describing everything # in terms of operations and masks is the stronger way. +# Digit size: +# SHIFT cannot be larger than below, for the moment. +# in division, the native integer type must be able to hold +# a sign bit plus two digits plus 1 overflow bit. +# +# Given that we support more primitive types, this might +# become a nicer layout for, say, and X86 assembly backend: +# The digit would be 32 bit long unsigned int, +# two digits would be 64 bit long lojng unsigned int, +# and the signed type mentioned above would be 80 bit extended. + SHIFT = (LONG_BIT // 2) - 1 MASK = int((1 << SHIFT) - 1) @@ -46,6 +53,7 @@ """This is a reimplementation of longs using a list of digits.""" # All functions that still rely on the underlying Python's longs are marked # with YYYYYY + # 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): @@ -313,71 +321,6 @@ div, mod = _l_divmod(w_long1, w_long2) return space.newtuple([div, mod]) -# helper for pow() -def _impl_long_long_pow(space, lv, lw, lz=None): - if lw.sign < 0: - if lz is not None: - raise OperationError(space.w_TypeError, - space.wrap("pow() 2nd argument " - "cannot be negative when 3rd argument specified")) - return space.pow(space.newfloat(_AsDouble(lv)), - space.newfloat(_AsDouble(lw)), - space.w_None) - if lz is not None: - if lz.sign == 0: - raise OperationError(space.w_ValueError, space.wrap( - "pow() 3rd argument cannot be 0")) - result = W_LongObject(space, [1], 1) - if lw.sign == 0: - if lz is not None: - result = mod__Long_Long(space, result, lz) - return result - if lz is not None: - temp = mod__Long_Long(space, lv, lz) - else: - temp = lv - i = 0 - # Treat the most significant digit specially to reduce multiplications - while i < len(lw.digits) - 1: - j = 0 - m = 1 - di = lw.digits[i] - while j < SHIFT: - if di & m: - result = mul__Long_Long(space, result, temp) - temp = mul__Long_Long(space, temp, temp) - if lz is not None: - result = mod__Long_Long(space, result, lz) - temp = mod__Long_Long(space, temp, lz) - m = m << 1 - j += 1 - i += 1 - m = 1 << (SHIFT - 1) - highest_set_bit = SHIFT - j = SHIFT - 1 - di = lw.digits[i] - while j >= 0: - if di & m: - highest_set_bit = j - break - m = m >> 1 - j -= 1 - assert highest_set_bit != SHIFT, "long not normalized" - j = 0 - m = 1 - while j <= highest_set_bit: - if di & m: - result = mul__Long_Long(space, result, temp) - temp = mul__Long_Long(space, temp, temp) - if lz is not None: - result = mod__Long_Long(space, result, lz) - temp = mod__Long_Long(space, temp, lz) - m = m << 1 - j += 1 - if lz: - result = mod__Long_Long(space, result, lz) - return result - def _impl_long_long_pow(space, a, b, c=None): """ pow(a, b, c) """ From tismer at codespeak.net Wed Jul 13 18:17:29 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 18:17:29 +0200 (CEST) Subject: [pypy-svn] r14628 - pypy/dist/pypy/objspace/std Message-ID: <20050713161729.2C6A727B60@code1.codespeak.net> Author: tismer Date: Wed Jul 13 18:17:28 2005 New Revision: 14628 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: typos, more commentary. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 13 18:17:28 2005 @@ -19,13 +19,15 @@ # Digit size: # SHIFT cannot be larger than below, for the moment. -# in division, the native integer type must be able to hold +# In division, the native integer type must be able to hold # a sign bit plus two digits plus 1 overflow bit. +# As a result, our digits will be 15 bits with one unused +# bit, exactly as it is in CPython. # -# Given that we support more primitive types, this might -# become a nicer layout for, say, and X86 assembly backend: +# Given that we support some more primitive types for integers, +# this might become a nicer layout for an X86 assembly backend: # The digit would be 32 bit long unsigned int, -# two digits would be 64 bit long lojng unsigned int, +# two digits would be 64 bit long long unsigned int, # and the signed type mentioned above would be 80 bit extended. SHIFT = (LONG_BIT // 2) - 1 From tismer at codespeak.net Wed Jul 13 18:19:51 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 18:19:51 +0200 (CEST) Subject: [pypy-svn] r14629 - pypy/dist/pypy/objspace/std Message-ID: <20050713161951.76E9927B64@code1.codespeak.net> Author: tismer Date: Wed Jul 13 18:19:51 2005 New Revision: 14629 Modified: pypy/dist/pypy/objspace/std/strutil.py Log: typo, wording Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Wed Jul 13 18:19:51 2005 @@ -364,13 +364,13 @@ try: while p >= 0: # note: exponentiation is intentionally used for - # exactness. If time is an issue, this can easily + # exactness. If speed is an issue, this can easily # be kept in a cache for every digit value. r += (ord(digits[p]) - ord('0')) * 10.0 ** e p -= 1 e += 1 except OverflowError: - r =1e200 * 1e200 + r = 1e200 * 1e200 if sign == '-': r = -r From tismer at codespeak.net Wed Jul 13 19:00:35 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 13 Jul 2005 19:00:35 +0200 (CEST) Subject: [pypy-svn] r14630 - pypy/dist/pypy/objspace/std Message-ID: <20050713170035.A0A2027B60@code1.codespeak.net> Author: tismer Date: Wed Jul 13 19:00:35 2005 New Revision: 14630 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: added more thoughts about different integer types. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Wed Jul 13 19:00:35 2005 @@ -24,11 +24,35 @@ # As a result, our digits will be 15 bits with one unused # bit, exactly as it is in CPython. # +# The algorithms are anyway not bound to a given digit size. +# There are different models possible, if we support more +# native integer sizes. To support this, the annotator should +# be extended to do some basic size tracking of integers. +# +# Examples: +# C +# Most C implementations have support for signed long long. +# use an unsigned 16 bit unsigned short for the digits. +# The operations which must hold two digits become unsigned long. +# The sign+two digits+overflow register in division becomes +# a 64 bit signed long long. +# +# X86 assembler # Given that we support some more primitive types for integers, # this might become a nicer layout for an X86 assembly backend: # The digit would be 32 bit long unsigned int, # two digits would be 64 bit long long unsigned int, # and the signed type mentioned above would be 80 bit extended. +# +# Emulation of different integer types +# Even if we don't have machine support for certain types, +# it might be worth trying to emulate them by providing some +# means of multi-precision integers in rpython. +# It is possible to write primitive code that emits the +# necessary operations for emulation of larger types. +# But we should do some careful testing how fast this code +# will be, compared to just working with native types. +# Probably the primitive types will outperform this. SHIFT = (LONG_BIT // 2) - 1 MASK = int((1 << SHIFT) - 1) From pedronis at codespeak.net Wed Jul 13 19:20:48 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 19:20:48 +0200 (CEST) Subject: [pypy-svn] r14631 - in pypy/dist/pypy: interpreter interpreter/test module/__builtin__ objspace objspace/flow objspace/std tool tool/pytest Message-ID: <20050713172048.CFB7C27B66@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 19:20:34 2005 New Revision: 14631 Modified: pypy/dist/pypy/interpreter/error.py pypy/dist/pypy/interpreter/eval.py pypy/dist/pypy/interpreter/executioncontext.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/generator.py pypy/dist/pypy/interpreter/nestedscope.py pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/interpreter/pytraceback.py pypy/dist/pypy/interpreter/test/test_eval.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/__builtin__/compiling.py pypy/dist/pypy/objspace/flow/flowcontext.py pypy/dist/pypy/objspace/std/fake.py pypy/dist/pypy/objspace/trace.py pypy/dist/pypy/tool/pytest/appsupport.py pypy/dist/pypy/tool/traceop.py Log: avoid that what was .code (now pycode) get improperly lifted to Frame from PyFrame and that various attributes of PyCode get also lifted improperly to Code. Introduced an intermediary subclass eval.EvalFrame for .eval() based run/resume behavior. Now PyFrame inherits from it. Modified: pypy/dist/pypy/interpreter/error.py ============================================================================== --- pypy/dist/pypy/interpreter/error.py (original) +++ pypy/dist/pypy/interpreter/error.py Wed Jul 13 19:20:34 2005 @@ -89,7 +89,7 @@ import linecache print >> file, "Traceback (application-level):" while tb is not None: - co = tb.frame.code + co = tb.frame.pycode lineno = tb.lineno fname = co.co_filename if fname.startswith('\n'): Modified: pypy/dist/pypy/interpreter/eval.py ============================================================================== --- pypy/dist/pypy/interpreter/eval.py (original) +++ pypy/dist/pypy/interpreter/eval.py Wed Jul 13 19:20:34 2005 @@ -54,38 +54,29 @@ """A frame is an environment supporting the execution of a code object. Abstract base class.""" - def __init__(self, space, code, w_globals=None, numlocals=-1): + def __init__(self, space, w_globals=None, numlocals=-1): self.space = space - self.code = code # Code instance self.w_globals = w_globals # wrapped dict of globals self.w_locals = None # wrapped dict of locals if numlocals < 0: # compute the minimal size based on arguments - numlocals = len(code.getvarnames()) + numlocals = len(self.getcode().getvarnames()) self.numlocals = numlocals - def resume(self): - "Resume the execution of the frame from its current state." - executioncontext = self.space.getexecutioncontext() - executioncontext.enter(self) - try: - result = self.eval(executioncontext) - finally: - executioncontext.leave(self) - return result - - # running a frame is usually the same as resuming it from its - # initial state, but not for generator frames - run = resume - - def eval(self, executioncontext): - "Abstract method to override." + def run(self): + "Abstract method to override. Runs the frame" raise TypeError, "abstract" - + def getdictscope(self): "Get the locals as a dictionary." self.fast2locals() return self.w_locals + def getcode(self): + return None + + def fget_code(space, self): + return space.wrap(self.getcode()) + def fget_getdictscope(space, self): # unwrapping through unwrap_spec in typedef.py return self.getdictscope() @@ -100,14 +91,14 @@ def setfastscope(self, scope_w): """Abstract. Initialize the fast locals from a list of values, - where the order is according to self.code.signature().""" + where the order is according to self.getcode().signature().""" raise TypeError, "abstract" def fast2locals(self): # Copy values from self.fastlocals_w to self.w_locals if self.w_locals is None: self.w_locals = self.space.newdict([]) - varnames = self.code.getvarnames() + varnames = self.getcode().getvarnames() fastscope_w = self.getfastscope() for i in range(min(len(varnames), len(fastscope_w))): name = varnames[i] @@ -119,7 +110,7 @@ def locals2fast(self): # Copy values from self.w_locals to self.fastlocals_w assert self.w_locals is not None - varnames = self.code.getvarnames() + varnames = self.getcode().getvarnames() new_fastlocals_w = [None]*self.numlocals @@ -134,3 +125,27 @@ new_fastlocals_w[i] = w_value self.setfastscope(new_fastlocals_w) + + +class EvalFrame(Frame): + + def resume(self): + "Resume the execution of the frame from its current state." + executioncontext = self.space.getexecutioncontext() + executioncontext.enter(self) + try: + result = self.eval(executioncontext) + finally: + executioncontext.leave(self) + return result + + # running a frame is usually the same as resuming it from its + # initial state, but not for generator frames + run = resume + + def eval(self, executioncontext): + "Abstract method to override." + raise TypeError, "abstract" + + def hide(self): + return False Modified: pypy/dist/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/dist/pypy/interpreter/executioncontext.py (original) +++ pypy/dist/pypy/interpreter/executioncontext.py Wed Jul 13 19:20:34 2005 @@ -23,14 +23,14 @@ except: frame.f_back = None - if not frame.code.hidden_applevel: + if not frame.hide(): self.framestack.push(frame) def leave(self, frame): if self.w_profilefunc: self._trace(frame, 'leaveframe', None) - if not frame.code.hidden_applevel: + if not frame.hide(): self.framestack.pop() def get_builtin(self): @@ -59,7 +59,7 @@ "Trace function called before each bytecode." if self.is_tracing or frame.w_f_trace is None: return - code = getattr(frame, 'code') + code = getattr(frame, 'pycode') if frame.instr_lb <= frame.last_instr < frame.instr_ub: return @@ -136,7 +136,7 @@ self.is_tracing = is_tracing def _trace(self, frame, event, w_arg, operr=None): - if self.is_tracing or frame.code.hidden_applevel: + if self.is_tracing or frame.hide(): return space = self.space Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Wed Jul 13 19:20:34 2005 @@ -235,6 +235,13 @@ # Initialization of locals is already done by the time run() is called, # via the interface defined in eval.Frame. + def __init__(self, space, code, w_globals=None, numlocals=-1): + self.bltn_code = code + eval.Frame.__init__(self, space, w_globals, numlocals) + + def getcode(self): + return self.bltn_code + def setfastscope(self, scope_w): """Subclasses with behavior specific for an unwrap spec are generated""" raise TypeError, "abstract" Modified: pypy/dist/pypy/interpreter/generator.py ============================================================================== --- pypy/dist/pypy/interpreter/generator.py (original) +++ pypy/dist/pypy/interpreter/generator.py Wed Jul 13 19:20:34 2005 @@ -1,6 +1,6 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.eval import Frame +from pypy.interpreter.eval import EvalFrame from pypy.interpreter.pyframe import ControlFlowException, ExitFrame # @@ -12,7 +12,7 @@ # that return iterators). # -class GeneratorFrame(Frame): +class GeneratorFrame(EvalFrame): "A frame attached to a generator." def run(self): Modified: pypy/dist/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/dist/pypy/interpreter/nestedscope.py (original) +++ pypy/dist/pypy/interpreter/nestedscope.py Wed Jul 13 19:20:34 2005 @@ -65,14 +65,14 @@ self.cells = [Cell() for i in range(ncellvars)] + closure def getclosure(self): - ncellvars = len(self.code.co_cellvars) # not part of the closure + ncellvars = len(self.pycode.co_cellvars) # not part of the closure return self.cells[ncellvars:] def fast2locals(self): PyInterpFrame.fast2locals(self) # cellvars are values exported to inner scopes # freevars are values coming from outer scopes - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars for i in range(len(freevarnames)): name = freevarnames[i] cell = self.cells[i] @@ -86,7 +86,7 @@ def locals2fast(self): PyInterpFrame.locals2fast(self) - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars for i in range(len(freevarnames)): name = freevarnames[i] cell = self.cells[i] @@ -101,10 +101,10 @@ def setfastscope(self, scope_w): PyInterpFrame.setfastscope(self, scope_w) - if self.code.co_cellvars: + if self.pycode.co_cellvars: # the first few cell vars could shadow already-set arguments, # in the same order as they appear in co_varnames - code = self.code + code = self.pycode argvars = code.co_varnames cellvars = code.co_cellvars next = 0 @@ -121,12 +121,12 @@ break # all cell vars initialized this way def getfreevarname(self, index): - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars return freevarnames[index] def iscellvar(self, index): # is the variable given by index a cell or a free var? - return index < len(self.code.co_cellvars) + return index < len(self.pycode.co_cellvars) ### extra opcodes ### Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Wed Jul 13 19:20:34 2005 @@ -21,7 +21,7 @@ return sys.exc_info()[2] cpython_tb._annspecialcase_ = "override:ignore" -class PyFrame(eval.Frame): +class PyFrame(eval.EvalFrame): """Represents a frame for a regular Python function that needs to be interpreted. @@ -37,7 +37,8 @@ """ def __init__(self, space, code, w_globals, closure): - eval.Frame.__init__(self, space, code, w_globals, code.co_nlocals) + self.pycode = code + eval.Frame.__init__(self, space, w_globals, code.co_nlocals) self.valuestack = Stack() self.blockstack = Stack() self.last_exception = None @@ -52,11 +53,17 @@ self.w_f_trace = None self.last_instr = -1 self.f_back = None - self.f_lineno = self.code.co_firstlineno + self.f_lineno = self.pycode.co_firstlineno # For tracing self.instr_lb = 0 self.instr_ub = -1 + + def hide(self): + return self.pycode.hidden_applevel + + def getcode(self): + return self.pycode def getfastscope(self): "Get the fast locals as a list." @@ -64,7 +71,7 @@ def setfastscope(self, scope_w): """Initialize the fast locals from a list of values, - where the order is according to self.code.signature().""" + where the order is according to self.pycode.signature().""" if len(scope_w) > len(self.fastlocals_w): raise ValueError, "new fastscope is longer than the allocated area" self.fastlocals_w[:len(scope_w)] = scope_w @@ -145,15 +152,15 @@ raise OperationError(space.w_ValueError, space.wrap("f_lineo can only be set by a trace function.")) - if new_lineno < self.code.co_firstlineno: + if new_lineno < self.pycode.co_firstlineno: raise OperationError(space.w_ValueError, space.wrap("line %d comes before the current code." % new_lineno)) - code = self.code.co_code + code = self.pycode.co_code addr = 0 - line = self.code.co_firstlineno + line = self.pycode.co_firstlineno new_lasti = -1 offset = 0 - lnotab = self.code.co_lnotab + lnotab = self.pycode.co_lnotab for offset in xrange(0, len(lnotab), 2): addr += ord(lnotab[offset]) line += ord(lnotab[offset + 1]) @@ -259,11 +266,11 @@ def get_last_lineno(self): "Returns the line number of the instruction currently being executed." - return pytraceback.offset2lineno(self.code, self.next_instr-1) + return pytraceback.offset2lineno(self.pycode, self.next_instr-1) def get_next_lineno(self): "Returns the line number of the next instruction to execute." - return pytraceback.offset2lineno(self.code, self.next_instr) + return pytraceback.offset2lineno(self.pycode, self.next_instr) def fget_f_builtins(space, self): return self.builtin.getdict() Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Wed Jul 13 19:20:34 2005 @@ -57,7 +57,7 @@ fn(self) def nextop(self): - c = self.code.co_code[self.next_instr] + c = self.pycode.co_code[self.next_instr] self.next_instr += 1 return ord(c) @@ -69,16 +69,16 @@ ### accessor functions ### def getlocalvarname(self, index): - return self.code.co_varnames[index] + return self.pycode.co_varnames[index] def getconstant_w(self, index): - return self.code.co_consts_w[index] + return self.pycode.co_consts_w[index] def getname_u(self, index): - return self.code.co_names[index] + return self.pycode.co_names[index] def getname_w(self, index): - return self.space.wrap(self.code.co_names[index]) + return self.space.wrap(self.pycode.co_names[index]) ################################################################ @@ -113,9 +113,9 @@ # print " varindex:", varindex # print " len(locals_w)", len(f.locals_w) # import dis - # print dis.dis(f.code) - # print "co_varnames", f.code.co_varnames - # print "co_nlocals", f.code.co_nlocals + # print dis.dis(f.pycode) + # print "co_varnames", f.pycode.co_varnames + # print "co_nlocals", f.pycode.co_nlocals # raise def POP_TOP(f): @@ -348,7 +348,7 @@ w_locals = f.valuestack.pop() w_globals = f.valuestack.pop() w_prog = f.valuestack.pop() - flags = f.space.getexecutioncontext().compiler.getcodeflags(f.code) + flags = f.space.getexecutioncontext().compiler.getcodeflags(f.pycode) w_compile_flags = f.space.wrap(flags) w_resulttuple = prepare_exec(f.space, f.space.wrap(f), w_prog, w_globals, w_locals, Modified: pypy/dist/pypy/interpreter/pytraceback.py ============================================================================== --- pypy/dist/pypy/interpreter/pytraceback.py (original) +++ pypy/dist/pypy/interpreter/pytraceback.py Wed Jul 13 19:20:34 2005 @@ -20,9 +20,9 @@ def record_application_traceback(space, operror, frame, last_instruction): - if frame.code.hidden_applevel: + if frame.pycode.hidden_applevel: return - lineno = offset2lineno(frame.code, last_instruction) + lineno = offset2lineno(frame.pycode, last_instruction) tb = operror.application_traceback tb = PyTraceback(space, frame, last_instruction, lineno, tb) operror.application_traceback = tb Modified: pypy/dist/pypy/interpreter/test/test_eval.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_eval.py (original) +++ pypy/dist/pypy/interpreter/test/test_eval.py Wed Jul 13 19:20:34 2005 @@ -13,9 +13,13 @@ class ConcreteFastscopeFrame(Frame): def __init__(self, space, code, numlocals): - Frame.__init__(self, space, code, numlocals=numlocals) + self.code = code + Frame.__init__(self, space, numlocals=numlocals) self.fastlocals_w = [None] * self.numlocals + def getcode(self): + return self.code + def setfastscope(self, scope_w): self.fastlocals_w = scope_w Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Wed Jul 13 19:20:34 2005 @@ -366,7 +366,7 @@ ) Frame.typedef = TypeDef('internal-frame', - f_code = interp_attrproperty('code', cls=Frame), + f_code = GetSetProperty(Frame.fget_code), f_locals = GetSetProperty(Frame.fget_getdictscope), f_globals = interp_attrproperty_w('w_globals', cls=Frame), ) Modified: pypy/dist/pypy/module/__builtin__/compiling.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/compiling.py (original) +++ pypy/dist/pypy/module/__builtin__/compiling.py Wed Jul 13 19:20:34 2005 @@ -20,7 +20,7 @@ except IndexError: pass else: - flags |= ec.compiler.getcodeflags(caller.code) + flags |= ec.compiler.getcodeflags(caller.getcode()) if mode not in ('exec', 'eval', 'single'): raise OperationError(space.w_ValueError, Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Wed Jul 13 19:20:34 2005 @@ -100,7 +100,7 @@ # If we have a SpamBlock, the first call to bytecode_trace() # occurs as soon as frame.resume() starts, before interpretation # really begins. - varnames = frame.code.getvarnames() + varnames = frame.pycode.getvarnames() for name, w_value in zip(varnames, frame.getfastscope()): if isinstance(w_value, Variable): w_value.rename(name) Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Wed Jul 13 19:20:34 2005 @@ -136,13 +136,20 @@ class CPythonFakeFrame(eval.Frame): + def __init__(self, space, code, w_globals=None, numlocals=-1): + self.fakecode = code + eval.Frame.__init__(self, space, w_globals, numlocals) + + def getcode(self): + return self.fakecode + def setfastscope(self, scope_w): w_args, w_kwds = scope_w try: self.unwrappedargs = self.space.unwrap(w_args) self.unwrappedkwds = self.space.unwrap(w_kwds) except UnwrapError, e: - code = self.code + code = self.fakecode assert isinstance(code, CPythonFakeCode) raise UnwrapError('calling %s: %s' % (code.cpy_callable, e)) @@ -150,7 +157,7 @@ raise OperationError(self.space.w_TypeError, self.space.wrap("cannot get fastscope of a CPythonFakeFrame")) def run(self): - code = self.code + code = self.fakecode assert isinstance(code, CPythonFakeCode) fn = code.cpy_callable try: Modified: pypy/dist/pypy/objspace/trace.py ============================================================================== --- pypy/dist/pypy/objspace/trace.py (original) +++ pypy/dist/pypy/objspace/trace.py Wed Jul 13 19:20:34 2005 @@ -18,7 +18,7 @@ """ bytecode trace. """ def __init__(self, frame): self.frame = frame - self.code = frame.code + self.code = frame.pycode self.index = frame.next_instr class EnterFrame(object): @@ -85,9 +85,9 @@ """ return (possibly cached) pydis result for the given frame. """ try: - return _cache[id(frame.code)] + return _cache[id(frame.pycode)] except KeyError: - res = _cache[id(frame.code)] = pydis.pydis(frame.code) + res = _cache[id(frame.pycode)] = pydis.pydis(frame.pycode) assert res is not None return res Modified: pypy/dist/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/dist/pypy/tool/pytest/appsupport.py (original) +++ pypy/dist/pypy/tool/pytest/appsupport.py Wed Jul 13 19:20:34 2005 @@ -10,7 +10,7 @@ class AppFrame(py.code.Frame): def __init__(self, pyframe): - self.code = py.code.Code(pyframe.code) + self.code = py.code.Code(pyframe.pycode) self.lineno = pyframe.get_last_lineno() - 1 self.space = pyframe.space self.w_globals = pyframe.w_globals Modified: pypy/dist/pypy/tool/traceop.py ============================================================================== --- pypy/dist/pypy/tool/traceop.py (original) +++ pypy/dist/pypy/tool/traceop.py Wed Jul 13 19:20:34 2005 @@ -149,7 +149,7 @@ if isinstance(event, trace.EnterFrame): frame = event.frame - if self.show_hidden_applevel or not frame.code.hidden_applevel: + if self.show_hidden_applevel or not frame.pycode.hidden_applevel: show = True else: show = False @@ -183,7 +183,7 @@ # Check if we are in applevel? if not self.show_hidden_applevel: - if lastframe is None or lastframe.code.hidden_applevel: + if lastframe is None or lastframe.pycode.hidden_applevel: show = False # Check if recursive operations? From pedronis at codespeak.net Wed Jul 13 19:28:09 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 19:28:09 +0200 (CEST) Subject: [pypy-svn] r14632 - in pypy/branch/pypy-translation-snapshot: interpreter interpreter/test module/__builtin__ objspace objspace/std Message-ID: <20050713172809.3A1C827B6A@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 19:27:58 2005 New Revision: 14632 Modified: pypy/branch/pypy-translation-snapshot/interpreter/error.py pypy/branch/pypy-translation-snapshot/interpreter/eval.py pypy/branch/pypy-translation-snapshot/interpreter/executioncontext.py pypy/branch/pypy-translation-snapshot/interpreter/gateway.py pypy/branch/pypy-translation-snapshot/interpreter/generator.py pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py pypy/branch/pypy-translation-snapshot/interpreter/pytraceback.py pypy/branch/pypy-translation-snapshot/interpreter/test/test_eval.py pypy/branch/pypy-translation-snapshot/interpreter/typedef.py pypy/branch/pypy-translation-snapshot/module/__builtin__/compiling.py pypy/branch/pypy-translation-snapshot/objspace/std/fake.py pypy/branch/pypy-translation-snapshot/objspace/trace.py Log: merge 14631 from trunk. Modified: pypy/branch/pypy-translation-snapshot/interpreter/error.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/error.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/error.py Wed Jul 13 19:27:58 2005 @@ -85,7 +85,7 @@ import linecache print >> file, "Traceback (application-level):" while tb is not None: - co = tb.frame.code + co = tb.frame.pycode lineno = tb.lineno fname = co.co_filename if fname.startswith('\n'): Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/eval.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/eval.py Wed Jul 13 19:27:58 2005 @@ -54,38 +54,29 @@ """A frame is an environment supporting the execution of a code object. Abstract base class.""" - def __init__(self, space, code, w_globals=None, numlocals=-1): + def __init__(self, space, w_globals=None, numlocals=-1): self.space = space - self.code = code # Code instance self.w_globals = w_globals # wrapped dict of globals self.w_locals = None # wrapped dict of locals if numlocals < 0: # compute the minimal size based on arguments - numlocals = len(code.getvarnames()) + numlocals = len(self.getcode().getvarnames()) self.numlocals = numlocals - def resume(self): - "Resume the execution of the frame from its current state." - executioncontext = self.space.getexecutioncontext() - executioncontext.enter(self) - try: - result = self.eval(executioncontext) - finally: - executioncontext.leave(self) - return result - - # running a frame is usually the same as resuming it from its - # initial state, but not for generator frames - run = resume - - def eval(self, executioncontext): - "Abstract method to override." + def run(self): + "Abstract method to override. Runs the frame" raise TypeError, "abstract" - + def getdictscope(self): "Get the locals as a dictionary." self.fast2locals() return self.w_locals + def getcode(self): + return None + + def fget_code(space, self): + return space.wrap(self.getcode()) + def fget_getdictscope(space, self): # unwrapping through unwrap_spec in typedef.py return self.getdictscope() @@ -100,14 +91,14 @@ def setfastscope(self, scope_w): """Abstract. Initialize the fast locals from a list of values, - where the order is according to self.code.signature().""" + where the order is according to self.getcode().signature().""" raise TypeError, "abstract" def fast2locals(self): # Copy values from self.fastlocals_w to self.w_locals if self.w_locals is None: self.w_locals = self.space.newdict([]) - varnames = self.code.getvarnames() + varnames = self.getcode().getvarnames() fastscope_w = self.getfastscope() for i in range(min(len(varnames), len(fastscope_w))): name = varnames[i] @@ -119,7 +110,7 @@ def locals2fast(self): # Copy values from self.w_locals to self.fastlocals_w assert self.w_locals is not None - varnames = self.code.getvarnames() + varnames = self.getcode().getvarnames() new_fastlocals_w = [None]*self.numlocals @@ -134,3 +125,27 @@ new_fastlocals_w[i] = w_value self.setfastscope(new_fastlocals_w) + + +class EvalFrame(Frame): + + def resume(self): + "Resume the execution of the frame from its current state." + executioncontext = self.space.getexecutioncontext() + executioncontext.enter(self) + try: + result = self.eval(executioncontext) + finally: + executioncontext.leave(self) + return result + + # running a frame is usually the same as resuming it from its + # initial state, but not for generator frames + run = resume + + def eval(self, executioncontext): + "Abstract method to override." + raise TypeError, "abstract" + + def hide(self): + return False Modified: pypy/branch/pypy-translation-snapshot/interpreter/executioncontext.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/executioncontext.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/executioncontext.py Wed Jul 13 19:27:58 2005 @@ -25,14 +25,14 @@ except: frame.f_back = None - if not frame.code.hidden_applevel: + if not frame.hide(): self.framestack.push(frame) def leave(self, frame): if self.w_profilefunc: self._trace(frame, 'leaveframe', None) - if not frame.code.hidden_applevel: + if not frame.hide(): self.framestack.pop() def get_builtin(self): @@ -61,7 +61,7 @@ "Trace function called before each bytecode." if self.is_tracing or frame.w_f_trace is None: return - code = getattr(frame, 'code') + code = getattr(frame, 'pycode') if frame.instr_lb <= frame.last_instr < frame.instr_ub: return @@ -144,7 +144,7 @@ self.is_tracing = is_tracing def _trace(self, frame, event, w_arg, operr=None): - if self.is_tracing or frame.code.hidden_applevel: + if self.is_tracing or frame.hide(): return space = self.space Modified: pypy/branch/pypy-translation-snapshot/interpreter/gateway.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/gateway.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/gateway.py Wed Jul 13 19:27:58 2005 @@ -235,6 +235,13 @@ # Initialization of locals is already done by the time run() is called, # via the interface defined in eval.Frame. + def __init__(self, space, code, w_globals=None, numlocals=-1): + self.bltn_code = code + eval.Frame.__init__(self, space, w_globals, numlocals) + + def getcode(self): + return self.bltn_code + def setfastscope(self, scope_w): """Subclasses with behavior specific for an unwrap spec are generated""" raise TypeError, "abstract" Modified: pypy/branch/pypy-translation-snapshot/interpreter/generator.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/generator.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/generator.py Wed Jul 13 19:27:58 2005 @@ -1,6 +1,6 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.eval import Frame +from pypy.interpreter.eval import EvalFrame from pypy.interpreter.pyframe import ControlFlowException, ExitFrame # @@ -12,7 +12,7 @@ # that return iterators). # -class GeneratorFrame(Frame): +class GeneratorFrame(EvalFrame): "A frame attached to a generator." def run(self): Modified: pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py Wed Jul 13 19:27:58 2005 @@ -65,14 +65,14 @@ self.cells = [Cell() for i in range(ncellvars)] + closure def getclosure(self): - ncellvars = len(self.code.co_cellvars) # not part of the closure + ncellvars = len(self.pycode.co_cellvars) # not part of the closure return self.cells[ncellvars:] def fast2locals(self): PyInterpFrame.fast2locals(self) # cellvars are values exported to inner scopes # freevars are values coming from outer scopes - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars for i in range(len(freevarnames)): name = freevarnames[i] cell = self.cells[i] @@ -86,7 +86,7 @@ def locals2fast(self): PyInterpFrame.locals2fast(self) - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars for i in range(len(freevarnames)): name = freevarnames[i] cell = self.cells[i] @@ -101,10 +101,10 @@ def setfastscope(self, scope_w): PyInterpFrame.setfastscope(self, scope_w) - if self.code.co_cellvars: + if self.pycode.co_cellvars: # the first few cell vars could shadow already-set arguments, # in the same order as they appear in co_varnames - code = self.code + code = self.pycode argvars = code.co_varnames cellvars = code.co_cellvars next = 0 @@ -121,12 +121,12 @@ break # all cell vars initialized this way def getfreevarname(self, index): - freevarnames = self.code.co_cellvars + self.code.co_freevars + freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars return freevarnames[index] def iscellvar(self, index): # is the variable given by index a cell or a free var? - return index < len(self.code.co_cellvars) + return index < len(self.pycode.co_cellvars) ### extra opcodes ### Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py Wed Jul 13 19:27:58 2005 @@ -21,7 +21,7 @@ return sys.exc_info()[2] cpython_tb._annspecialcase_ = "override:ignore" -class PyFrame(eval.Frame): +class PyFrame(eval.EvalFrame): """Represents a frame for a regular Python function that needs to be interpreted. @@ -37,7 +37,8 @@ """ def __init__(self, space, code, w_globals, closure): - eval.Frame.__init__(self, space, code, w_globals, code.co_nlocals) + self.pycode = code + eval.Frame.__init__(self, space, w_globals, code.co_nlocals) self.valuestack = Stack() self.blockstack = Stack() self.last_exception = None @@ -52,11 +53,17 @@ self.w_f_trace = None self.last_instr = -1 self.f_back = None - self.f_lineno = self.code.co_firstlineno + self.f_lineno = self.pycode.co_firstlineno # For tracing self.instr_lb = 0 self.instr_ub = -1 + + def hide(self): + return self.pycode.hidden_applevel + + def getcode(self): + return self.pycode def getfastscope(self): "Get the fast locals as a list." @@ -64,7 +71,7 @@ def setfastscope(self, scope_w): """Initialize the fast locals from a list of values, - where the order is according to self.code.signature().""" + where the order is according to self.pycode.signature().""" if len(scope_w) > len(self.fastlocals_w): raise ValueError, "new fastscope is longer than the allocated area" self.fastlocals_w[:len(scope_w)] = scope_w @@ -145,15 +152,15 @@ raise OperationError(space.w_ValueError, space.wrap("f_lineo can only be set by a trace function.")) - if new_lineno < self.code.co_firstlineno: + if new_lineno < self.pycode.co_firstlineno: raise OperationError(space.w_ValueError, space.wrap("line %d comes before the current code." % new_lineno)) - code = self.code.co_code + code = self.pycode.co_code addr = 0 - line = self.code.co_firstlineno + line = self.pycode.co_firstlineno new_lasti = -1 offset = 0 - lnotab = self.code.co_lnotab + lnotab = self.pycode.co_lnotab for offset in xrange(0, len(lnotab), 2): addr += ord(lnotab[offset]) line += ord(lnotab[offset + 1]) @@ -259,11 +266,11 @@ def get_last_lineno(self): "Returns the line number of the instruction currently being executed." - return pytraceback.offset2lineno(self.code, self.next_instr-1) + return pytraceback.offset2lineno(self.pycode, self.next_instr-1) def get_next_lineno(self): "Returns the line number of the next instruction to execute." - return pytraceback.offset2lineno(self.code, self.next_instr) + return pytraceback.offset2lineno(self.pycode, self.next_instr) def fget_f_builtins(space, self): return self.builtin.getdict() Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py Wed Jul 13 19:27:58 2005 @@ -57,7 +57,7 @@ fn(self) def nextop(self): - c = self.code.co_code[self.next_instr] + c = self.pycode.co_code[self.next_instr] self.next_instr += 1 return ord(c) @@ -69,16 +69,16 @@ ### accessor functions ### def getlocalvarname(self, index): - return self.code.co_varnames[index] + return self.pycode.co_varnames[index] def getconstant_w(self, index): - return self.code.co_consts_w[index] + return self.pycode.co_consts_w[index] def getname_u(self, index): - return self.code.co_names[index] + return self.pycode.co_names[index] def getname_w(self, index): - return self.space.wrap(self.code.co_names[index]) + return self.space.wrap(self.pycode.co_names[index]) ################################################################ @@ -113,9 +113,9 @@ # print " varindex:", varindex # print " len(locals_w)", len(f.locals_w) # import dis - # print dis.dis(f.code) - # print "co_varnames", f.code.co_varnames - # print "co_nlocals", f.code.co_nlocals + # print dis.dis(f.pycode) + # print "co_varnames", f.pycode.co_varnames + # print "co_nlocals", f.pycode.co_nlocals # raise def POP_TOP(f): @@ -346,7 +346,7 @@ w_locals = f.valuestack.pop() w_globals = f.valuestack.pop() w_prog = f.valuestack.pop() - flags = f.space.getexecutioncontext().compiler.getcodeflags(f.code) + flags = f.space.getexecutioncontext().compiler.getcodeflags(f.pycode) w_compile_flags = f.space.wrap(flags) w_resulttuple = prepare_exec(f.space, f.space.wrap(f), w_prog, w_globals, w_locals, Modified: pypy/branch/pypy-translation-snapshot/interpreter/pytraceback.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pytraceback.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pytraceback.py Wed Jul 13 19:27:58 2005 @@ -20,9 +20,9 @@ def record_application_traceback(space, operror, frame, last_instruction): - if frame.code.hidden_applevel: + if frame.pycode.hidden_applevel: return - lineno = offset2lineno(frame.code, last_instruction) + lineno = offset2lineno(frame.pycode, last_instruction) tb = operror.application_traceback tb = PyTraceback(space, frame, last_instruction, lineno, tb) operror.application_traceback = tb Modified: pypy/branch/pypy-translation-snapshot/interpreter/test/test_eval.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/test/test_eval.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/test/test_eval.py Wed Jul 13 19:27:58 2005 @@ -13,9 +13,13 @@ class ConcreteFastscopeFrame(Frame): def __init__(self, space, code, numlocals): - Frame.__init__(self, space, code, numlocals=numlocals) + self.code = code + Frame.__init__(self, space, numlocals=numlocals) self.fastlocals_w = [None] * self.numlocals + def getcode(self): + return self.code + def setfastscope(self, scope_w): self.fastlocals_w = scope_w Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Wed Jul 13 19:27:58 2005 @@ -366,7 +366,7 @@ ) Frame.typedef = TypeDef('internal-frame', - f_code = interp_attrproperty('code', cls=Frame), + f_code = GetSetProperty(Frame.fget_code), f_locals = GetSetProperty(Frame.fget_getdictscope), f_globals = interp_attrproperty_w('w_globals', cls=Frame), ) Modified: pypy/branch/pypy-translation-snapshot/module/__builtin__/compiling.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/__builtin__/compiling.py (original) +++ pypy/branch/pypy-translation-snapshot/module/__builtin__/compiling.py Wed Jul 13 19:27:58 2005 @@ -20,7 +20,7 @@ except IndexError: pass else: - flags |= ec.compiler.getcodeflags(caller.code) + flags |= ec.compiler.getcodeflags(caller.getcode()) code = ec.compiler.compile(str_, filename, mode, flags) return space.wrap(code) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/fake.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/fake.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Wed Jul 13 19:27:58 2005 @@ -136,13 +136,20 @@ class CPythonFakeFrame(eval.Frame): + def __init__(self, space, code, w_globals=None, numlocals=-1): + self.fakecode = code + eval.Frame.__init__(self, space, w_globals, numlocals) + + def getcode(self): + return self.fakecode + def setfastscope(self, scope_w): w_args, w_kwds = scope_w try: self.unwrappedargs = self.space.unwrap(w_args) self.unwrappedkwds = self.space.unwrap(w_kwds) except UnwrapError, e: - code = self.code + code = self.fakecode assert isinstance(code, CPythonFakeCode) raise UnwrapError('calling %s: %s' % (code.cpy_callable, e)) @@ -150,7 +157,7 @@ raise OperationError(self.space.w_TypeError, self.space.wrap("cannot get fastscope of a CPythonFakeFrame")) def run(self): - code = self.code + code = self.fakecode assert isinstance(code, CPythonFakeCode) fn = code.cpy_callable try: Modified: pypy/branch/pypy-translation-snapshot/objspace/trace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/trace.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/trace.py Wed Jul 13 19:27:58 2005 @@ -18,7 +18,7 @@ """ bytecode trace. """ def __init__(self, frame): self.frame = frame - self.code = frame.code + self.code = frame.pycode self.index = frame.next_instr class EnterFrame(object): @@ -85,9 +85,9 @@ """ return (possibly cached) pydis result for the given frame. """ try: - return _cache[id(frame.code)] + return _cache[id(frame.pycode)] except KeyError: - res = _cache[id(frame.code)] = pydis.pydis(frame.code) + res = _cache[id(frame.pycode)] = pydis.pydis(frame.pycode) assert res is not None return res From pedronis at codespeak.net Wed Jul 13 19:51:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 19:51:12 +0200 (CEST) Subject: [pypy-svn] r14637 - pypy/dist/pypy/translator/goal Message-ID: <20050713175112.DEDA627B6D@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 19:51:11 2005 New Revision: 14637 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: fixed. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Wed Jul 13 19:51:11 2005 @@ -11,8 +11,4 @@ * how to implement the three overrides of translator/ann_override.py ? - * we get tons of warnings about attributes like 'co_code' that seem to be - erroneously attached to the base 'Code' class, instead of staying on - 'PyCode'. - * the pypy trunk is still not annotable. From pedronis at codespeak.net Wed Jul 13 20:08:36 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 20:08:36 +0200 (CEST) Subject: [pypy-svn] r14639 - in pypy/dist/pypy/rpython: . test Message-ID: <20050713180836.090CA27B6E@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 20:08:33 2005 New Revision: 14639 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rspecialcase.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/rpython/test/test_rspecialcase.py Log: implemented call_specialcase(override:ignore). Conversion from NoneFrozePBCRepr to other reprs. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 13 20:08:33 2005 @@ -157,6 +157,9 @@ class __extend__(pairtype(NoneFrozenPBCRepr, Repr)): + def convert_from_to((_, r_to), v, llops): + return inputconst(r_to, None) + def rtype_is_((rnone1, robj2), hop): return rtype_is_None(robj2, rnone1, hop, pos=1) Modified: pypy/dist/pypy/rpython/rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/rspecialcase.py (original) +++ pypy/dist/pypy/rpython/rspecialcase.py Wed Jul 13 20:08:33 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython import rclass -from pypy.rpython.rmodel import TyperError +from pypy.rpython.rmodel import TyperError, inputconst def rtype_call_specialcase(hop): @@ -24,3 +24,7 @@ # def rtype_override_XXX to be added later + + +def rtype_override_ignore(hop): + return inputconst(hop.r_result, None) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Jul 13 20:08:33 2005 @@ -414,3 +414,30 @@ assert res == 9 res = interpret(f, [3]) assert res == 13 + +def test_conv_from_None(): + class A(object): pass + def none(): + return None + + def f(i): + if i == 1: + return none() + else: + return "ab" + res = interpret(f, [1]) + assert not res + res = interpret(f, [0]) + assert ''.join(res.chars) == "ab" + + def g(i): + if i == 1: + return none() + else: + return A() + res = interpret(g, [1]) + assert not res + res = interpret(g, [0]) + assert res.super.typeptr.name[0] == 'A' + + Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rspecialcase.py (original) +++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Wed Jul 13 20:08:33 2005 @@ -4,4 +4,19 @@ from pypy.translator.ann_override import PyPyAnnotatorPolicy -# nothing to test here at the moment +def test_override_ignore(): + def f(): + pass + f._annspecialcase_ = "override:ignore" + def g(i): + if i == 1: + return "ab" + else: + return f() + + res = interpret(g, [0]) + assert not res + res = interpret(g, [1]) + assert ''.join(res.chars) == "ab" + + From pedronis at codespeak.net Wed Jul 13 20:31:20 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 20:31:20 +0200 (CEST) Subject: [pypy-svn] r14640 - in pypy/dist/pypy/rpython: . test Message-ID: <20050713183120.10DFA27B6E@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 20:31:18 2005 New Revision: 14640 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: implemented widening conversions for ClassesPBCRepr with tests. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 13 20:31:18 2005 @@ -567,6 +567,17 @@ return NotImplemented # good enough for now return v +class __extend__(pairtype(ClassesPBCRepr, ClassesPBCRepr)): + def convert_from_to((r_clspbc1, r_clspbc2), v, llops): + # this check makes sense because both source and dest repr are ClassesPBCRepr + if r_clspbc1.lowleveltype == r_clspbc2.lowleveltype: + return v + if r_clspbc1.lowleveltype == Void: + return inputconst(r_clspbc2, r_clspbc1.s_pbc.const) + return NotImplemented + + + # ____________________________________________________________ def rtype_call_memo(hop): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Jul 13 20:31:18 2005 @@ -441,3 +441,47 @@ assert res.super.typeptr.name[0] == 'A' +def test_conv_from_classpbcset_to_larger(): + class A(object): pass + class B(A): pass + class C(A): pass + + def a(): + return A + def b(): + return B + + + def g(i): + if i == 1: + cls = a() + else: + cls = b() + return cls() + + res = interpret(g, [0]) + assert res.super.typeptr.name[0] == 'B' + res = interpret(g, [1]) + assert res.super.typeptr.name[0] == 'A' + + def bc(j): + if j == 1: + return B + else: + return C + + def g(i, j): + if i == 1: + cls = a() + else: + cls = bc(j) + return cls() + + res = interpret(g, [0, 0]) + assert res.super.typeptr.name[0] == 'C' + res = interpret(g, [0, 1]) + assert res.super.typeptr.name[0] == 'B' + res = interpret(g, [1, 0]) + assert res.super.typeptr.name[0] == 'A' + + From hpk at codespeak.net Wed Jul 13 21:47:54 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 13 Jul 2005 21:47:54 +0200 (CEST) Subject: [pypy-svn] r14643 - pypy/dist/pypy/tool/pytest Message-ID: <20050713194754.AC5AA27B7D@code1.codespeak.net> Author: hpk Date: Wed Jul 13 21:47:54 2005 New Revision: 14643 Modified: pypy/dist/pypy/tool/pytest/htmlreport.py pypy/dist/pypy/tool/pytest/overview.py pypy/dist/pypy/tool/pytest/result.py Log: issue93 testing the testreport pages should now work again. The last problem was the mixture between win32 and posix paths and incorrect sorting between them. The according code in pypy/tool/pytest/ needs to be refactored and generalized (also to allow per-platform/per-python version views) but not now. Modified: pypy/dist/pypy/tool/pytest/htmlreport.py ============================================================================== --- pypy/dist/pypy/tool/pytest/htmlreport.py (original) +++ pypy/dist/pypy/tool/pytest/htmlreport.py Wed Jul 13 21:47:54 2005 @@ -18,6 +18,7 @@ class HtmlReport(object): def __init__(self): self.resultcache = ResultCache() + def parselatest(self): self.resultcache.parselatest() @@ -70,14 +71,13 @@ def render_test_references(self, result): dest = self.make_single_test_result(result) - modified = result.fspath.dirpath().dirpath().basename.startswith('modified') - modified = modified and " [mod]" or "" + modified = result.ismodifiedtest() and " [mod]" or "" return html.div(html.a(result.path.purebasename + modified, href=self.getrelpath(dest)), style="background-color: transparent") def make_single_test_result(self, result): - cache = self.indexpath.dirpath('.cache') + cache = self.indexpath.dirpath('.cache', result['userhost'][:15]) cache.ensure(dir=1) dest = cache.join(result.path.basename).new(ext='.html') doc = ViewResult(result) Modified: pypy/dist/pypy/tool/pytest/overview.py ============================================================================== --- pypy/dist/pypy/tool/pytest/overview.py (original) +++ pypy/dist/pypy/tool/pytest/overview.py Wed Jul 13 21:47:54 2005 @@ -22,7 +22,8 @@ raise TypeError except TypeError: return - name = res.fspath.purebasename + name = res.testname + print name self.name2result.setdefault(name, []).append(res) return res Modified: pypy/dist/pypy/tool/pytest/result.py ============================================================================== --- pypy/dist/pypy/tool/pytest/result.py (original) +++ pypy/dist/pypy/tool/pytest/result.py Wed Jul 13 21:47:54 2005 @@ -89,7 +89,13 @@ if name in self._reprs: value = eval(value) # XXX security self._headers[name] = value - self.fspath = py.path.local(self['fspath']) + self.fspath = self['fspath'] + if self['platform'] == 'win32' and '\\' in self.fspath: + self.testname = self.fspath.split('\\')[-1] + else: + self.testname = self.fspath.split('/')[-1] + #if sys.platform != 'win32' and '\\' in self.fspath: + # self.fspath = py.path.local(self['fspath'].replace('\\' self.path = path payload = msg.get_payload() @@ -99,6 +105,11 @@ fn = submsg.get_filename() assert fn self.addnamedtext(fn, submsg.get_payload()) + + def ismodifiedtest(self): + # XXX we need proper cross-platform paths! + return 'modified' in self.fspath + def __repr__(self): return '<%s (%s) %r rev=%s>' %(self.__class__.__name__, self['outcome'], From pedronis at codespeak.net Wed Jul 13 22:02:11 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Jul 2005 22:02:11 +0200 (CEST) Subject: [pypy-svn] r14644 - in pypy/dist/pypy/rpython: . test Message-ID: <20050713200211.5B67D27B80@code1.codespeak.net> Author: pedronis Date: Wed Jul 13 22:02:05 2005 New Revision: 14644 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_robject.py Log: * added support for operations on pyobjects (ptrs) in llinterp (with some simple tests) * extended interpret interface with a flag someobjects wich if True will pass to annotation SomeObjects for the arguments that are of type Ptr(PyObject) * special case dicts with SomeObject keys and values to be just treated as SomeObjects with a test - fixed problem about pyobject ops returning void instead of pyobjects in robject. - added _callable to some gencapis so that they can be used when testing with llinterp. This is a stop-gap solutuin. We likely want to refactor gencapi using the external function table. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Jul 13 22:02:05 2005 @@ -3,7 +3,7 @@ from pypy.objspace.flow.model import Constant, Variable, last_exception from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck import py -from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer +from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer, PyObject, pyobjectptr from pypy.rpython.lltype import Array import math @@ -28,6 +28,12 @@ llframe = LLFrame(graph, args, self) return llframe.eval() +# implementations of ops from flow.operation +from pypy.objspace.flow.operation import FunctionByName +opimpls = FunctionByName.copy() +opimpls['is_true'] = bool + + class LLFrame(object): def __init__(self, graph, args, llinterpreter): self.graph = graph @@ -289,11 +295,21 @@ assert type(c) is float return math.fmod(b,c) + # operations on pyobjects! + for opname in opimpls.keys(): + exec py.code.Source(""" + def op_%(opname)s(self, *pyobjs): + for pyo in pyobjs: + assert typeOf(pyo) == Ptr(PyObject) + func = opimpls[%(opname)r] + return pyobjectptr(func(*[pyo._obj.value for pyo in pyobjs])) + """ % locals()).compile() + del opname + + + # __________________________________________________________ # primitive operations -from pypy.objspace.flow.operation import FunctionByName -opimpls = FunctionByName.copy() -opimpls['is_true'] = bool ops_returning_a_bool = {'gt': True, 'ge': True, 'lt': True, 'le': True, 'eq': True, 'ne': True, Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Wed Jul 13 22:02:05 2005 @@ -54,7 +54,9 @@ class __extend__(pairtype(PyObjRepr, BoolRepr)): def convert_from_to((r_from, r_to), v, llops): if r_to.lowleveltype == Bool: - return llops.gencapicall('PyObject_IsTrue', [v], resulttype=Bool) + # xxx put in table + return llops.gencapicall('PyObject_IsTrue', [v], resulttype=Bool, + _callable=lambda pyo: bool(pyo._obj.value)) return NotImplemented class __extend__(pairtype(BoolRepr, PyObjRepr)): Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Wed Jul 13 22:02:05 2005 @@ -4,6 +4,7 @@ from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rarithmetic import r_uint from pypy.rpython import rlist, rconstantdict, remptydict +from pypy.rpython import robject # ____________________________________________________________ # @@ -25,7 +26,8 @@ class __extend__(annmodel.SomeDict): def rtyper_makerepr(self, rtyper): - s_key = self.dictdef.dictkey.s_value + s_key = self.dictdef.dictkey.s_value + s_value = self.dictdef.dictvalue.s_value if isinstance(s_key, annmodel.SomeString): if s_key.can_be_none(): raise rmodel.TyperError("cannot make repr of dict with " @@ -41,6 +43,9 @@ rtyper.getrepr(dictvalue.s_value)) elif isinstance(s_key, annmodel.SomeImpossibleValue): return remptydict.EmptyDictRepr() + elif (s_key.__class__ is annmodel.SomeObject and s_key.knowntype == object and + s_value.__class__ is annmodel.SomeObject and s_value.knowntype == object): + return robject.pyobj_repr else: raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) @@ -284,6 +289,8 @@ def rtype_newdict(hop): r_dict = hop.r_result + if r_dict == robject.pyobj_repr: # special case: SomeObject: SomeObject dicts! + return hop.inputconst(robject.pyobj_repr, {}) if not isinstance(r_dict, StrDictRepr): raise rmodel.TyperError("cannot create non-StrDicts, got %r" %(r_dict,)) c1 = hop.inputconst(lltype.Void, r_dict.lowleveltype) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Wed Jul 13 22:02:05 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.objspace import op_appendices from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \ - UniChar, GcArray, malloc, Array + UniChar, GcArray, malloc, Array, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \ inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -374,6 +374,7 @@ return llops.gencapicall('PyLong_FromUnsignedLong', [v], resulttype=pyobj_repr) if r_from.lowleveltype == Signed: + # xxx put in table return llops.gencapicall('PyInt_FromLong', [v], - resulttype=pyobj_repr) + resulttype=pyobj_repr, _callable = lambda i: pyobjectptr(i)) return NotImplemented Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Wed Jul 13 22:02:05 2005 @@ -49,8 +49,11 @@ def make_operation(opname, cls=PyObjRepr): def rtype_op(_, hop): vlist = hop.inputargs(*([pyobj_repr]*hop.nb_args)) - v = hop.genop(opname, vlist, resulttype = pyobj_repr) - return hop.llops.convertvar(v, pyobj_repr, hop.r_result) + if isinstance(hop.r_result, VoidRepr): + hop.genop(opname, vlist) + else: + v = hop.genop(opname, vlist, resulttype=pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, hop.r_result) funcname = 'rtype_' + opname func = func_with_new_name(rtype_op, funcname) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jul 13 22:02:05 2005 @@ -11,7 +11,7 @@ from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.rslice import minusone_slice_repr from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc -from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf +from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf, pyobjectptr from pypy.rpython.rclass import InstanceRepr @@ -451,9 +451,11 @@ 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) + resulttype=pyobj_repr, + _callable= lambda chars, sz: pyobjectptr(''.join(chars))) # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jul 13 22:02:05 2005 @@ -586,7 +586,7 @@ return self.genop('direct_call', [cf]+list(args_v), resulttype) def gencapicall(self, cfnname, args_v, resulttype=None, **flags): - return self.genexternalcall(cfnname, args_v, resulttype=resulttype, external="C") + return self.genexternalcall(cfnname, args_v, resulttype=resulttype, external="C", **flags) # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations 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 Wed Jul 13 22:02:05 2005 @@ -1,6 +1,6 @@ import py -from pypy.rpython.lltype import typeOf,pyobjectptr +from pypy.rpython.lltype import typeOf, pyobjectptr, Ptr, PyObject from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.llinterp import LLInterpreter, LLException,log from pypy.translator.translator import Translator @@ -52,12 +52,19 @@ _lastinterpreted = [] _tcache = {} -def interpret(func, values, view=False, viewbefore=False, policy=None): - key = (func,) + tuple([typeOf(x) for x in values]) +def interpret(func, values, view=False, viewbefore=False, policy=None, someobjects=False): + key = (func,) + tuple([typeOf(x) for x in values])+ (someobjects,) try: (t, interp) = _tcache[key] - except KeyError: - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) + except KeyError: + def annotation(x): + T = typeOf(x) + if T == Ptr(PyObject) and someobjects: + return object + else: + return lltype_to_annotation(T) + + t, typer = gengraph(func, [annotation(x) for x in values], viewbefore, policy) interp = LLInterpreter(t.flowgraphs, typer) _tcache[key] = (t, interp) @@ -231,6 +238,21 @@ return [l1,l2,l3] res = interpret(f,[]) assert len(res.items) == 3 + +def test_obj_obj_add(): + def f(x,y): + return x+y + _1L = pyobjectptr(1L) + _2L = pyobjectptr(2L) + res = interpret(f, [_1L, _2L], someobjects=True) + assert res._obj.value == 3L + +def test_obj_obj_is(): + def f(x,y): + return x is y + o = pyobjectptr(object()) + res = interpret(f, [o, o], someobjects=True) + assert res is True #__________________________________________________________________ # Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Wed Jul 13 22:02:05 2005 @@ -1,16 +1,22 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * +from pypy.rpython.test.test_llinterp import interpret -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - t.specialize() - t.checkgraphs() - return t - - -def test_set_del_item(): - def dummyfn(obj): +def test_simple(): + def fn(obj): return obj + 1 - rtype(dummyfn, [object]) + _1L = pyobjectptr(1L) + res = interpret(fn, [_1L], someobjects=True) + assert res._obj.value == 2L + +def test_obj_obj_dict(): + def f(i, c): + d = {} + d[1] = 'a' + d['a'] = i + d['ab'] = c + return d + res = interpret(f, [1, 'c']) + print res + From pedronis at codespeak.net Thu Jul 14 03:29:30 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 03:29:30 +0200 (CEST) Subject: [pypy-svn] r14654 - in pypy/dist/pypy/objspace/flow: . test Message-ID: <20050714012930.B770E27B68@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 03:29:28 2005 New Revision: 14654 Modified: pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/test/test_objspace.py Log: flowspace was looping forever on g(1,*(2,3)). fix with test. Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Thu Jul 14 03:29:28 2005 @@ -271,6 +271,11 @@ return result def unpackiterable(self, w_iterable, expected_length=None): + if not isinstance(w_iterable, Variable): + l = list(self.unwrap(w_iterable)) + if expected_length is not None and len(l) != expected_length: + raise ValueError + return [self.wrap(x) for x in l] if isinstance(w_iterable, Variable) and expected_length is None: raise UnwrapException, ("cannot unpack a Variable iterable" "without knowing its length") Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Thu Jul 14 03:29:28 2005 @@ -555,6 +555,23 @@ traverse(visit, graph) assert results == [Constant(4)] + def test_const_star_call(self): + def g(a=1,b=2,c=3): + pass + def f(): + return g(1,*(2,3)) + graph = self.codetest(f) + call_args = [] + def visit(block): + if isinstance(block, Block): + for op in block.operations: + if op.opname == "call_args": + call_args.append(op) + traverse(visit, graph) + assert not call_args + + + DATA = {'x': 5, 'y': 6} From pedronis at codespeak.net Thu Jul 14 03:31:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 03:31:13 +0200 (CEST) Subject: [pypy-svn] r14655 - in pypy/dist/pypy/rpython: . test Message-ID: <20050714013113.E5DD027B68@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 03:31:12 2005 New Revision: 14655 Added: pypy/dist/pypy/rpython/callparse.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: refactor to reuse argument.py logic in rtyping of simple_call and call_args. Support for call_args for non-normalized cases, with tests. Added: pypy/dist/pypy/rpython/callparse.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/callparse.py Thu Jul 14 03:31:12 2005 @@ -0,0 +1,151 @@ +from pypy.interpreter.pycode import cpython_code_signature +from pypy.interpreter.argument import Arguments, ArgErr +from pypy.annotation import model as annmodel +from pypy.rpython import rtuple + +class CallPatternTooComplex(Exception): + pass + + +# for parsing call arguments +class RPythonCallsSpace: + """Pseudo Object Space providing almost no real operation. + For the Arguments class: if it really needs other operations, it means + that the call pattern is too complex for R-Python. + """ + def newtuple(self, items): + return NewTupleHolder(items) + + def newdict(self, stuff): + raise CallPatternTooComplex, "'**' argument" + + def unpackiterable(self, it, expected_length=None): + if it.is_tuple(): + items = it.items() + if (expected_length is not None and + expected_length != len(items)): + raise ValueError + return items + raise CallPatternTooComplex, "'*' argument must be a tuple" + + +def callparse(op, func, rinputs, hop): + space = RPythonCallsSpace() + def args_h(start): + return [VarHolder(i, hop.args_s[i]) for i in range(start, hop.nb_args)] + if op == "simple_call": + arguments = Arguments(space, args_h(1)) + elif op == "call_args": + arguments = Arguments.fromshape(space, hop.args_s[1].const, # shape + args_h(2)) + # parse the arguments according to the function we are calling + signature = cpython_code_signature(func.func_code) + defs_h = [] + if func.func_defaults: + for x in func.func_defaults: + defs_h.append(ConstHolder(x)) + try: + holders = arguments.match_signature(signature, defs_h) + except ArgErr, e: + raise TypeError, "signature mismatch: %s" % e.getmsg(arguments, func.__name__) + + assert len(holders) == len(rinputs), "argument parsing mismatch" + vlist = [] + for h,r in zip(holders, rinputs): + v = h.emit(r, hop) + vlist.append(v) + return vlist + + +class Holder(object): + + def is_tuple(self): + return False + + def emit(self, repr, hop): + try: + cache = self._cache + except AttributeError: + cache = self._cache = {} + try: + return cache[repr] + except KeyError: + v = self._emit(repr, hop) + cache[repr] = v + return v + + +class VarHolder(Holder): + + def __init__(self, num, s_obj): + self.num = num + self.s_obj = s_obj + + def is_tuple(self): + return isinstance(self.s_obj, annmodel.SomeTuple) + + def items(self): + assert self.is_tuple() + n = len(self.s_obj.items) + return tuple([ItemHolder(self, i) for i in range(n)]) + + def _emit(self, repr, hop): + return hop.inputarg(repr, arg=self.num) + + def access(self, hop): + repr = hop.args_r[self.num] + return repr, self.emit(repr, hop) + +class ConstHolder(Holder): + def __init__(self, value): + self.value = value + + def is_tuple(self): + return type(self.value) is tuple + + def items(self): + assert self.is_tuple() + return self.value + + def _emit(self, repr, hop): + return hop.inputconst(repr, self.value) + + +class NewTupleHolder(Holder): + def __new__(cls, holders): + for h in holders: + if not isinstance(h, ItemHolder) or not h.holder == holders[0].holder: + break + else: + if 0 < len(holders) == len(holders[0].holder.items()): + return h[0].holder + inst = Holder.__new__(cls) + inst.holders = tuple(holders) + return inst + + def is_tuple(self): + return True + + def items(self): + return self.holders + + def _emit(self, repr, hop): + assert isinstance(repr, rtuple.TupleRepr) + tupleitems_v = [] + for h in self.holders: + v = h.emit(repr.items_r[len(tupleitems_v)], hop) + tupleitems_v.append(v) + vtuple = rtuple.newtuple(hop.llops, repr, tupleitems_v) + return vtuple + + +class ItemHolder(Holder): + def __init__(self, holder, index): + self.holder = holder + self.index = index + + def _emit(self, repr, hop): + index = self.index + r_tup, v_tuple = self.holder.access(hop) + v = r_tup.getitem(hop, v_tuple, index) + return hop.llops.convertvar(v, r_tup.items_r[index], repr) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Jul 14 03:31:12 2005 @@ -12,6 +12,8 @@ from pypy.rpython import rtuple from pypy.tool.sourcetools import has_varargs +from pypy.rpython import callparse + class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): # for now, we require that the PBC fits neatly into one of the Repr @@ -340,7 +342,7 @@ f, rinputs, rresult = self.function_signatures()[value] return f - def rtype_simple_call(self, hop): + def PREVIOUS_rtype_simple_call(self, hop): f, rinputs, rresult = self.function_signatures().itervalues().next() extravlist = [] if getattr(f._obj.graph, 'normalized_for_calls', False): @@ -386,15 +388,44 @@ v = hop.genop('direct_call', vlist, resulttype = rresult) return hop.llops.convertvar(v, rresult, hop.r_result) + def rtype_simple_call(self, hop): + f, rinputs, rresult = self.function_signatures().itervalues().next() + + if getattr(f._obj.graph, 'normalized_for_calls', False): + # should not have an argument count mismatch + assert len(rinputs) == hop.nb_args-1, "normalization bug" + vlist = hop.inputargs(self, *rinputs) + else: + # if not normalized, should be a call to a known function + assert len(self.function_signatures()) == 1, "normalization bug" + func, = self.function_signatures().keys() + vlist = [hop.inputarg(self, arg=0)] + vlist += callparse.callparse('simple_call', func, rinputs, hop) + + return self.call(hop, f, vlist, rresult) + + def call(self, hop, f, vlist, rresult): + if self.lowleveltype == Void: + assert len(self.function_signatures()) == 1 + vlist[0] = hop.inputconst(typeOf(f), f) + v = hop.genop('direct_call', vlist, resulttype = rresult) + return hop.llops.convertvar(v, rresult, hop.r_result) + def rtype_call_args(self, hop): f, rinputs, rresult = self.function_signatures().itervalues().next() # the function arguments may have been normalized by normalizecalls() # already - if not getattr(f._obj.graph, 'normalized_for_calls', False): - assert False, "XXX do stuff here" - vlist = hop.inputargs(self, Void, *rinputs) - return hop.genop('direct_call', vlist[:1] + vlist[2:], - resulttype = rresult) + if getattr(f._obj.graph, 'normalized_for_calls', False): + vlist = hop.inputargs(self, Void, *rinputs) + vlist = vlist[:1] + vlist[2:] + else: + # if not normalized, should be a call to a known function + assert len(self.function_signatures()) == 1, "normalization bug" + func, = self.function_signatures().keys() + vlist = [hop.inputarg(self, arg=0)] + vlist += callparse.callparse('call_args', func, rinputs, hop) + + return self.call(hop, f, vlist, rresult) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Thu Jul 14 03:31:12 2005 @@ -70,6 +70,13 @@ return Length1TupleIteratorRepr(self) raise TyperError("can only iterate over tuples of length 1 for now") + def getitem(self, llops, v_tuple, index): + name = self.fieldnames[index] + llresult = self.lltypes[index] + cname = inputconst(Void, name) + return llops.genop('getfield', [v_tuple, cname], resulttype = llresult) + + class __extend__(pairtype(TupleRepr, Repr)): def rtype_contains((r_tup, r_item), hop): v_tup = hop.args_v[0] @@ -98,10 +105,7 @@ if not isinstance(v_index, Constant): raise TyperError("non-constant tuple index") index = v_index.value - name = r_tup.fieldnames[index] - llresult = r_tup.lltypes[index] - cname = hop.inputconst(Void, name) - return hop.genop('getfield', [v_tuple, cname], resulttype = llresult) + return r_tup.getitem(hop.llops, v_tuple, index) class __extend__(pairtype(TupleRepr, TupleRepr)): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Thu Jul 14 03:31:12 2005 @@ -484,4 +484,128 @@ res = interpret(g, [1, 0]) assert res.super.typeptr.name[0] == 'A' - +def test_call_keywords(): + def g(a=1, b=2, c=3): + return 100*a+10*b+c + + def f(i): + if i == 0: + return g(a=7) + elif i == 1: + return g(b=11) + elif i == 2: + return g(c=13) + elif i == 3: + return g(a=7, b=11) + elif i == 4: + return g(b=7, a=11) + elif i == 5: + return g(a=7, c=13) + elif i == 6: + return g(c=7, a=13) + elif i == 7: + return g(a=7,b=11,c=13) + elif i == 8: + return g(a=7,c=11,b=13) + elif i == 9: + return g(b=7,a=11,c=13) + else: + return g(b=7,c=11,a=13) + + for i in range(11): + res = interpret(f, [i]) + assert res == f(i) + +def test_call_star_and_keywords(): + def g(a=1, b=2, c=3): + return 100*a+10*b+c + + def f(i, x): + if x == 1: + j = 11 + else: + j = 22 + if i == 0: + return g(7) + elif i == 1: + return g(7,*(j,)) + elif i == 2: + return g(7,*(11,j)) + elif i == 3: + return g(a=7) + elif i == 4: + return g(b=7, *(j,)) + elif i == 5: + return g(b=7, c=13, *(j,)) + elif i == 6: + return g(c=7, b=13, *(j,)) + elif i == 7: + return g(c=7,*(j,)) + elif i == 8: + return g(c=7,*(11,j)) + else: + return 0 + + for i in range(9): + for x in range(1): + res = interpret(f, [i, x]) + assert res == f(i, x) + +def test_call_star_and_keywords_starargs(): + def g(a=1, b=2, c=3, *rest): + return 1000*len(rest)+100*a+10*b+c + + def f(i, x): + if x == 1: + j = 13 + else: + j = 31 + if i == 0: + return g() + elif i == 1: + return g(*(j,)) + elif i == 2: + return g(*(13, j)) + elif i == 3: + return g(*(13, j, 19)) + elif i == 4: + return g(*(13, j, 19, 21)) + elif i == 5: + return g(7) + elif i == 6: + return g(7, *(j,)) + elif i == 7: + return g(7, *(13, j)) + elif i == 8: + return g(7, *(13, 17, j)) + elif i == 9: + return g(7, *(13, 17, j, 21)) + elif i == 10: + return g(7, 9) + elif i == 11: + return g(7, 9, *(j,)) + elif i == 12: + return g(7, 9, *(j, 17)) + elif i == 13: + return g(7, 9, *(13, j, 19)) + elif i == 14: + return g(7, 9, 11) + elif i == 15: + return g(7, 9, 11, *(j,)) + elif i == 16: + return g(7, 9, 11, *(13, j)) + elif i == 17: + return g(7, 9, 11, *(13, 17, j)) + elif i == 18: + return g(7, 9, 11, 2) + elif i == 19: + return g(7, 9, 11, 2, *(j,)) + elif i == 20: + return g(7, 9, 11, 2, *(13, j)) + else: + return 0 + + for i in range(21): + for x in range(1): + res = interpret(f, [i, x]) + assert res == f(i, x) From ac at codespeak.net Thu Jul 14 11:15:06 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 14 Jul 2005 11:15:06 +0200 (CEST) Subject: [pypy-svn] r14656 - pypy/dist/pypy/module/unicodedata Message-ID: <20050714091506.6085127B58@code1.codespeak.net> Author: ac Date: Thu Jul 14 11:14:37 2005 New Revision: 14656 Modified: pypy/dist/pypy/module/unicodedata/function.py Log: Fix missplaced ']'. Modified: pypy/dist/pypy/module/unicodedata/function.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/function.py (original) +++ pypy/dist/pypy/module/unicodedata/function.py Thu Jul 14 11:14:37 2005 @@ -136,14 +136,14 @@ T = TBase + SIndex % TCount; if T == TBase: if j + 2 > resultlen: - result.extend([0 * (j + 2 - resultlen + 10)]) + result.extend([0] * (j + 2 - resultlen + 10)) resultlen = len(result) result[j] = L result[j + 1] = V j += 2 else: if j + 3 > resultlen: - result.extend([0 * (j + 3 - resultlen + 10)]) + result.extend([0] * (j + 3 - resultlen + 10)) resultlen = len(result) result[j] = L result[j + 1] = V @@ -154,14 +154,14 @@ if decomp: decomplen = len(decomp) if j + decomplen > resultlen: - result.extend([0 * (j + decomplen - resultlen + 10)]) + result.extend([0] * (j + decomplen - resultlen + 10)) resultlen = len(result) for ch in decomp: result[j] = ch j += 1 else: if j + 1 > resultlen: - result.extend([0 * (j + 1 - resultlen + 10)]) + result.extend([0] * (j + 1 - resultlen + 10)) resultlen = len(result) result[j] = ch j += 1 From pedronis at codespeak.net Thu Jul 14 12:42:46 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 12:42:46 +0200 (CEST) Subject: [pypy-svn] r14659 - pypy/dist/pypy/rpython Message-ID: <20050714104246.353BB27B64@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 12:42:45 2005 New Revision: 14659 Modified: pypy/dist/pypy/rpython/rpbc.py Log: oops, remove disabled/not-used code Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Jul 14 12:42:45 2005 @@ -342,52 +342,6 @@ f, rinputs, rresult = self.function_signatures()[value] return f - def PREVIOUS_rtype_simple_call(self, hop): - f, rinputs, rresult = self.function_signatures().itervalues().next() - extravlist = [] - if getattr(f._obj.graph, 'normalized_for_calls', False): - # should not have an argument count mismatch - assert len(rinputs) == hop.nb_args-1, "normalization bug" - else: - # if not normalized, should be a call to a known function - assert len(self.function_signatures()) == 1, "normalization bug" - func, = self.function_signatures().keys() - if has_varargs(func): - # collect the arguments for '*arg' into a tuple - rstar = rinputs[-1] - rinputs = rinputs[:-1] - assert isinstance(rstar, rtuple.TupleRepr) - tupleitems_v = [] - for i in range(1+len(rinputs), hop.nb_args): - v = hop.inputarg(rstar.items_r[len(tupleitems_v)], arg=i) - tupleitems_v.append(v) - vtuple = rtuple.newtuple(hop.llops, rstar, tupleitems_v) - extravlist.append(vtuple) - hop = hop.copy() - del hop.args_v[1+len(rinputs):] - del hop.args_s[1+len(rinputs):] - del hop.args_r[1+len(rinputs):] - hop.nb_args = len(hop.args_v) - - defaults = func.func_defaults or () - if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs): - rinputs = list(rinputs) - defaults = list(defaults) - while len(rinputs) > hop.nb_args-1: - c = hop.inputconst(rinputs.pop(), defaults.pop()) - extravlist.insert(0, c) - else: - if hop.nb_args-1 > len(rinputs): - raise TyperError("too many arguments in function call") - else: - raise TyperError("not enough arguments in function call") - vlist = hop.inputargs(self, *rinputs) + extravlist - if self.lowleveltype == Void: - assert len(self.function_signatures()) == 1 - vlist[0] = hop.inputconst(typeOf(f), f) - v = hop.genop('direct_call', vlist, resulttype = rresult) - return hop.llops.convertvar(v, rresult, hop.r_result) - def rtype_simple_call(self, hop): f, rinputs, rresult = self.function_signatures().itervalues().next() From pedronis at codespeak.net Thu Jul 14 12:51:23 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 12:51:23 +0200 (CEST) Subject: [pypy-svn] r14660 - pypy/dist/pypy/translator/goal Message-ID: <20050714105123.2E80227B64@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 12:51:22 2005 New Revision: 14660 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: call_args support added Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 14 12:51:22 2005 @@ -7,8 +7,6 @@ * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. - * 'call_args' needs to be implemented in rpbc.py. - * how to implement the three overrides of translator/ann_override.py ? * the pypy trunk is still not annotable. From tismer at codespeak.net Thu Jul 14 13:34:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 14 Jul 2005 13:34:02 +0200 (CEST) Subject: [pypy-svn] r14661 - pypy/dist/pypy/translator/goal Message-ID: <20050714113402.EBCF027B64@code1.codespeak.net> Author: tismer Date: Thu Jul 14 13:34:02 2005 New Revision: 14661 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: RTYPERSEED documentation Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 14 13:34:02 2005 @@ -10,3 +10,13 @@ * how to implement the three overrides of translator/ann_override.py ? * the pypy trunk is still not annotable. + +How to work in parallel: +There is an environment variable to be set with your personal random seed. +Seeds taken so far are +Armin: 42, Samuele: 46, Chris: 49 +Under Windows, use +SET RTYPERSEED=xx +where xx is your seed. When you run translate_pypy, you will get a message +with your seed, if everything is fine. The purpose of the seed is to +shuffle the annotated blocks, in order to create different errors. From pedronis at codespeak.net Thu Jul 14 19:00:47 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 19:00:47 +0200 (CEST) Subject: [pypy-svn] r14672 - in pypy/dist/pypy/rpython: . test Message-ID: <20050714170047.417BE27B66@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 19:00:29 2005 New Revision: 14672 Modified: pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: tuple conversions with test Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Thu Jul 14 19:00:29 2005 @@ -117,7 +117,19 @@ return newtuple(hop.llops, res, vlist) rtype_inplace_add = rtype_add - + def convert_from_to((r_from, r_to), v, llops): + if len(r_from.items_r) == len(r_to.items_r): + n = len(r_from.items_r) + items_v = [] + for i in range(n): + item_v = r_from.getitem(llops, v, i) + item_v = llops.convertvar(item_v, + r_from.items_r[i], + r_to.items_r[i]) + items_v.append(item_v) + return newtuple(llops, r_to, items_v) + return NotImplemented + # ____________________________________________________________ # # Irregular operations. Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Thu Jul 14 19:00:29 2005 @@ -86,3 +86,21 @@ return total res = interpret(f, [93813]) assert res == 93813 + +def test_conv(): + def t0(): + return (3, 2, None) + def t1(): + return (7, 2, "xy") + def f(i): + if i == 1: + return t1() + else: + return t0() + + res = interpret(f, [1]) + assert res.item0 == 7 + assert isinstance(typeOf(res.item2), Ptr) and ''.join(res.item2.chars) == "xy" + res = interpret(f, [0]) + assert res.item0 == 3 + assert isinstance(typeOf(res.item2), Ptr) and not res.item2 From pedronis at codespeak.net Thu Jul 14 19:10:21 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 19:10:21 +0200 (CEST) Subject: [pypy-svn] r14673 - pypy/dist/pypy/translator/goal Message-ID: <20050714171021.28F8F27B6A@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 19:10:15 2005 New Revision: 14673 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: some new issues seen Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 14 19:10:15 2005 @@ -4,6 +4,11 @@ Let's list and update here the issues that will show up, or have shown up already sometime ago, while running translate_pypy:: + * we need a call_args similar to simple_call (doing redispatching) + on MethodOfFrozenPBCRepr + + * isinstance(SomeObject, _), needed by wrap__object + * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From pedronis at codespeak.net Thu Jul 14 19:24:56 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Jul 2005 19:24:56 +0200 (CEST) Subject: [pypy-svn] r14674 - pypy/dist/pypy/translator/goal Message-ID: <20050714172456.2999D27B6A@code1.codespeak.net> Author: pedronis Date: Thu Jul 14 19:24:18 2005 New Revision: 14674 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: other new issue Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 14 19:24:18 2005 @@ -9,6 +9,8 @@ * isinstance(SomeObject, _), needed by wrap__object + * is (and conversion) + * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From hpk at codespeak.net Thu Jul 14 21:35:04 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 14 Jul 2005 21:35:04 +0200 (CEST) Subject: [pypy-svn] r14678 - pypy/extradoc/minute Message-ID: <20050714193504.3327427B5E@code1.codespeak.net> Author: hpk Date: Thu Jul 14 21:34:14 2005 New Revision: 14678 Added: pypy/extradoc/minute/ pypy/extradoc/minute/pypy-sync-07-14.txt - copied unchanged from r14676, pypy/eu-tracking/minute/pypy-sync-07-14.txt Log: moved the pypy-sync meeting minutes to extradoc because they should always be quite public in contrary to technical board and consortium meetings. From ac at codespeak.net Fri Jul 15 10:54:33 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 10:54:33 +0200 (CEST) Subject: [pypy-svn] r14684 - pypy/dist/pypy/objspace/std Message-ID: <20050715085433.8E5C927B5E@code1.codespeak.net> Author: ac Date: Fri Jul 15 10:54:33 2005 New Revision: 14684 Modified: pypy/dist/pypy/objspace/std/listobject.py Log: Only use range() in a for-statement. Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jul 15 10:54:33 2005 @@ -331,7 +331,6 @@ "assign sequence of size %d to extended slice of size %d" % (len2,slicelength))) - r = range(len2) items = w_list.ob_item if sequence2 is items: if step > 0: @@ -342,7 +341,7 @@ else: # Make a shallow copy to more easily handle the reversal case sequence2 = list(sequence2) - for i in r: + for i in range(len2): items[start+i*step] = sequence2[i] return space.w_None From ac at codespeak.net Fri Jul 15 10:56:10 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 10:56:10 +0200 (CEST) Subject: [pypy-svn] r14685 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050715085610.3D63227B5E@code1.codespeak.net> Author: ac Date: Fri Jul 15 10:56:09 2005 New Revision: 14685 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Log: Merge 14684 from trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Fri Jul 15 10:56:09 2005 @@ -331,7 +331,6 @@ "assign sequence of size %d to extended slice of size %d" % (len2,slicelength))) - r = range(len2) items = w_list.ob_item if sequence2 is items: if step > 0: @@ -342,7 +341,7 @@ else: # Make a shallow copy to more easily handle the reversal case sequence2 = list(sequence2) - for i in r: + for i in range(len2): items[start+i*step] = sequence2[i] return space.w_None From ac at codespeak.net Fri Jul 15 11:37:22 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 11:37:22 +0200 (CEST) Subject: [pypy-svn] r14688 - pypy/dist/pypy/objspace/std Message-ID: <20050715093722.A3BE027B66@code1.codespeak.net> Author: ac Date: Fri Jul 15 11:37:22 2005 New Revision: 14688 Modified: pypy/dist/pypy/objspace/std/listobject.py Log: Oops. Last fix needed a more complex solution. Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jul 15 11:37:22 2005 @@ -337,7 +337,9 @@ # Always copy starting from the right to avoid # having to make a shallow copy in the case where # the source and destination lists are the same list. - r.reverse() + for i in range(len2 - 1, -1, -1): + items[start+i*step] = sequence2[i] + return space.w_None else: # Make a shallow copy to more easily handle the reversal case sequence2 = list(sequence2) From ac at codespeak.net Fri Jul 15 11:38:14 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 11:38:14 +0200 (CEST) Subject: [pypy-svn] r14689 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050715093814.721A927B66@code1.codespeak.net> Author: ac Date: Fri Jul 15 11:38:14 2005 New Revision: 14689 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Log: Merge 14688 from trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Fri Jul 15 11:38:14 2005 @@ -337,7 +337,9 @@ # Always copy starting from the right to avoid # having to make a shallow copy in the case where # the source and destination lists are the same list. - r.reverse() + for i in range(len2 - 1, -1, -1): + items[start+i*step] = sequence2[i] + return space.w_None else: # Make a shallow copy to more easily handle the reversal case sequence2 = list(sequence2) From ac at codespeak.net Fri Jul 15 11:39:55 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 11:39:55 +0200 (CEST) Subject: [pypy-svn] r14690 - pypy/dist/pypy/translator/goal Message-ID: <20050715093955.5F04927B66@code1.codespeak.net> Author: ac Date: Fri Jul 15 11:39:55 2005 New Revision: 14690 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: Claim a seed value. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 15 11:39:55 2005 @@ -21,7 +21,7 @@ How to work in parallel: There is an environment variable to be set with your personal random seed. Seeds taken so far are -Armin: 42, Samuele: 46, Chris: 49 +Armin: 42, Samuele: 46, Chris: 49, Arre: 97 Under Windows, use SET RTYPERSEED=xx where xx is your seed. When you run translate_pypy, you will get a message From mwh at codespeak.net Fri Jul 15 12:05:43 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Jul 2005 12:05:43 +0200 (CEST) Subject: [pypy-svn] r14692 - pypy/dist/pypy/lib Message-ID: <20050715100543.E58A527B66@code1.codespeak.net> Author: mwh Date: Fri Jul 15 12:05:42 2005 New Revision: 14692 Modified: pypy/dist/pypy/lib/_formatting.py Log: grotesque code for testing for nans and infs (no tests, but a quick check on windows both with 2.3 and 2.4 would be much appreciated). use this to print nans and infs as "nan" and "inf", respectively. Modified: pypy/dist/pypy/lib/_formatting.py ============================================================================== --- pypy/dist/pypy/lib/_formatting.py (original) +++ pypy/dist/pypy/lib/_formatting.py Fri Jul 15 12:05:42 2005 @@ -193,6 +193,16 @@ return floater() +# isinf isn't too hard... +def isinf(v): + return v != 0 and v*2.0 == v + +# To get isnan, working x-platform and both on 2.3 and 2.4, is a +# horror. I think this works (for reasons I don't really want to talk +# about), and probably when implemented on top of pypy, too. +def isnan(v): + return v != v*1.0 or (v == 1.0 and v == 2.0) + from _float_formatting import flonum2digits class FloatFormatter(Formatter): @@ -221,6 +231,10 @@ def format(self): v = maybe_float(self.value) + if isnan(v): + return 'nan' + elif isinf(v): + return 'inf' v, sign = self.numeric_preprocess(v) if self.prec is None: self.prec = 6 From ac at codespeak.net Fri Jul 15 14:20:53 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 14:20:53 +0200 (CEST) Subject: [pypy-svn] r14695 - pypy/dist/pypy/objspace/std Message-ID: <20050715122053.9764C27B66@code1.codespeak.net> Author: ac Date: Fri Jul 15 14:20:53 2005 New Revision: 14695 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: Do not iterate over a tuple. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Jul 15 14:20:53 2005 @@ -205,7 +205,7 @@ if isinstance(x, float): return W_FloatObject(self, x) if isinstance(x, tuple): - wrappeditems = [self.wrap(item) for item in x] + wrappeditems = [self.wrap(item) for item in list(x)] return W_TupleObject(self, wrappeditems) if isinstance(x, list): wrappeditems = [self.wrap(item) for item in x] From ac at codespeak.net Fri Jul 15 14:21:28 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Jul 2005 14:21:28 +0200 (CEST) Subject: [pypy-svn] r14696 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050715122128.D2B2427B66@code1.codespeak.net> Author: ac Date: Fri Jul 15 14:21:28 2005 New Revision: 14696 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Log: Merge 14695 from trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Fri Jul 15 14:21:28 2005 @@ -205,7 +205,7 @@ if isinstance(x, float): return W_FloatObject(self, x) if isinstance(x, tuple): - wrappeditems = [self.wrap(item) for item in x] + wrappeditems = [self.wrap(item) for item in list(x)] return W_TupleObject(self, wrappeditems) if isinstance(x, list): wrappeditems = [self.wrap(item) for item in x] From rxe at codespeak.net Fri Jul 15 17:01:13 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 15 Jul 2005 17:01:13 +0200 (CEST) Subject: [pypy-svn] r14702 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050715150113.B491E27B66@code1.codespeak.net> Author: rxe Date: Fri Jul 15 17:01:09 2005 New Revision: 14702 Added: pypy/dist/pypy/translator/llvm2/opaquenode.py Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_lltype.py Log: * add dummy opaque nodes. * get rid of hack in StructVarsizeNode where we were creating multiple nodes for the last entry in the struct. * refactored out database to just use obj2node and _pendingsetup attributes again. Will write to pypy-dev with status update later today. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Fri Jul 15 17:01:09 2005 @@ -1,7 +1,7 @@ import py from pypy.rpython import lltype from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2 import varsize import itertools log = log.structnode @@ -51,7 +51,7 @@ self.constructor_decl, fromtype) -class ArrayNode(LLVMNode): +class ArrayNode(ConstantLLVMNode): """ An arraynode. Elements can be a primitive, a struct, @@ -71,24 +71,24 @@ def setup(self): if isinstance(self.arraytype, lltype.Ptr): for item in self.value.items: - self.db.addptrvalue(item) + self.db.prepare_ptr(item) # set castref (note we must ensure that types are "setup" before we can # get typeval) typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) - self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(), + self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), self.ref, typeval) self._issetup = True - def get_typestr(self): + def get_typerepr(self): items = self.value.items arraylen = len(items) typeval = self.db.repr_arg_type(self.arraytype) return "{ int, [%s x %s] }" % (arraylen, typeval) def castfrom(self): - return "%s*" % self.get_typestr() + return "%s*" % self.get_typerepr() def constantvalue(self): """ Returns the constant representation for this node. """ @@ -96,13 +96,13 @@ arraylen = len(items) typeval = self.db.repr_arg_type(self.arraytype) - arrayvalues = [self.db.reprs_constant(v) for v in items] + arrayvalues = [self.db.repr_constant(v)[1] for v in items] value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, typeval, ", ".join(arrayvalues)) - return "%s {%s}" % (self.get_typestr(), value) + return "%s {%s}" % (self.get_typerepr(), value) # ______________________________________________________________________ # entry points from genllvm Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 15 17:01:09 2005 @@ -3,6 +3,8 @@ from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode +from pypy.translator.llvm2.opaquenode import OpaqueNode, OpaqueTypeNode +from pypy.translator.llvm2.node import ConstantLLVMNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -30,10 +32,10 @@ def dump(self): for x,y in self._dict.items(): print x, y - def _get(self, key): + def _get(self, key): if isinstance(key, Constant): - if isinstance(key.value, lltype._ptr): - key = key.value._obj + if isinstance(key.value, lltype._ptr): + key = key.value._obj return key def __getitem__(self, key): key = self._get(key) @@ -58,7 +60,7 @@ elif type_ is lltype.Char: repr = str(ord(value)) elif type_ is lltype.UniChar: - repr = "0" #XXX + repr = "0" # XXX Dont know what to do here at all? else: repr = str(value) return repr @@ -67,17 +69,10 @@ def __init__(self, translator): self._translator = translator self.obj2node = NormalizingDict() - self.ptr2nodevalue = {} self._pendingsetup = [] - self._pendingconstants = [] self._tmpcount = 1 - def addptrvalue(self, ptrvalue): - value = ptrvalue._obj - self.ptr2nodevalue[value] = self.create_constant_node(value, setup=True) - - def create_constant_node(self, value, setup=False): - type_ = lltype.typeOf(value) + def create_constant_node(self, type_, value, setup=False): node = None if isinstance(type_, lltype.FuncType): if value._callable and (not hasattr(value, "graph") or value.graph is None @@ -94,21 +89,28 @@ elif isinstance(type_, lltype.Array): node = ArrayNode(self, value) - assert node is not None, "%s not supported" % lltype.typeOf(value) + + elif isinstance(type_, lltype.OpaqueType): + node = OpaqueNode(self, value) + + assert node is not None, "%s not supported %s" % (type_, lltype.typeOf(value)) if setup: node.setup() return node - + def addpending(self, key, node): + # santity check we at least have a key of the right type + assert (isinstance(key, lltype.LowLevelType) or + isinstance(key, Constant) or + isinstance(lltype.typeOf(key), lltype.ContainerType)) + assert key not in self.obj2node, ( "node with key %r already known!" %(key,)) + + log("added to pending nodes:", type(key), node) self.obj2node[key] = node - log("added to pending nodes:", node) - if isinstance(node, (StructNode, ArrayNode)): - self._pendingconstants.append(node) - else: - self._pendingsetup.append(node) - + self._pendingsetup.append(node) + def prepare_repr_arg(self, const_or_var): """if const_or_var is not already in a dictionary self.obj2node, the appropriate node gets constructed and gets added to @@ -123,9 +125,9 @@ return assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" - value = const_or_var.value._obj - - self.addpending(const_or_var, self.create_constant_node(value)) + value = const_or_var.value._obj + + self.addpending(const_or_var, self.create_constant_node(ct.TO, value)) else: log.prepare(const_or_var, type(const_or_var)) @@ -152,6 +154,9 @@ elif isinstance(type_, lltype.Array): self.addpending(type_, ArrayTypeNode(self, type_)) + elif isinstance(type_, lltype.OpaqueType): + self.addpending(type_, OpaqueTypeNode(self, type_)) + else: assert False, "need to prepare typerepr %s %s" % (type_, type(type_)) @@ -164,24 +169,35 @@ self.prepare_repr_arg_type(const_or_var.concretetype) self.prepare_repr_arg(const_or_var) + def prepare_ptr(self, ptrvalue): + assert isinstance(lltype.typeOf(ptrvalue), lltype.Ptr) + value = ptrvalue._obj + type_ = lltype.typeOf(ptrvalue).TO + if value in self.obj2node or value is None: + return + self.addpending(value, + self.create_constant_node(type_, value)) + def setup_all(self): + # Constants setup need to be done after the rest + pendingconstants = [] while self._pendingsetup: - x = self._pendingsetup.pop() - log.settingup(x) - x.setup() - - while self._pendingconstants: - x = self._pendingconstants.pop() - log.settingup_constant(x) - x.setup() - - - def getobjects(self, subset_types=None): - res = [] - for v in self.obj2node.values() + self.ptr2nodevalue.values(): - if subset_types is None or isinstance(v, subset_types): - res.append(v) - return res + node = self._pendingsetup.pop() + if isinstance(node, (StructNode, ArrayNode)): + pendingconstants.append(node) + continue + log.settingup(node) + node.setup() + + self._pendingsetup = pendingconstants + while self._pendingsetup: + node = self._pendingsetup.pop() + assert isinstance(node, ConstantLLVMNode) + log.settingup_constant(node) + node.setup() + + def getnodes(self): + return self.obj2node.values() # __________________________________________________________ # Representing variables and constants in LLVM source code @@ -222,26 +238,32 @@ def repr_arg_type_multi(self, args): return [self.repr_arg_type(arg) for arg in args] - def reprs_constant(self, value): + def repr_constant(self, value): + " returns node and repr as tuple " type_ = lltype.typeOf(value) if isinstance(type_, lltype.Primitive): repr = primitive_to_str(type_, value) - return "%s %s" % (self.repr_arg_type(type_), repr) + return None, "%s %s" % (self.repr_arg_type(type_), repr) elif isinstance(type_, lltype.Ptr): - node = self.ptr2nodevalue[value._obj] + toptr = self.repr_arg_type(type_) + + # special case, null pointer + if value._obj is None: + return None, "%s null" % (toptr,) + + node = self.obj2node[value._obj] ref = node.ref fromptr = node.castfrom() - toptr = self.repr_arg_type(type_) if fromptr: refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref) ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) - return "%s %s" % (toptr, ref) + return node, "%s %s" % (toptr, ref) elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): - node = self.create_constant_node(value, setup=True) - return node.constantvalue() + node = self.create_constant_node(type_, value, setup=True) + return node, node.constantvalue() assert False, "%s not supported" % (type(value)) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 15 17:01:09 2005 @@ -4,7 +4,7 @@ from pypy.rpython import lltype from pypy.translator.backendoptimization import remove_same_as from pypy.translator.unsimplify import remove_double_links -from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log from pypy.rpython.extfunctable import table as extfunctable @@ -17,7 +17,9 @@ self.db = db assert isinstance(type_, lltype.FuncType) self.type_ = type_ - self.ref = 'ft.%s.%s' % (type_, nextnum()) + # XXX Make simplier for now, it is far too hard to read otherwise + #self.ref = 'ft.%s.%s' % (type_, nextnum()) + self.ref = '%%ft.%s' % (nextnum(),) def __str__(self): return "" % self.ref @@ -29,11 +31,9 @@ def writedatatypedecl(self, codewriter): returntype = self.db.repr_arg_type(self.type_.RESULT) inputargtypes = self.db.repr_arg_type_multi(self.type_._trueargs()) - decl = "%s type %s (%s)*" % (self.ref, returntype, - ", ".join(inputargtypes)) codewriter.funcdef(self.ref, returntype, inputargtypes) -class FuncNode(LLVMNode): +class FuncNode(ConstantLLVMNode): _issetup = False def __init__(self, db, value): Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 15 17:01:09 2005 @@ -49,18 +49,18 @@ nl = codewriter.newline nl(); comment("Type Declarations"); nl() - for typ_decl in self.db.getobjects(): + for typ_decl in self.db.getnodes(): typ_decl.writedatatypedecl(codewriter) nl(); comment("Global Data") ; nl() - for typ_decl in self.db.getobjects(): + for typ_decl in self.db.getnodes(): typ_decl.writeglobalconstants(codewriter) nl(); comment("Function Prototypes") ; nl() if self.embedexterns: for extdecl in extdeclarations.split('\n'): codewriter.append(extdecl) - for typ_decl in self.db.getobjects(): + for typ_decl in self.db.getnodes(): typ_decl.writedecl(codewriter) #import pdb ; pdb.set_trace() @@ -73,7 +73,7 @@ for extfunc in gc_funcs.split('\n'): codewriter.append(extfunc) - for typ_decl in self.db.getobjects(): + for typ_decl in self.db.getnodes(): typ_decl.writeimpl(codewriter) depdone = {} Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Fri Jul 15 17:01:09 2005 @@ -47,3 +47,8 @@ # __________________ after "implementation" ____________________ def writeimpl(self, codewriter): """ write function implementations. """ + +class ConstantLLVMNode(LLVMNode): + + def castfrom(self): + return None Added: pypy/dist/pypy/translator/llvm2/opaquenode.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/opaquenode.py Fri Jul 15 17:01:09 2005 @@ -0,0 +1,27 @@ +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode +from pypy.rpython import lltype + +class OpaqueTypeNode(LLVMNode): + + def __init__(self, db, opaquetype): + assert isinstance(opaquetype, lltype.OpaqueType) + self.db = db + self.opaquetype = opaquetype + self.ref = "%%opaque.%s" % (opaquetype.tag) + + def __str__(self): + return "" %(self.ref,) + + # ______________________________________________________________________ + # main entry points from genllvm + + def writedatatypedecl(self, codewriter): + # XXX Dummy - not sure what what we want + codewriter.funcdef(self.ref, 'sbyte*', ['sbyte *']) + + +class OpaqueNode(ConstantLLVMNode): + def __init__(self, db, value): + self.db = db + self.value = value + self.ref = "null" Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Fri Jul 15 17:01:09 2005 @@ -1,6 +1,6 @@ import py from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2 import varsize from pypy.rpython import lltype @@ -77,7 +77,7 @@ self.ref, self.constructor_decl, arraytype, indices_to_array) -class StructNode(LLVMNode): +class StructNode(ConstantLLVMNode): """ A struct constant. Can simply contain a primitive, a struct, @@ -90,7 +90,7 @@ self.value = value self.structtype = self.value._TYPE self.ref = "%%stinstance.%s" % (nextnum(),) - + def __str__(self): return "" % (self.ref,) @@ -98,27 +98,27 @@ return [(name, self.structtype._flds[name]) for name in self.structtype._names_without_voids()] + def _getvalues(self): + values = [] + for name, T in self._gettypes(): + value = getattr(self.value, name) + values.append(self.db.repr_constant(value)[1]) + return values + def setup(self): for name, T in self._gettypes(): assert T is not lltype.Void if isinstance(T, lltype.Ptr): - self.db.addptrvalue(getattr(self.value, name)) + self.db.prepare_ptr(getattr(self.value, name)) self._issetup = True - def castfrom(self): - return None - - def get_typestr(self): + def get_typerepr(self): return self.db.repr_arg_type(self.structtype) def constantvalue(self): """ Returns the constant representation for this node. """ - values = [] - for name, T in self._gettypes(): - value = getattr(self.value, name) - values.append(self.db.reprs_constant(value)) - - return "%s {%s}" % (self.get_typestr(), ", ".join(values)) + values = self._getvalues() + return "%s {%s}" % (self.get_typerepr(), ", ".join(values)) # ______________________________________________________________________ # main entry points from genllvm @@ -141,31 +141,44 @@ def __str__(self): return "" % (self.ref,) + def _getvalues(self): + values = [] + for name, T in self._gettypes()[:-1]: + value = getattr(self.value, name) + values.append(self.db.repr_constant(value)[1]) + values.append(self._get_lastnoderepr()) + return values + + def _get_lastnode(self): + if not hasattr(self, "lastnode"): + lastname, LASTT = self._gettypes()[-1] + assert isinstance(LASTT, lltype.Array) or ( + isinstance(LASTT, lltype.Struct) and LASTT._arrayfld) + value = getattr(self.value, lastname) + self.lastnode, self.lastnode_repr = self.db.repr_constant(value) + return self.lastnode + + def _get_lastnoderepr(self): + self._get_lastnode() + return self.lastnode_repr + def setup(self): # set castref (note we must ensure that types are "setup" before we can # get typeval) typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) - self.castref = "cast (%s* %s to %s*)" % (self.get_typestr(), + self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), self.ref, typeval) super(StructVarsizeNode, self).setup() + + def get_typerepr(self): + # last type is a special case and need to be worked out recursively + types = self._gettypes()[:-1] + types_repr = [self.db.repr_arg_type(T) for name, T in types] + types_repr.append(self._get_lastnode().get_typerepr()) - def get_typestr(self): - lastname, LASTT = self._gettypes()[-1] - assert isinstance(LASTT, lltype.Array) or ( - isinstance(LASTT, lltype.Struct) and LASTT._arrayfld) - - #XXX very messy - node = self.db.create_constant_node(getattr(self.value, lastname), True) - lasttype = node.get_typestr() - - types = [] - for name, T in self._gettypes()[:-1]: - types.append(self.db.repr_arg_type(T)) - types.append(lasttype) - - return "{%s}" % ", ".join(types) + return "{%s}" % ", ".join(types_repr) def castfrom(self): - return "%s*" % self.get_typestr() + return "%s*" % self.get_typerepr() Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_lltype.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Fri Jul 15 17:01:09 2005 @@ -178,3 +178,13 @@ fn = compile_function(array_constant, [], embedexterns=False) assert fn() == 42 +def test_struct_opaque(): + PRTTI = lltype.Ptr(lltype.RuntimeTypeInfo) + S = lltype.GcStruct('s', ('a', lltype.Signed), ('r', PRTTI)) + s = lltype.malloc(S) + s.a = 42 + def array_constant(): + return s.a + fn = compile_function(array_constant, [], embedexterns=False) + assert fn() == 42 + From pedronis at codespeak.net Fri Jul 15 21:02:02 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 21:02:02 +0200 (CEST) Subject: [pypy-svn] r14706 - pypy/dist/pypy/translator Message-ID: <20050715190202.BA67427B66@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 21:02:01 2005 New Revision: 14706 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: fix logic to retrieve lib for app-level helpers imports such that it works with translate_pypy import redirection setup. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Fri Jul 15 21:02:01 2005 @@ -78,7 +78,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.2' # bump this for substantial changes +GI_VERSION = '1.1.3' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): @@ -422,9 +422,14 @@ self.initcode.append1('import pypy') self.initcode.append1('import sys') self.initcode.append1('import os') - self.initcode.append1('libdir = os.path.join(pypy.__path__[0], "lib")\n' - 'sys.path.insert(0, libdir)\n' - 'try:\n' + self.initcode.append1('for pkgdir in pypy.__path__:\n' + ' libdir = os.path.join(pkgdir, "lib")\n' + ' if os.path.isdir(libdir):\n' + ' break\n' + 'else:\n' + ' raise Exception, "cannot find pypy/lib directory"\n' + 'sys.path.insert(0, libdir)\n') + self.initcode.append1('try:\n' ' import %s as _tmp\n' 'finally:\n' ' if libdir in sys.path:\n' @@ -1323,7 +1328,12 @@ dic['__file__'] = filename # XXX allow the app-level code to contain e.g. "import _formatting" - libdir = os.path.join(pypy.__path__[0], "lib") + for pkgdir in pypy.__path__: + libdir = os.path.join(pkgdir, "lib") + if os.path.isdir(libdir): + break + else: + raise Exception, "cannot find pypy/lib directory" sys.path.insert(0, libdir) try: exec code in dic From pedronis at codespeak.net Fri Jul 15 21:09:26 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 21:09:26 +0200 (CEST) Subject: [pypy-svn] r14707 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050715190926.7F6C527B66@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 21:09:24 2005 New Revision: 14707 Modified: pypy/dist/pypy/annotation/listdef.py pypy/dist/pypy/translator/test/test_annrpython.py Log: fix bug in listitem.merge, read locations of the other listitem were not reflown even if the merge involved a generalization of the previous annotation for other. Test that show-cased the problem. Modified: pypy/dist/pypy/annotation/listdef.py ============================================================================== --- pypy/dist/pypy/annotation/listdef.py (original) +++ pypy/dist/pypy/annotation/listdef.py Fri Jul 15 21:09:24 2005 @@ -22,9 +22,22 @@ if other.range_step != self.range_step: self.range_step = None self.itemof.update(other.itemof) + read_locations = self.read_locations.copy() + other_read_locations = other.read_locations.copy() self.read_locations.update(other.read_locations) self.patch() # which should patch all refs to 'other' - self.generalize(other.s_value) + s_value = self.s_value + s_other_value = other.s_value + s_new_value = tracking_unionof(self.__class__.__name__, s_value, s_other_value) + if s_new_value != s_value: + self.s_value = s_new_value + # reflow from reading points + for position_key in read_locations: + self.bookkeeper.annotator.reflowfromposition(position_key) + if s_new_value != s_other_value: + # reflow from reading points + for position_key in other_read_locations: + self.bookkeeper.annotator.reflowfromposition(position_key) def patch(self): for listdef in self.itemof: Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jul 15 21:09:24 2005 @@ -1395,6 +1395,31 @@ s = a.build_types(f, [int, str]) assert s.knowntype == int + def test_listitem_merge_asymmetry_bug(self): + class K: + pass + def mutr(k, x, i): + k.l2 = [x] + k.l2 # this involves a side-effectful union and unification, with this order + # of arguments some reflowing was missed + k.l2[i] = x + def witness(i): + pass + def trouble(k): + l = k.l1 + k.l2 + for i in range(len(l)): + witness(l[i]) + def f(flag, k, x, i): + if flag: + k = K() + k.l1 = [] + k.l2 = [] + trouble(k) + mutr(k, x, i) + a = self.RPythonAnnotator() + a.build_types(f, [bool, K, int, int]) + g = a.translator.getflowgraph(witness) + assert a.binding(g.getargs()[0]).knowntype == int + def g(n): return [0,1,2,n] From pedronis at codespeak.net Fri Jul 15 21:31:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 21:31:54 +0200 (CEST) Subject: [pypy-svn] r14708 - pypy/dist/pypy/translator/goal Message-ID: <20050715193154.BAC9C27B5E@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 21:31:53 2005 New Revision: 14708 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: given that recording annotator debug info is off by default now, replace -no-d option with a -d to reenable the debug info recording. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jul 15 21:31:53 2005 @@ -21,7 +21,7 @@ -o Generate and compile the C code, but don't run it -tcc Equivalent to the envvar PYPY_CC='tcc -shared -o "%s.so" "%s.c"' -- http://fabrice.bellard.free.fr/tcc/ - -no-d Disable recording of debugging information + -d Enable recording of annotator debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed -no-snapshot @@ -259,7 +259,7 @@ '-no-t': False, '-no-o': False, '-tcc': False, - '-no-d': False, + '-d': False, '-no-snapshot' : False, '-load': False, '-save': False, @@ -292,8 +292,8 @@ save_file = argiter.next() if options['-tcc']: os.environ['PYPY_CC'] = 'tcc -shared -o "%s.so" "%s.c"' - if options['-no-d']: - annmodel.DEBUG = False + if options['-d']: + annmodel.DEBUG = True def about(x): """ interactive debugging helper """ From rxe at codespeak.net Fri Jul 15 21:45:26 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 15 Jul 2005 21:45:26 +0200 (CEST) Subject: [pypy-svn] r14709 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050715194526.915A427B5E@code1.codespeak.net> Author: rxe Date: Fri Jul 15 21:45:24 2005 New Revision: 14709 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Arghh - backtrack of ideas from about 10 days ago. We now create a node for every pbc recursively in the database and ensure they are created at setup time. We need to do this so we because a pointer in a pbc can be nested too deep and to be seen at setup time and then it is never instantiated. Actually it feels a lot cleaner this way. Also added cast_pointer. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Fri Jul 15 21:45:24 2005 @@ -69,9 +69,8 @@ return "" % (self.ref,) def setup(self): - if isinstance(self.arraytype, lltype.Ptr): - for item in self.value.items: - self.db.prepare_ptr(item) + for item in self.value.items: + self.db.prepare_constant(self.arraytype, item) # set castref (note we must ensure that types are "setup" before we can # get typeval) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 15 21:45:24 2005 @@ -72,7 +72,7 @@ self._pendingsetup = [] self._tmpcount = 1 - def create_constant_node(self, type_, value, setup=False): + def create_constant_node(self, type_, value): node = None if isinstance(type_, lltype.FuncType): if value._callable and (not hasattr(value, "graph") or value.graph is None @@ -93,9 +93,7 @@ elif isinstance(type_, lltype.OpaqueType): node = OpaqueNode(self, value) - assert node is not None, "%s not supported %s" % (type_, lltype.typeOf(value)) - if setup: - node.setup() + assert node is not None, "%s not supported" % (type_) return node def addpending(self, key, node): @@ -168,13 +166,19 @@ log.prepare(const_or_var) self.prepare_repr_arg_type(const_or_var.concretetype) self.prepare_repr_arg(const_or_var) - - def prepare_ptr(self, ptrvalue): - assert isinstance(lltype.typeOf(ptrvalue), lltype.Ptr) - value = ptrvalue._obj - type_ = lltype.typeOf(ptrvalue).TO - if value in self.obj2node or value is None: + + def prepare_constant(self, type_, value): + if isinstance(type_, lltype.Primitive): + log.prepare_constant(value, "(is primitive)") return + elif isinstance(type_, lltype.Ptr): + type_ = type_.TO + value = value._obj + + # we can share data via pointers & dont need a node for nulls + if value in self.obj2node or value is None: + return + self.addpending(value, self.create_constant_node(type_, value)) @@ -262,7 +266,8 @@ return node, "%s %s" % (toptr, ref) elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): - node = self.create_constant_node(type_, value, setup=True) + assert value in self.obj2node, "XXX tmp assert" + node = self.obj2node[value] return node, node.constantvalue() assert False, "%s not supported" % (type(value)) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 15 21:45:24 2005 @@ -324,6 +324,7 @@ fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) + cast_pointer = cast_primitive cast_bool_to_int = cast_primitive cast_bool_to_uint = uint_is_true = cast_primitive cast_int_to_char = cast_char_to_int = cast_primitive @@ -389,6 +390,7 @@ self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) + r = op.result assert targettype != "void" self.codewriter.load(targetvar, targettype, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Fri Jul 15 21:45:24 2005 @@ -108,8 +108,9 @@ def setup(self): for name, T in self._gettypes(): assert T is not lltype.Void - if isinstance(T, lltype.Ptr): - self.db.prepare_ptr(getattr(self.value, name)) + value = getattr(self.value, name) + self.db.prepare_constant(T, value) + self._issetup = True def get_typerepr(self): @@ -148,28 +149,29 @@ values.append(self.db.repr_constant(value)[1]) values.append(self._get_lastnoderepr()) return values - + + def _get_lastnode_helper(self): + lastname, LASTT = self._gettypes()[-1] + assert isinstance(LASTT, lltype.Array) or ( + isinstance(LASTT, lltype.Struct) and LASTT._arrayfld) + value = getattr(self.value, lastname) + return self.db.repr_constant(value) + def _get_lastnode(self): - if not hasattr(self, "lastnode"): - lastname, LASTT = self._gettypes()[-1] - assert isinstance(LASTT, lltype.Array) or ( - isinstance(LASTT, lltype.Struct) and LASTT._arrayfld) - value = getattr(self.value, lastname) - self.lastnode, self.lastnode_repr = self.db.repr_constant(value) - return self.lastnode + return self._get_lastnode_helper()[0] def _get_lastnoderepr(self): - self._get_lastnode() - return self.lastnode_repr + return self._get_lastnode_helper()[1] def setup(self): + super(StructVarsizeNode, self).setup() + # set castref (note we must ensure that types are "setup" before we can # get typeval) typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), self.ref, typeval) - super(StructVarsizeNode, self).setup() def get_typerepr(self): # last type is a special case and need to be worked out recursively Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 15 21:45:24 2005 @@ -319,10 +319,29 @@ def method_call(a, b): obj = MyBase() obj.z = a - return obj.m(b) - f = compile_function(f, [int, int], view=True) + return obj.z + b + f = compile_function(method_call, [int, int], view=True) assert f(4, 5) == 9 +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(): + 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 class TestException(Exception): pass From rxe at codespeak.net Fri Jul 15 22:00:35 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 15 Jul 2005 22:00:35 +0200 (CEST) Subject: [pypy-svn] r14710 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050715200035.1786827B64@code1.codespeak.net> Author: rxe Date: Fri Jul 15 22:00:33 2005 New Revision: 14710 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: Skip getfield() / getsubstruct() which return void. Thanks perdronis. Aside - there were asserts in the code, which makes me think that remove_void() transformation should of been preventing this (although it looks as if it it doing something entirely different). In either case - I actually prefer to have a comment in the generated code. Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 15 22:00:33 2005 @@ -387,29 +387,36 @@ struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - r = op.result - assert targettype != "void" - self.codewriter.load(targetvar, targettype, tmpvar) - + if targettype != "void": + self.codewriter.getelementptr(tmpvar, structtype, struct, + ("uint", index)) + self.codewriter.load(targetvar, targettype, tmpvar) + else: + self.codewriter.comment("***Skipping operation getfield()***", + indent=True) + def getsubstruct(self, op): struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) targetvar = self.db.repr_arg(op.result) - self.codewriter.getelementptr(targetvar, structtype, - struct, ("uint", index)) targettype = self.db.repr_arg_type(op.result) - assert targettype != "void" + if targettype != "void": + self.codewriter.getelementptr(targetvar, structtype, + struct, ("uint", index)) + else: + self.codewriter.comment("***Skipping operation getsubstruct()***", + indent=True) def setfield(self, op): tmpvar = self.db.repr_tmpvar() struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, structtype, struct, ("uint", index)) + self.codewriter.getelementptr(tmpvar, structtype, struct, + ("uint", index)) valuevar, valuetype = self.db.repr_argwithtype(op.args[2]) assert valuetype != "void" self.codewriter.store(valuetype, valuevar, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 15 22:00:33 2005 @@ -301,28 +301,6 @@ f = compile_function(string_simple, [int, int, int, int]) assert f(0, 0, 1, 4) == ord("h") + ord("d") -def Xtest_dict_creation(): - d = {'hello' : 23, - 'world' : 21} - l = ["hello", "world"] - def createdict(i, j): - return d[l[i]] + d[l[j]] - f = compile_function(createdict, [int, int], view=True) - - assert createdict(0, 1) == 43 - -def Xtest_method_call(): - class MyBase: - def m(self, x): - return self.z + x - - def method_call(a, b): - obj = MyBase() - obj.z = a - return obj.z + b - f = compile_function(method_call, [int, int], view=True) - assert f(4, 5) == 9 - def test_attrs_class(): class MyBase: pass @@ -343,6 +321,16 @@ 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 + class TestException(Exception): pass @@ -358,3 +346,13 @@ except TestException: return 0 f = compile_function(catch, [int]) + +def Xtest_dict_creation(): + d = {'hello' : 23, + 'world' : 21} + l = ["hello", "world"] + def createdict(i, j): + return d[l[i]] + d[l[j]] + f = compile_function(createdict, [int, int], view=True) + + assert createdict(0, 1) == 43 From pedronis at codespeak.net Fri Jul 15 22:03:09 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 22:03:09 +0200 (CEST) Subject: [pypy-svn] r14711 - in pypy/dist/pypy/rpython: . test Message-ID: <20050715200309.A066027B66@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 22:03:07 2005 New Revision: 14711 Modified: pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: - more generic approach to implemeting is - conversion from SingleFrozenPBCRepr to MultipleFrozenPBCRepr - new test Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Fri Jul 15 22:03:07 2005 @@ -123,6 +123,12 @@ class __extend__(pairtype(Repr, Repr)): def rtype_is_((robj1, robj2), hop): + if hop.s_result.is_constant(): + return inputconst(Bool, hop.s_result.const) + if robj1.lowleveltype == Void: + robj1 = robj2 + elif robj2.lowleveltype == Void: + robj2 = robj1 if (not isinstance(robj1.lowleveltype, Ptr) or not isinstance(robj2.lowleveltype, Ptr)): raise TyperError('is of instances of the non-pointers: %r, %r' % ( Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jul 15 22:03:07 2005 @@ -103,19 +103,24 @@ def getPyObjRepr(rtyper, s_pbc): return robject.pyobj_repr +def get_access_set(rtyper, pbc): + access_sets = rtyper.annotator.getpbcaccesssets() + try: + return access_sets[pbc] + except KeyError: + return None def getFrozenPBCRepr(rtyper, s_pbc): if len(s_pbc.prebuiltinstances) <= 1: #if s_pbc.const is None: -- take care of by rtyper_makerepr() above # return none_frozen_pbc_repr - return single_frozen_pbc_repr + return SingleFrozenPBCRepr(s_pbc.prebuiltinstances.keys()[0]) else: pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys() if pbc is not None] - access_sets = rtyper.annotator.getpbcaccesssets() - _, _, access = access_sets.find(pbcs[0]) + access = get_access_set(rtyper, pbcs[0]) for obj in pbcs[1:]: - _, _, access1 = access_sets.find(obj) + access1 = get_access_set(rtyper, obj) assert access1 is access # XXX not implemented try: return rtyper.pbc_reprs[access] @@ -130,20 +135,21 @@ """Representation selected for a single non-callable pre-built constant.""" lowleveltype = Void + def __init__(self, value): + self.value = value + def rtype_getattr(_, hop): if not hop.s_result.is_constant(): raise TyperError("getattr on a constant PBC returns a non-constant") return hop.inputconst(hop.r_result, hop.s_result.const) -single_frozen_pbc_repr = SingleFrozenPBCRepr() - # __ None ____________________________________________________ class NoneFrozenPBCRepr(SingleFrozenPBCRepr): def rtype_is_true(self, hop): return Constant(False, Bool) -none_frozen_pbc_repr = NoneFrozenPBCRepr() +none_frozen_pbc_repr = NoneFrozenPBCRepr(None) def rtype_is_None(robj1, rnone2, hop, pos=0): @@ -190,14 +196,15 @@ self.initialized = "in progress" llfields = [] llfieldmap = {} - attrlist = self.access_set.attrs.keys() - attrlist.sort() - for attr in attrlist: - s_value = self.access_set.attrs[attr] - r_value = self.rtyper.getrepr(s_value) - mangled_name = 'pbc_' + attr - llfields.append((mangled_name, r_value.lowleveltype)) - llfieldmap[attr] = mangled_name, r_value + if self.access_set is not None: + attrlist = self.access_set.attrs.keys() + attrlist.sort() + for attr in attrlist: + s_value = self.access_set.attrs[attr] + r_value = self.rtyper.getrepr(s_value) + mangled_name = 'pbc_' + attr + llfields.append((mangled_name, r_value.lowleveltype)) + llfieldmap[attr] = mangled_name, r_value self.pbc_type.become(Struct('pbc', *llfields)) self.llfieldmap = llfieldmap self.initialized = True @@ -248,6 +255,19 @@ return llops.genop('getfield', [vpbc, cmangledname], resulttype = r_value) +class __extend__(pairtype(MultipleFrozenPBCRepr, MultipleFrozenPBCRepr)): + def convert_from_to((r_pbc1, r_pbc2), v, llops): + if r_pbc1.access_set == r_pbc2.access_set: + return v + return NotImplemented + +class __extend__(pairtype(SingleFrozenPBCRepr, MultipleFrozenPBCRepr)): + def convert_from_to((r_pbc1, r_pbc2), v, llops): + value = r_pbc1.value + access = get_access_set(r_pbc2.rtyper, value) + if access is r_pbc2.access_set: + return inputconst(r_pbc2, value) + return NotImplemented # ____________________________________________________________ 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 Jul 15 22:03:07 2005 @@ -158,6 +158,24 @@ res = interpret(f, [-1]) assert res == 5 +def test_is_among_frozen(): + fr1 = Freezing() + fr2 = Freezing() + def givefr1(): + return fr1 + def givefr2(): + return fr2 + def f(i): + if i == 1: + fr = givefr1() + else: + fr = givefr2() + return fr is fr1 + res = interpret(f, [0]) + assert res is False + res = interpret(f, [1]) + assert res is True + def test_unbound_method(): def f(): inst = MySubclass() From pedronis at codespeak.net Fri Jul 15 22:06:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 22:06:57 +0200 (CEST) Subject: [pypy-svn] r14712 - pypy/dist/pypy/translator/goal Message-ID: <20050715200657.82D0527B64@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 22:06:56 2005 New Revision: 14712 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: update Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 15 22:06:56 2005 @@ -9,8 +9,6 @@ * isinstance(SomeObject, _), needed by wrap__object - * is (and conversion) - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From pedronis at codespeak.net Fri Jul 15 22:13:48 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 22:13:48 +0200 (CEST) Subject: [pypy-svn] r14713 - pypy/dist/pypy/translator/goal Message-ID: <20050715201348.39DC827B5D@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 22:13:47 2005 New Revision: 14713 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: more issues Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 15 22:13:47 2005 @@ -4,6 +4,10 @@ Let's list and update here the issues that will show up, or have shown up already sometime ago, while running translate_pypy:: + * FlotRepr abs + + * equality on instances (=== is) + * we need a call_args similar to simple_call (doing redispatching) on MethodOfFrozenPBCRepr From pedronis at codespeak.net Fri Jul 15 22:33:21 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Jul 2005 22:33:21 +0200 (CEST) Subject: [pypy-svn] r14714 - pypy/dist/pypy/translator/goal Message-ID: <20050715203321.E2AF127B64@code1.codespeak.net> Author: pedronis Date: Fri Jul 15 22:33:21 2005 New Revision: 14714 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: another issue listed Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 15 22:33:21 2005 @@ -6,6 +6,8 @@ * FlotRepr abs + * slice(SomeObject, SomeObject, SomeObject) + * equality on instances (=== is) * we need a call_args similar to simple_call (doing redispatching) From rxe at codespeak.net Fri Jul 15 23:15:36 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 15 Jul 2005 23:15:36 +0200 (CEST) Subject: [pypy-svn] r14715 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050715211536.BE36027B64@code1.codespeak.net> Author: rxe Date: Fri Jul 15 23:15:35 2005 New Revision: 14715 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: Oops twice. funcnode.py - missed pedronis correcting himself on irc. database.py - didn't mean to check in. Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Fri Jul 15 23:15:35 2005 @@ -266,7 +266,6 @@ return node, "%s %s" % (toptr, ref) elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): - assert value in self.obj2node, "XXX tmp assert" node = self.obj2node[value] return node, node.constantvalue() Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 15 23:15:35 2005 @@ -403,12 +403,9 @@ index = fieldnames.index(op.args[1].value) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - if targettype != "void": - self.codewriter.getelementptr(targetvar, structtype, - struct, ("uint", index)) - else: - self.codewriter.comment("***Skipping operation getsubstruct()***", - indent=True) + assert targettype != "void" + self.codewriter.getelementptr(targetvar, structtype, + struct, ("uint", index)) def setfield(self, op): tmpvar = self.db.repr_tmpvar() From nik at codespeak.net Mon Jul 18 13:52:22 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Mon, 18 Jul 2005 13:52:22 +0200 (CEST) Subject: [pypy-svn] r14726 - pypy/dist/pypy/lib Message-ID: <20050718115222.D79F827B4F@code1.codespeak.net> Author: nik Date: Mon Jul 18 13:52:19 2005 New Revision: 14726 Modified: pypy/dist/pypy/lib/gc.py Log: The timeit module didn't work because it uses the gc module to disable gc during the timinig, and the gc module is just a stub at the moment. Added more stub functions to make the timeit module happy. Timers now work, no idea how accurate they are, though. Modified: pypy/dist/pypy/lib/gc.py ============================================================================== --- pypy/dist/pypy/lib/gc.py (original) +++ pypy/dist/pypy/lib/gc.py Mon Jul 18 13:52:19 2005 @@ -1,3 +1,12 @@ def collect(): - pass + pass + +def isenabled(): + pass + +def enable(): + pass + +def disable(): + pass From pedronis at codespeak.net Mon Jul 18 15:45:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 15:45:01 +0200 (CEST) Subject: [pypy-svn] r14729 - in pypy/dist/pypy: rpython rpython/test translator/goal Message-ID: <20050718134501.23CDB27B4F@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 15:44:56 2005 New Revision: 14729 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: * isinstance(SomeObject...) * support for simple_call in llinterp Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jul 18 15:44:56 2005 @@ -306,6 +306,13 @@ """ % locals()).compile() del opname + def op_simple_call(self, f, *args): + assert typeOf(f) == Ptr(PyObject) + for pyo in args: + assert typeOf(pyo) == Ptr(PyObject) + res = f._obj.value(*[pyo._obj.value for pyo in args]) + return pyobjectptr(res) + # __________________________________________________________ Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 18 15:44:56 2005 @@ -8,6 +8,7 @@ from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr, FloatRepr +from pypy.rpython.rbool import bool_repr from pypy.rpython import rclass from pypy.tool import sourcetools @@ -112,6 +113,12 @@ return hop.args_r[0].rtype_bltn_list(hop) def rtype_builtin_isinstance(hop): + if hop.args_r[0] == pyobj_repr or hop.args_r[1] == pyobj_repr: + v_obj, v_typ = hop.inputargs(pyobj_repr, pyobj_repr) + c = hop.inputconst(pyobj_repr, isinstance) + v = hop.genop('simple_call', [c, v_obj, v_typ], resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, bool_repr) + instance_repr = rclass.getinstancerepr(hop.rtyper, None) class_repr = rclass.get_type_repr(hop.rtyper) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Mon Jul 18 15:44:56 2005 @@ -1,6 +1,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test import test_llinterp from pypy.rpython.objectmodel import instantiate +from pypy.rpython import lltype from pypy.objspace.flow import model as flowmodel from pypy.tool import udir @@ -157,3 +158,16 @@ assert res.super.typeptr.name[0] == 'A' res = interpret(f, [2]) assert res.super.typeptr.name[0] == 'B' + + +def test_isinstance_obj(): + _1 = lltype.pyobjectptr(1) + def f(x): + return isinstance(x, int) + res = interpret(f, [_1], someobjects=True) + assert res is True + _1_0 = lltype.pyobjectptr(1.0) + res = interpret(f, [_1_0], someobjects=True) + assert res is False + + Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 18 15:44:56 2005 @@ -13,8 +13,6 @@ * we need a call_args similar to simple_call (doing redispatching) on MethodOfFrozenPBCRepr - * isinstance(SomeObject, _), needed by wrap__object - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From pedronis at codespeak.net Mon Jul 18 16:08:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 16:08:08 +0200 (CEST) Subject: [pypy-svn] r14730 - pypy/dist/pypy/rpython Message-ID: <20050718140808.8F5BF27B4F@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 16:08:07 2005 New Revision: 14730 Modified: pypy/dist/pypy/rpython/rpbc.py Log: conversion for restriction to None Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 18 16:08:07 2005 @@ -159,6 +159,9 @@ return hop.genop('ptr_iszero', [v1], resulttype=Bool) class __extend__(pairtype(Repr, NoneFrozenPBCRepr)): + + def convert_from_to((r_from, _), v, llops): + return inputconst(Void, None) def rtype_is_((robj1, rnone2), hop): return rtype_is_None(robj1, rnone2, hop) From pedronis at codespeak.net Mon Jul 18 16:39:10 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 16:39:10 +0200 (CEST) Subject: [pypy-svn] r14732 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718143910.D6B8327B51@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 16:39:08 2005 New Revision: 14732 Modified: pypy/dist/pypy/rpython/rspecialcase.py pypy/dist/pypy/rpython/test/test_rspecialcase.py Log: override:ignore support for methods too Modified: pypy/dist/pypy/rpython/rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/rspecialcase.py (original) +++ pypy/dist/pypy/rpython/rspecialcase.py Mon Jul 18 16:39:08 2005 @@ -6,10 +6,10 @@ def rtype_call_specialcase(hop): - v_function = hop.args_v[0] - if not isinstance(v_function, Constant): - raise TyperError("call_specialcase on a variable function") - func = v_function.value + s_function = hop.args_s[0] + if len(s_function.prebuiltinstances) != 1: + raise TyperError("not monomorphic call_specialcase") + func, clsdef = s_function.prebuiltinstances.items()[0] tag = func._annspecialcase_ if not tag.startswith("override:"): raise TyperError("call_specialcase only supports 'override:' functions") @@ -20,11 +20,9 @@ raise TyperError("call_specialcase: unknown tag override:" + tag) hop2 = hop.copy() hop2.r_s_popfirstarg() - return rtype_override_fn(hop2) + return rtype_override_fn(hop2, clsdef) -# def rtype_override_XXX to be added later - -def rtype_override_ignore(hop): +def rtype_override_ignore(hop, clsdef): # ignore works for methods too return inputconst(hop.r_result, None) Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rspecialcase.py (original) +++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Mon Jul 18 16:39:08 2005 @@ -20,3 +20,19 @@ assert ''.join(res.chars) == "ab" +def test_meth_override_ignore(): + class X: + def f(self): + pass + f._annspecialcase_ = "override:ignore" + def g(i): + x = X() + if i == 1: + return "ab" + else: + return x.f() + + res = interpret(g, [0]) + assert not res + res = interpret(g, [1]) + assert ''.join(res.chars) == "ab" From pedronis at codespeak.net Mon Jul 18 16:45:49 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 16:45:49 +0200 (CEST) Subject: [pypy-svn] r14733 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718144549.7418E27B51@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 16:45:47 2005 New Revision: 14733 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: FunctionsPBCRepr conversions Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jul 18 16:45:47 2005 @@ -404,6 +404,15 @@ return self.call(hop, f, vlist, rresult) +class __extend__(pairtype(FunctionsPBCRepr, FunctionsPBCRepr)): + def convert_from_to((r_fpbc1, r_fpbc2), v, llops): + # this check makes sense because both source and dest repr are FunctionsPBCRepr + if r_fpbc1.lowleveltype == r_fpbc2.lowleveltype: + return v + if r_fpbc1.lowleveltype == Void: + return inputconst(r_fpbc2, r_fpbc1.s_pbc.const) + return NotImplemented + # ____________________________________________________________ def commonbase(classdefs): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jul 18 16:45:47 2005 @@ -627,3 +627,49 @@ for x in range(1): res = interpret(f, [i, x]) assert res == f(i, x) + +def test_conv_from_funcpbcset_to_larger(): + def f1(): + return 7 + def f2(): + return 11 + def f3(): + return 13 + + def a(): + return f1 + def b(): + return f2 + + + def g(i): + if i == 1: + f = a() + else: + f = b() + return f() + + res = interpret(g, [0]) + assert res == 11 + res = interpret(g, [1]) + assert res == 7 + + def bc(j): + if j == 1: + return f2 + else: + return f3 + + def g(i, j): + if i == 1: + cls = a() + else: + cls = bc(j) + return cls() + + res = interpret(g, [0, 0]) + assert res == 13 + res = interpret(g, [0, 1]) + assert res == 11 + res = interpret(g, [1, 0]) + assert res == 7 From ale at codespeak.net Mon Jul 18 17:18:49 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 18 Jul 2005 17:18:49 +0200 (CEST) Subject: [pypy-svn] r14735 - in pypy/dist/pypy: interpreter module/posix module/posix/test rpython rpython/module Message-ID: <20050718151849.997C727B51@code1.codespeak.net> Author: ale Date: Mon Jul 18 17:18:47 2005 New Revision: 14735 Added: pypy/dist/pypy/module/posix/ pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/ pypy/dist/pypy/module/posix/test/test_posix.py Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py Log: The start of the mixedmodule os. The module function used in _file and _sio are implemented. The lowlevel support for these functions are not complete (fstat for instance doent work). a few test is added as well Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Jul 18 17:18:47 2005 @@ -153,7 +153,7 @@ self.setbuiltinmodule('parser', 'recparser') elif self.options.useparsermodule == "parser": self.setbuiltinmodule('parser') - + self.setbuiltinmodule('posix') # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): if name.startswith('w_') and not name.endswith('Type'): Added: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/posix/__init__.py Mon Jul 18 17:18:47 2005 @@ -0,0 +1,18 @@ +# Package initialisation +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + appleveldefs = { + } + interpleveldefs = { + 'open' : 'interp_posix.open', + 'lseek' : 'interp_posix.lseek', + 'write' : 'interp_posix.write', + 'isatty' : 'interp_posix.isatty', + 'read' : 'interp_posix.read', + 'close' : 'interp_posix.close', + 'ftruncate' : 'interp_posix.ftruncate', + 'fstat' : 'interp_posix.fstat', + 'dup' : 'interp_posix.dup' + '__doc__' : "space.wrap('Posix module')" + } Added: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/posix/interp_posix.py Mon Jul 18 17:18:47 2005 @@ -0,0 +1,49 @@ +from pypy.interpreter.baseobjspace import ObjSpace,W_Root + +import os +from os import * + +def open(space, w_fname, w_flag, w_mode=0777): + fname = space.str_w(w_fname) + flag = space.int_w(w_flag) + mode = space.int_w(w_mode) + # notice that an unwrap_spec attached to open could be used to the same effect + fd = os.open(fname, flag, mode) + return space.wrap(fd) + + +def lseek(space, w_fd, pos, how): + os.lseek(fd,pos,how) +lseek.unwrap_spec = [ObjSpace, W_Root, int, int] + +def isatty(space, w_fd): + return os.isatty(fd) +lseek.unwrap_spec = [ObjSpace, W_Root, int, int] + +def read(space, w_fd, buffersize): + return os.read(w_fd,buffersize) +read.unwrap_spec = [ObjSpace, W_Root, int] + +def write(space, w_fd, data): + return os.write( w_fd, data) +write.unwrap_spec = [ObjSpace, W_Root, str] + +def close(space, w_fd): + os.close(w_fd) +close.unwrap_spec = [ObjSpace, W_Root] + +def ftruncate(space, w_fd, length): + os.ftruncate(w_fd, length) +ftruncate.unwrap_spec = [ObjSpace, W_Root, int] + +def fstat(space, w_fd): + return os.fstat(w_fd) +fstat.unwrap_spec = [ObjSpace, W_Root] + +def getcwd(space): + return os.getcwd() +getcwd.unwrap_spec = [ObjSpace] + +def dup(space, w_fd): + return os.dup(w_fd) +dup.unwrap_spec = [ObjSpace, W_Root] \ No newline at end of file Added: pypy/dist/pypy/module/posix/test/test_posix.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/posix/test/test_posix.py Mon Jul 18 17:18:47 2005 @@ -0,0 +1,28 @@ +from pypy.rpython.test.test_llinterp import interpret + +def test_open(): + def f(): + import os + ff = os.open('test_posix.py',0,0755) + return ff + func = interpret(f,[]) + assert func + +def test_dup(): + def ff(): + import os + fi = os.open('test_posix.py',0,0755) + g = os.dup(fi) + #fi.close() + return g + func = interpret(ff,[]) + assert func + +def test_fstat(): + def fo(): + import os + fi = os.open('test_posix.py',0,0755) + g = os.fstat(fi) + return g + func = interpret(fo,[],True) + assert func Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Mon Jul 18 17:18:47 2005 @@ -57,6 +57,7 @@ declare(os.close , nonefactory, 'll_os/close') declare(os.getcwd , str , 'll_os/getcwd') declare(os.dup , int , 'll_os/dup') +declare(os.fstat , int , 'll_os/fstat') declare(time.time , float , 'll_time/time') declare(time.clock, float , 'll_time/clock') declare(time.sleep, nonefactory, 'll_time/sleep') 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 Mon Jul 18 17:18:47 2005 @@ -15,7 +15,7 @@ import os, errno from pypy.rpython.rstr import STR -from pypy.rpython.lltype import malloc +from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc # utility conversion functions @@ -77,3 +77,14 @@ def ll_os_dup(fd): return os.dup(fd) ll_os_dup.suggested_primitive = True + +def ll_os_fstat(fd): + stat = os.fstat(fd) + n = len(stat) + fieldnames = ['item%d' % i for i in range(n)] + lltypes = [Signed]*n + fields = tuple(zip(fieldnames, lltypes)) + tup = GcStruct('tuple%d' % n, fields) + #lowleveltype = Ptr(tup) + #p = malloc( tup ) + return tup \ No newline at end of file From hpk at codespeak.net Mon Jul 18 17:33:25 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 18 Jul 2005 17:33:25 +0200 (CEST) Subject: [pypy-svn] r14737 - in pypy/dist/pypy/module/posix: . test Message-ID: <20050718153325.9573827B4E@code1.codespeak.net> Author: hpk Date: Mon Jul 18 17:33:24 2005 New Revision: 14737 Modified: pypy/dist/pypy/module/posix/ (props changed) pypy/dist/pypy/module/posix/__init__.py (contents, props changed) pypy/dist/pypy/module/posix/interp_posix.py (props changed) pypy/dist/pypy/module/posix/test/ (props changed) pypy/dist/pypy/module/posix/test/test_posix.py (props changed) Log: - fix SyntaxError in posix/__init__.py - fixeol One remark regarding the tests: I think test_posix.py should generally contain more precise and and more complete tests and also it should allow to run tests if you are in a directory other than posix/test. Use 'pypy.tool.udir.udir' as a starting point for creating e.g. a temporary 'test_posix' directory, create a file there and pass the filename as a prebuilt constant (string) into the tests. Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Mon Jul 18 17:33:24 2005 @@ -13,6 +13,6 @@ 'close' : 'interp_posix.close', 'ftruncate' : 'interp_posix.ftruncate', 'fstat' : 'interp_posix.fstat', - 'dup' : 'interp_posix.dup' - '__doc__' : "space.wrap('Posix module')" + 'dup' : 'interp_posix.dup', + '__doc__' : 'space.wrap('Posix module')', } From tismer at codespeak.net Mon Jul 18 17:58:55 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 18 Jul 2005 17:58:55 +0200 (CEST) Subject: [pypy-svn] r14738 - pypy/dist/pypy/module/posix Message-ID: <20050718155855.F203727B4E@code1.codespeak.net> Author: tismer Date: Mon Jul 18 17:58:55 2005 New Revision: 14738 Modified: pypy/dist/pypy/module/posix/__init__.py Log: typo Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Mon Jul 18 17:58:55 2005 @@ -14,5 +14,5 @@ 'ftruncate' : 'interp_posix.ftruncate', 'fstat' : 'interp_posix.fstat', 'dup' : 'interp_posix.dup', - '__doc__' : 'space.wrap('Posix module')', + '__doc__' : "space.wrap('Posix module')", } From pedronis at codespeak.net Mon Jul 18 18:30:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 18:30:01 +0200 (CEST) Subject: [pypy-svn] r14739 - pypy/dist/pypy/rpython Message-ID: <20050718163001.6289F27B50@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 18:29:59 2005 New Revision: 14739 Modified: pypy/dist/pypy/rpython/rint.py Log: don't make assumptions Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jul 18 18:29:59 2005 @@ -34,7 +34,7 @@ if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: if debug: print 'explicit cast_uint_to_int' return llops.genop('cast_uint_to_int', [v], resulttype=Signed) - return v + return NotImplemented #arithmetic From pedronis at codespeak.net Mon Jul 18 18:32:22 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 18:32:22 +0200 (CEST) Subject: [pypy-svn] r14741 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050718163222.4FD7127B50@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 18:32:19 2005 New Revision: 14741 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/translator/test/test_annrpython.py Log: hack to get wrap__int to contain sensible code :( Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Mon Jul 18 18:32:19 2005 @@ -129,7 +129,11 @@ elif our_issubclass(s_obj.knowntype, typ) and not s_obj.can_be_none(): r.const = True elif not our_issubclass(typ, s_obj.knowntype): - r.const = False + r.const = False + elif s_obj.knowntype == int and typ == bool: # xxx this will explode in case of generalisation + # from bool to int, notice that isinstance( , bool|int) + # is quite border case for RPython + r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK # XXX HACK HACK HACK Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Mon Jul 18 18:32:19 2005 @@ -1419,6 +1419,27 @@ a.build_types(f, [bool, K, int, int]) g = a.translator.getflowgraph(witness) assert a.binding(g.getargs()[0]).knowntype == int + + # check RPython static semantics of isinstance(x,bool|int) as needed for wrap + + def test_isinstance_int_bool(self): + def f(x): + if isinstance(x, int): + if isinstance(x, bool): + return "bool" + return "int" + return "dontknow" + a = self.RPythonAnnotator() + s = a.build_types(f, [bool]) + assert s.const == "bool" + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.const == "int" + a = self.RPythonAnnotator() + s = a.build_types(f, [float]) + assert s.const == "dontknow" + + def g(n): From pedronis at codespeak.net Mon Jul 18 19:00:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 19:00:44 +0200 (CEST) Subject: [pypy-svn] r14742 - in pypy/dist/pypy: rpython rpython/test translator/goal Message-ID: <20050718170044.CAD4927B50@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 19:00:41 2005 New Revision: 14742 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: == and != for instances (with identity semantics) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jul 18 19:00:41 2005 @@ -8,7 +8,7 @@ from pypy.rpython.lltype import cast_pointer, castable, nullptr from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo -from pypy.rpython.lltype import FuncType +from pypy.rpython.lltype import FuncType, Bool # # There is one "vtable" per user class, with the following structure: @@ -599,6 +599,13 @@ r_ins = getinstancerepr(r_ins1.rtyper, basedef) return pairtype(Repr, Repr).rtype_is_(pair(r_ins, r_ins), hop) + rtype_eq = rtype_is_ + + def rtype_ne(rpair, hop): + v = rpair.rtype_eq(hop) + return hop.genop("bool_not", [v], resulttype=Bool) + + # ____________________________________________________________ def rtype_new_instance(rtyper, cls, llops): 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 Jul 18 19:00:41 2005 @@ -205,3 +205,61 @@ assert res == 0x0100 res = interpret(f, [3]) assert res == 0x0200 + +def test_eq(): + class A: pass + class B(A): pass + class C: pass + def f(i): + a = A() + b = B() + c = C() + d = None + e = None + if i == 0: + d = a + elif i == 1: + d = b + elif i == 2: + e = c + return (0x0001*(a == b) | 0x0002*(a == c) | 0x0004*(a == d) | + 0x0008*(a == e) | 0x0010*(b == c) | 0x0020*(b == d) | + 0x0040*(b == e) | 0x0080*(c == d) | 0x0100*(c == e) | + 0x0200*(d == e)) + res = interpret(f, [0]) + assert res == 0x0004 + res = interpret(f, [1]) + assert res == 0x0020 + res = interpret(f, [2]) + assert res == 0x0100 + res = interpret(f, [3]) + assert res == 0x0200 + +def test_ne(): + class A: pass + class B(A): pass + class C: pass + def f(i): + a = A() + b = B() + c = C() + d = None + e = None + if i == 0: + d = a + elif i == 1: + d = b + elif i == 2: + e = c + return (0x0001*(a != b) | 0x0002*(a != c) | 0x0004*(a != d) | + 0x0008*(a != e) | 0x0010*(b != c) | 0x0020*(b != d) | + 0x0040*(b != e) | 0x0080*(c != d) | 0x0100*(c != e) | + 0x0200*(d != e)) + res = interpret(f, [0]) + assert res == ~0x0004 & 0x3ff + res = interpret(f, [1]) + assert res == ~0x0020 & 0x3ff + res = interpret(f, [2]) + assert res == ~0x0100 & 0x3ff + res = interpret(f, [3]) + assert res == ~0x0200 & 0x3ff Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 18 19:00:41 2005 @@ -8,8 +8,6 @@ * slice(SomeObject, SomeObject, SomeObject) - * equality on instances (=== is) - * we need a call_args similar to simple_call (doing redispatching) on MethodOfFrozenPBCRepr From pedronis at codespeak.net Mon Jul 18 19:16:51 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 19:16:51 +0200 (CEST) Subject: [pypy-svn] r14743 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718171651.D402927B50@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 19:16:49 2005 New Revision: 14743 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_robject.py Log: fix newdict for pyobj_repr case. The same dict was reused, oops Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Mon Jul 18 19:16:49 2005 @@ -290,7 +290,8 @@ def rtype_newdict(hop): r_dict = hop.r_result if r_dict == robject.pyobj_repr: # special case: SomeObject: SomeObject dicts! - return hop.inputconst(robject.pyobj_repr, {}) + cdict = hop.inputconst(robject.pyobj_repr, dict) + return hop.genop('simple_call', [cdict], resulttype = robject.pyobj_repr) if not isinstance(r_dict, StrDictRepr): raise rmodel.TyperError("cannot create non-StrDicts, got %r" %(r_dict,)) c1 = hop.inputconst(lltype.Void, r_dict.lowleveltype) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jul 18 19:16:49 2005 @@ -365,7 +365,8 @@ resulttype=Unsigned) if r_to.lowleveltype == Signed: return llops.gencapicall('PyInt_AsLong', [v], - resulttype=Signed) + resulttype=Signed, + _callable = lambda pyo: int(pyo._obj.value)) return NotImplemented class __extend__(pairtype(IntegerRepr, PyObjRepr)): Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Mon Jul 18 19:16:49 2005 @@ -16,7 +16,10 @@ d[1] = 'a' d['a'] = i d['ab'] = c - return d - res = interpret(f, [1, 'c']) - print res + d[i] = c + return len(d) + res = interpret(f, [2, 'c']) + assert res == 4 + res = interpret(f, [3, 'c']) + assert res == 4 From ale at codespeak.net Mon Jul 18 20:03:18 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 18 Jul 2005 20:03:18 +0200 (CEST) Subject: [pypy-svn] r14744 - pypy/dist/pypy/interpreter Message-ID: <20050718180318.86A1727B56@code1.codespeak.net> Author: ale Date: Mon Jul 18 20:03:17 2005 New Revision: 14744 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: Disable posix Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Jul 18 20:03:17 2005 @@ -153,7 +153,7 @@ self.setbuiltinmodule('parser', 'recparser') elif self.options.useparsermodule == "parser": self.setbuiltinmodule('parser') - self.setbuiltinmodule('posix') + #self.setbuiltinmodule('posix') # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): if name.startswith('w_') and not name.endswith('Type'): From tismer at codespeak.net Mon Jul 18 20:19:06 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 18 Jul 2005 20:19:06 +0200 (CEST) Subject: [pypy-svn] r14745 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718181906.D4E7627B50@code1.codespeak.net> Author: tismer Date: Mon Jul 18 20:19:01 2005 New Revision: 14745 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_robject.py Log: support for generic Pyobject lists, calling back into CPython. Seems to work, the flowgraph looks good. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jul 18 20:19:01 2005 @@ -11,6 +11,7 @@ from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive from pypy.rpython.lltype import Bool, nullptr from pypy.rpython import rstr +from pypy.rpython import robject # ____________________________________________________________ # @@ -27,13 +28,17 @@ class __extend__(annmodel.SomeList): def rtyper_makerepr(self, rtyper): listitem = self.listdef.listitem + s_value = listitem.s_value if listitem.range_step and not listitem.mutated: return rrange.RangeRepr(listitem.range_step) + elif (s_value.__class__ is annmodel.SomeObject and s_value.knowntype == object): + return robject.pyobj_repr else: # cannot do the rtyper.getrepr() call immediately, for the case # of recursive structures -- i.e. if the listdef contains itself return ListRepr(lambda: rtyper.getrepr(listitem.s_value), listitem) + def rtyper_makekey(self): return self.listdef.listitem @@ -550,6 +555,15 @@ def rtype_newlist(hop): nb_args = hop.nb_args r_list = hop.r_result + if r_list == robject.pyobj_repr: # special case: SomeObject lists! + clist = hop.inputconst(robject.pyobj_repr, list) + v_result = hop.genop('simple_call', [clist], resulttype = robject.pyobj_repr) + cname = hop.inputconst(robject.pyobj_repr, 'append') + v_meth = hop.genop('getattr', [v_result, cname], resulttype = robject.pyobj_repr) + for i in range(nb_args): + v_item = hop.inputarg(robject.pyobj_repr, arg=i) + hop.genop('simple_call', [v_meth, v_item], resulttype = robject.pyobj_repr) + return v_result r_listitem = r_list.item_repr c1 = hop.inputconst(Void, r_list.lowleveltype) c2 = hop.inputconst(Signed, nb_args) Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Mon Jul 18 20:19:01 2005 @@ -22,4 +22,13 @@ assert res == 4 res = interpret(f, [3, 'c']) assert res == 4 - + +def test_obj_list(): + def f(i, c): + lis = [1, 2, 3, 4] + lis[i] = c + return len(lis) + res = interpret(f, [2, 'c'])#, view=True) + assert res == 4 + res = interpret(f, [3, 'c']) + assert res == 4 From pedronis at codespeak.net Mon Jul 18 20:45:17 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 20:45:17 +0200 (CEST) Subject: [pypy-svn] r14746 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718184517.A9CE427B4E@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 20:45:14 2005 New Revision: 14746 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: fix isinstance(None, cls) behavior. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 18 20:45:14 2005 @@ -124,9 +124,7 @@ v_obj, v_cls = hop.inputargs(instance_repr, class_repr) - v_objcls = hop.gendirectcall(rclass.ll_type, v_obj) - return hop.gendirectcall(rclass.ll_issubclass, v_objcls, v_cls) - + return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls) #def rtype_builtin_range(hop): see rrange.py Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jul 18 20:45:14 2005 @@ -637,5 +637,11 @@ subcls = subcls.parenttypeptr return True +def ll_isinstance(obj, cls): + if not obj: + return False + obj_cls = ll_type(obj) + return ll_issubclass(obj_cls, cls) + def ll_runtime_type_info(obj): return obj.typeptr.rtti 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 Jul 18 20:45:14 2005 @@ -101,24 +101,26 @@ assert res == 1 def test_isinstance(): - def a(): - b = B() - return isinstance(b, A) - def b(): - b = B() - return isinstance(b, B) - def c(): - b = B() - return isinstance(b, C) - - res = interpret(a, []) - assert res is True + def f(i): + if i == 0: + o = None + elif i == 1: + o = A() + elif i == 2: + o = B() + else: + o = C() + return 100*isinstance(o, A)+10*isinstance(o, B)+1*isinstance(o ,C) - res = interpret(b, []) - assert res is True + res = interpret(f, [1]) + assert res == 100 + res = interpret(f, [2]) + assert res == 110 + res = interpret(f, [3]) + assert res == 111 - res = interpret(c, []) - assert res is False + res = interpret(f, [0]) + assert res == 0 def test_method_used_in_subclasses_only(): class A: From pedronis at codespeak.net Mon Jul 18 20:48:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 20:48:27 +0200 (CEST) Subject: [pypy-svn] r14747 - pypy/dist/pypy/translator/goal Message-ID: <20050718184827.3652327B50@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 20:48:26 2005 New Revision: 14747 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: update Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 18 20:48:26 2005 @@ -9,7 +9,10 @@ * slice(SomeObject, SomeObject, SomeObject) * we need a call_args similar to simple_call (doing redispatching) - on MethodOfFrozenPBCRepr + on MethodOfFrozenPBCRepr etc + + * implementation for isinstance(x,list) makes sense only if x is a list, then needs + to check that x is not None * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From pedronis at codespeak.net Mon Jul 18 21:05:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 21:05:55 +0200 (CEST) Subject: [pypy-svn] r14748 - in pypy/dist/pypy/rpython: . test Message-ID: <20050718190555.5C57F27B56@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 21:05:53 2005 New Revision: 14748 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: direct support for isinstance calls statically computed by the annotator Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 18 21:05:53 2005 @@ -113,6 +113,8 @@ return hop.args_r[0].rtype_bltn_list(hop) def rtype_builtin_isinstance(hop): + if hop.s_result.is_constant(): + return hop.inputconst(lltype.Bool, hop.s_result.const) if hop.args_r[0] == pyobj_repr or hop.args_r[1] == pyobj_repr: v_obj, v_typ = hop.inputargs(pyobj_repr, pyobj_repr) c = hop.inputconst(pyobj_repr, isinstance) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Mon Jul 18 21:05:53 2005 @@ -169,5 +169,13 @@ _1_0 = lltype.pyobjectptr(1.0) res = interpret(f, [_1_0], someobjects=True) assert res is False - - + + +def test_const_isinstance(): + class B(object): + pass + def f(): + b = B() + return isinstance(b, B) + res = interpret(f, []) + assert res is True From pedronis at codespeak.net Mon Jul 18 21:25:35 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Jul 2005 21:25:35 +0200 (CEST) Subject: [pypy-svn] r14750 - in pypy/dist/pypy: rpython rpython/test translator/goal Message-ID: <20050718192535.310AE27B56@code1.codespeak.net> Author: pedronis Date: Mon Jul 18 21:25:32 2005 New Revision: 14750 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: isinstance(, list) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 18 21:25:32 2005 @@ -120,6 +120,14 @@ c = hop.inputconst(pyobj_repr, isinstance) v = hop.genop('simple_call', [c, v_obj, v_typ], resulttype = pyobj_repr) return hop.llops.convertvar(v, pyobj_repr, bool_repr) + + if hop.args_s[1].is_constant() and hop.args_s[1].const == list: + if hop.args_s[0].knowntype != list: + raise TyperError("isinstance(x, list) expects x to be known statically to be a list or None") + rlist = hop.args_r[0] + vlist = hop.inputarg(rlist, arg=0) + cnone = hop.inputconst(rlist, None) + return hop.genop('ptr_ne', [vlist, cnone], resulttype=lltype.Bool) instance_repr = rclass.getinstancerepr(hop.rtyper, None) class_repr = rclass.get_type_repr(hop.rtyper) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Mon Jul 18 21:25:32 2005 @@ -179,3 +179,15 @@ return isinstance(b, B) res = interpret(f, []) assert res is True + +def test_isinstance_list(): + def f(i): + if i == 0: + l = [] + else: + l = None + return isinstance(l, list) + res = interpret(f, [0]) + assert res is True + res = interpret(f, [1]) + assert res is False Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 18 21:25:32 2005 @@ -11,9 +11,6 @@ * we need a call_args similar to simple_call (doing redispatching) on MethodOfFrozenPBCRepr etc - * implementation for isinstance(x,list) makes sense only if x is a list, then needs - to check that x is not None - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From pedronis at codespeak.net Tue Jul 19 00:35:52 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 00:35:52 +0200 (CEST) Subject: [pypy-svn] r14752 - pypy/dist/pypy/translator/c/test Message-ID: <20050718223552.DFF4B27B5A@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 00:35:52 2005 New Revision: 14752 Modified: pypy/dist/pypy/translator/c/test/test_typed.py Log: avoid using a mixed type list Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Tue Jul 19 00:35:52 2005 @@ -37,7 +37,7 @@ def test_get_set_del_slice(self): def get_set_del_nonneg_slice(): # no neg slices for now! - l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] + 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: @@ -48,7 +48,7 @@ #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 + l[0], l[-1], l[2], l[3] =3, 9, 8, 11 list_3_c = l[:2] list_9 = l[5:] @@ -59,10 +59,10 @@ len(list_11_h), list_11_h[0], list_11_h[1]) fn = self.getcompiled(get_set_del_nonneg_slice) result = fn() - assert result == (6, 3, 'c', 8, 11, 'h', 9, - 2, 3, 'c', + assert result == (6, 3, ord('c'), 8, 11, ord('h'), 9, + 2, 3, ord('c'), 1, 9, - 2, 11, 'h') + 2, 11, ord('h')) def test_is(self): def testfn(): From tismer at codespeak.net Tue Jul 19 01:22:27 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 19 Jul 2005 01:22:27 +0200 (CEST) Subject: [pypy-svn] r14753 - in pypy/dist/pypy/translator/c: . src Message-ID: <20050718232227.B284327B5A@code1.codespeak.net> Author: tismer Date: Tue Jul 19 01:22:26 2005 New Revision: 14753 Modified: pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/src/exception.h pypy/dist/pypy/translator/c/src/ll_time.h Log: windows support: - added missing include for ll_time.h - renamed macro RaiseException, because windows uses it. Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue Jul 19 01:22:26 2005 @@ -210,7 +210,7 @@ # exceptional return block exc_cls = self.expr(block.inputargs[0]) exc_value = self.expr(block.inputargs[1]) - yield 'RaiseException(%s, %s);' % (exc_cls, exc_value) + yield 'RPyRaiseException(%s, %s);' % (exc_cls, exc_value) for line in self.return_with_error(): yield line else: 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 Tue Jul 19 01:22:26 2005 @@ -14,7 +14,7 @@ #define ExceptionOccurred() (rpython_exc_type != NULL) -#define RaiseException(etype, evalue) \ +#define RPyRaiseException(etype, evalue) \ assert(!ExceptionOccurred()); \ rpython_exc_type = etype; \ rpython_exc_value = evalue @@ -78,7 +78,7 @@ /******************************************************************/ #define ExceptionOccurred() PyErr_Occurred() -#define RaiseException(etype, evalue) PyErr_Restore(etype, evalue, NULL) +#define RPyRaiseException(etype, evalue) PyErr_Restore(etype, evalue, NULL) #define FetchException(etypevar, evaluevar, ignored) { \ PyObject *__tb; \ PyErr_Fetch(&etypevar, &evaluevar, &__tb); \ Modified: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_time.h (original) +++ pypy/dist/pypy/translator/c/src/ll_time.h Tue Jul 19 01:22:26 2005 @@ -9,6 +9,7 @@ #if defined(MS_WINDOWS) && !defined(MS_WIN64) && !defined(__BORLANDC__) /* Win32 has better clock replacement XXX Win64 does not yet, but might when the platform matures. */ +#include double LL_time_clock(void) { From pedronis at codespeak.net Tue Jul 19 01:34:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 01:34:12 +0200 (CEST) Subject: [pypy-svn] r14754 - in pypy/dist/pypy: rpython translator/goal Message-ID: <20050718233412.003CB27B5A@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 01:34:11 2005 New Revision: 14754 Added: pypy/dist/pypy/translator/goal/module-list.example (contents, props changed) pypy/dist/pypy/translator/goal/order.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rtyper.py Log: Experimental hook to have more fine control over which blocks get specialized in which order. The order.py module is an example using it, it uses a list of modules names (or :) to sort the blocks use RTYPERORDER=order and edit locally 'module-list.example' as 'module-list' to try it out. with this approach I discovered e.g. that the ~8500 blocks from (synthetic) functions without module (module=None) all specialize fine. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 19 01:34:11 2005 @@ -59,6 +59,15 @@ print '*' * len(s) except: self.seed = 0 + try: + self.order = __import__(os.getenv('RTYPERORDER'), {}, {}, ['*']).order + s = 'Using %s.%s for order' % (self.order.__module__, self.order.__name__) + print '*' * len(s) + print s + print '*' * len(s) + except: + self.order = None + def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -114,8 +123,15 @@ import random r = random.Random(self.seed) r.shuffle(pending) + + if self.order: + tracking = self.order(self.annotator, pending) + else: + tracking = lambda block: None + # specialize all blocks in the 'pending' list for block in pending: + tracking(block) self.specialize_block(block) self.already_seen[block] = True # progress bar Added: pypy/dist/pypy/translator/goal/module-list.example ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/module-list.example Tue Jul 19 01:34:11 2005 @@ -0,0 +1,71 @@ +pypy.objspace.std.listobject +pypy.objspace.std.listobject:unwrap +None +posixpath +pypy._cache._exceptions_45b09df9652a189b2135b8b32a956e3e +pypy.interpreter.argument +pypy.interpreter.baseobjspace +pypy.interpreter.compiler +pypy.interpreter.error +pypy.interpreter.eval +pypy.interpreter.executioncontext +pypy.interpreter.function +pypy.interpreter.gateway +pypy.interpreter.generator +pypy.interpreter.miscutils +pypy.interpreter.mixedmodule +pypy.interpreter.module +pypy.interpreter.nestedscope +pypy.interpreter.pycode +pypy.interpreter.pyframe +pypy.interpreter.pyopcode +pypy.interpreter.pytraceback +pypy.interpreter.special +pypy.interpreter.typedef +pypy.module.__builtin__ +pypy.module.__builtin__.compiling +pypy.module.__builtin__.importing +pypy.module.__builtin__.operation +pypy.module.sys +pypy.module.sys.hook +pypy.module.sys.state +pypy.module.sys.vm +pypy.module.unicodedata.function +pypy.module.unicodedata.unicodedb +pypy.objspace.descroperation +pypy.objspace.std.boolobject +pypy.objspace.std.booltype +pypy.objspace.std.default +pypy.objspace.std.dictobject +pypy.objspace.std.dictproxyobject +pypy.objspace.std.dictproxytype +pypy.objspace.std.dicttype +pypy.objspace.std.fake +pypy.objspace.std.floatobject +pypy.objspace.std.floattype +pypy.objspace.std.intobject +pypy.objspace.std.inttype +pypy.objspace.std.iterobject +pypy.objspace.std.listsort +pypy.objspace.std.listtype +pypy.objspace.std.longobject +pypy.objspace.std.longtype +pypy.objspace.std.model +pypy.objspace.std.multimethod +pypy.objspace.std.noneobject +pypy.objspace.std.objecttype +pypy.objspace.std.objspace +pypy.objspace.std.register_all +pypy.objspace.std.sliceobject +pypy.objspace.std.slicetype +pypy.objspace.std.stdtypedef +pypy.objspace.std.stringobject +pypy.objspace.std.stringtype +pypy.objspace.std.strutil +pypy.objspace.std.tupleobject +pypy.objspace.std.tupletype +pypy.objspace.std.typeobject +pypy.objspace.std.typetype +pypy.objspace.std.unicodeobject +pypy.objspace.std.unicodetype +pypy.rpython.normalizecalls Added: pypy/dist/pypy/translator/goal/order.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/order.py Tue Jul 19 01:34:11 2005 @@ -0,0 +1,47 @@ +import sys +import os + +lst = open('module-list', 'r') +try: + prefixes = lst.read().split() +finally: + lst.close() + +NOMATCH = sys.maxint + +def order(annotator, pending): + cache = {} + annotated = annotator.annotated + def indx(block): + func = annotated[block] + module = func.__module__ + if module is None: + module = 'None' + tag = "%s:%s" % (module, func.__name__) + try: + return cache[tag] + except KeyError: + match = NOMATCH + i = 0 + for pfx in prefixes: + if tag.startswith(pfx): + if match == NOMATCH: + match = i + else: + if len(pfx) > len(prefixes[match]): + match = i + i += 1 + cache[tag] = match + return match + + pending.sort(lambda blk1, blk2: cmp(indx(blk1), indx(blk2))) + + cur_module = ['$'] + def track(block): + module = annotated[block].__module__ + if module != cur_module[0]: + print "Specializing blocks in module: %s" % module + cur_module[0] = module + return track + + From hpk at codespeak.net Tue Jul 19 12:07:16 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 12:07:16 +0200 (CEST) Subject: [pypy-svn] r14759 - pypy/dist/pypy/interpreter Message-ID: <20050719100716.5538927B51@code1.codespeak.net> Author: hpk Date: Tue Jul 19 12:07:15 2005 New Revision: 14759 Modified: pypy/dist/pypy/interpreter/function.py Log: - remove unused import - cosmetics Modified: pypy/dist/pypy/interpreter/function.py ============================================================================== --- pypy/dist/pypy/interpreter/function.py (original) +++ pypy/dist/pypy/interpreter/function.py Tue Jul 19 12:07:15 2005 @@ -8,7 +8,6 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.argument import Arguments from pypy.interpreter.eval import Code from pypy.interpreter.gateway import NoneNotWrapped @@ -50,7 +49,8 @@ # unwrapping is done through unwrap_specs in typedef.py - def descr_method__new__(space, w_subtype, w_code, w_globals, w_name=None, w_argdefs=None, w_closure=NoneNotWrapped): + def descr_method__new__(space, w_subtype, w_code, w_globals, + w_name=None, w_argdefs=None, w_closure=NoneNotWrapped): code = space.interpclass_w(w_code) if code is None or not isinstance(code, Code): raise OperationError(space.w_TypeError, space.wrap("expected code")) From hpk at codespeak.net Tue Jul 19 12:08:46 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 12:08:46 +0200 (CEST) Subject: [pypy-svn] r14760 - pypy/dist/pypy/documentation Message-ID: <20050719100846.7D3B527B51@code1.codespeak.net> Author: hpk Date: Tue Jul 19 12:08:45 2005 New Revision: 14760 Added: pypy/dist/pypy/documentation/style.css Log: add a stylesheet similar to the one used on codespeak Added: pypy/dist/pypy/documentation/style.css ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/style.css Tue Jul 19 12:08:45 2005 @@ -0,0 +1,1077 @@ +body,body.editor,body.body { + font: 110% "Times New Roman", Arial, Verdana, Helvetica, serif; + background: White; + color: Black; +} + +a, a.reference { + text-decoration: none; +} +a[href]:hover { text-decoration: underline; } + +img { + border: none; + vertical-align: middle; +} + +p, div.text { + text-align: left; + line-height: 1.5em; + margin: 0.5em 0em 0em 0em; +} + + + +p a:active { + color: Red; + background-color: transparent; +} + +p img { + border: 0; + margin: 0; +} + +img.inlinephoto { + padding: 0; + padding-right: 1em; + padding-top: 0.7em; + float: left; +} + +hr { + clear: both; + height: 1px; + color: #8CACBB; + background-color: transparent; +} + + +ul { + line-height: 1.5em; + /*list-style-image: url("bullet.gif"); */ + margin-left: 1.5em; + padding:0; +} + +ol { + line-height: 1.5em; + margin-left: 1.5em; + padding:0; +} + +ul a, ol a { + text-decoration: underline; +} + +dl { +} + +dt { + font-weight: bold; +} + +dd { + line-height: 1.5em; + margin-bottom: 1em; +} + +blockquote { + font-family: Times, "Times New Roman", serif; + font-style: italic; + font-size: 120%; +} + +code { + color: Black; + /*background-color: #dee7ec;*/ + background-color: #cccccc; +} + +pre { + padding: 1em; + border: 1px solid #8cacbb; + color: Black; + background-color: #dee7ec; + background-color: #cccccc; + overflow: auto; +} + + +.netscape4 { + display: none; +} + +/* main page styles */ + +/*a[href]:hover { color: black; text-decoration: underline; } +a[href]:link { color: black; text-decoration: underline; } +a[href] { color: black; text-decoration: underline; } +*/ + +span.menu_selected { + color: black; + font: 140% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; + padding-right: 0.3em; + background-color: #cccccc; +} + + +a.menu { + /*color: #3ba6ec; */ + font: 140% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; + padding-right: 0.3em; +} + +a.menu[href]:visited, a.menu[href]:link{ + /*color: #3ba6ec; */ + font: 140% Verdana, Helvetica, Arial, sans-serif; + text-decoration: none; +} + +a.menu[href]:hover { + /*color: black;*/ +} + +div.project_title{ + /*border-spacing: 20px;*/ + font: 160% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: center; + padding-bottom: 0.3em; +} + +a.wikicurrent { + font: 100% Verdana, Helvetica, Arial, sans-serif; + color: #3ba6ec; + vertical-align: middle; +} + + +table.body { + border: 0; + /*padding: 0; + border-spacing: 0px; + border-collapse: separate; + */ +} + +td.page-header-left { + padding: 5px; + /*border-bottom: 1px solid #444444;*/ +} + +td.page-header-top { + padding: 0; + + /*border-bottom: 1px solid #444444;*/ +} + +td.sidebar { + padding: 1 0 0 1; +} + +td.sidebar p.classblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeee; +} + +td.sidebar p.userblock { + padding: 0 5 0 5; + margin: 1 1 1 1; + border: 1px solid #444444; + background-color: #eeeeff; +} + +td.content { + padding: 1 5 1 5; + vertical-align: top; + width: 100%; +} + +p.ok-message { + background-color: #22bb22; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +p.error-message { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} + +p:first-child { + margin: 0 ; + padding: 0; +} + +/* style for forms */ +table.form { + padding: 2; + border-spacing: 0px; + border-collapse: separate; +} + +table.form th { + color: #333388; + text-align: right; + vertical-align: top; + font-weight: normal; +} +table.form th.header { + font-weight: bold; + background-color: #eeeeff; + text-align: left; +} + +table.form th.required { + font-weight: bold; +} + +table.form td { + color: #333333; + empty-cells: show; + vertical-align: top; +} + +table.form td.optional { + font-weight: bold; + font-style: italic; +} + +table.form td.html { + color: #777777; +} + +/* style for lists */ +table.list { + border-spacing: 0px; + border-collapse: separate; + vertical-align: top; + padding-top: 0; + width: 100%; +} + +table.list th { + padding: 0 4 0 4; + color: #404070; + background-color: #eeeeff; + border-right: 1px solid #404070; + border-top: 1px solid #404070; + border-bottom: 1px solid #404070; + vertical-align: top; + empty-cells: show; +} +table.list th a[href]:hover { color: #404070 } +table.list th a[href]:link { color: #404070 } +table.list th a[href] { color: #404070 } +table.list th.group { + background-color: #f4f4ff; + text-align: center; + font-size: 120%; +} + +table.list td { + padding: 0 4 0 4; + border: 0 2 0 2; + border-right: 1px solid #404070; + color: #404070; + background-color: white; + vertical-align: top; + empty-cells: show; +} + +table.list tr.normal td { + background-color: white; + white-space: nowrap; +} + +table.list tr.alt td { + background-color: #efefef; + white-space: nowrap; +} + +table.list td:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list th:first-child { + border-left: 1px solid #404070; + border-right: 1px solid #404070; +} + +table.list tr.navigation th { + text-align: right; +} +table.list tr.navigation th:first-child { + border-right: none; + text-align: left; +} + + +/* style for message displays */ +table.messages { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.messages th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.messages th { + font-weight: bold; + color: black; + text-align: left; + border-bottom: 1px solid #afafaf; +} + +table.messages td { + font-family: monospace; + background-color: #efefef; + border-bottom: 1px solid #afafaf; + color: black; + empty-cells: show; + border-right: 1px solid #afafaf; + vertical-align: top; + padding: 2 5 2 5; +} + +table.messages td:first-child { + border-left: 1px solid #afafaf; + border-right: 1px solid #afafaf; +} + +/* style for file displays */ +table.files { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.files th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.files th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +table.files td { + font-family: monospace; + empty-cells: show; +} + +/* style for history displays */ +table.history { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.history th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; + font-size: 100%; +} + +table.history th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; + font-size: 90%; +} + +table.history td { + font-size: 90%; + vertical-align: top; + empty-cells: show; +} + + +/* style for class list */ +table.classlist { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classlist th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.classlist th { + font-weight: bold; + text-align: left; +} + + +/* style for class help display */ +table.classhelp { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.classhelp th { + font-weight: bold; + text-align: left; + color: #707040; +} + +table.classhelp td { + padding: 2 2 2 2; + border: 1px solid black; + text-align: left; + vertical-align: top; + empty-cells: show; +} + + +/* style for "other" displays */ +table.otherinfo { + border-spacing: 0px; + border-collapse: separate; + width: 100%; +} + +table.otherinfo th.header{ + padding-top: 10px; + border-bottom: 1px solid gray; + font-weight: bold; + background-color: white; + color: #707040; +} + +table.otherinfo th { + border-bottom: 1px solid #afafaf; + font-weight: bold; + text-align: left; +} + +input { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + +select { + border: 1px solid #8cacbb; + color: Black; + background-color: white; + vertical-align: middle; + margin-bottom: 1px; /* IE bug fix */ + padding: 0.1em; +} + + +a.nonexistent { + color: #FF2222; +} +a.nonexistent:visited { + color: #FF2222; +} +a.external { + color: #AA6600; +} + +/* +dl,ul,ol { + margin-top: 1pt; +} +tt,pre { + font-family: Lucida Console,Courier New,Courier,monotype; + font-size: 12pt; +} +pre.code { + margin-top: 8pt; + margin-bottom: 8pt; + background-color: #FFFFEE; + white-space:pre; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#111111; + padding:5px; + width:100%; +} +*/ +div.diffold { + background-color: #FFFF80; + border-style:none; + border-width:thin; + width:100%; +} +div.diffnew { + background-color: #80FF80; + border-style:none; + border-width:thin; + width:100%; +} +div.message { + margin-top: 6pt; + background-color: #E8FFE8; + border-style:solid; + border-width:1pt; + border-color:#999999; + color:#440000; + padding:5px; + width:100%; +} +strong.highlight { + background-color: #FFBBBB; +/* as usual, NetScape fucks up with innocent CSS + border-color: #FFAAAA; + border-style: solid; + border-width: 1pt; +*/ +} + +table.navibar { + background-color: #C8C8C8; + border-spacing: 3px; +} +td.navibar { + background-color: #E8E8E8; + vertical-align: top; + text-align: right; + padding: 0px; +} + +div.pagename { + font-size: 140%; + color: blue; + text-align: center; + font-weight: bold; + background-color: white; + padding: 0 ; +} + +a.wikiaction, input.wikiaction { + color: black; + text-decoration: None; + text-align: center; + color: black; + /*border: 1px solid #3ba6ec; */ + margin: 4px; + padding: 5; + padding-bottom: 0; + white-space: nowrap; +} + +a.wikiaction[href]:hover { + color: black; + text-decoration: none; + /*background-color: #dddddd; */ +} + +span.wikiuserpref { + padding-top: 1em; + font-size: 120%; +} + +div.wikitrail { + vertical-align: bottom; + /*font-size: -1;*/ + padding-top: 1em; + display: none; +} + +div.wikiaction { + vertical-align: middle; + /*border-bottom: 1px solid #8cacbb;*/ + padding-bottom:1em; + text-align: left; + width: 100%; +} + +div.wikieditmenu { + text-align: right; +} + +form.wikiedit { + border: 1px solid #8cacbb; + background-color: #f0f0f0; + background-color: #fabf00; + padding: 1em; + padding-right: 0em; +} + +div.legenditem { + padding-top: 0.5em; + padding-left: 0.3em; +} + +span.wikitoken { + background-color: #eeeeee; +} + + +div#contentspace h1:first-child, div.heading:first-child { + padding-top: 0; + margin-top: 0; +} +div#contentspace h2:first-child { + padding-top: 0; + margin-top: 0; +} + +/* heading and paragraph text */ + +div.heading, h1 { + font-family: Verdana, Helvetica, Arial, sans-serif; + background-color: #58b3ef; + background-color: #FFFFFF; + /*color: #4893cf;*/ + color: black; + padding-top: 1.0em; + padding-bottom:0.2em; + text-align: left; + margin-top: 0em; + /*margin-bottom:8pt;*/ + font-weight: bold; + font-size: 115%; + border-bottom: 1px solid #8CACBB; +} + + +h1, h2, h3, h4, h5, h6 { + color: Black; + clear: left; + font: 100% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 1em; + padding-bottom: 0.2em; + /*border-bottom: 1px solid #8CACBB;*/ +} +/* h1,h2 { padding-top: 0; }*/ + + +h1 { font-size: 145%; } +h2 { font-size: 135%; } +h3 { font-size: 125%; } +h4 { font-size: 120%; } +h5 { font-size: 110%; } +h6 { font-size: 80%; } + +h1 a { text-decoration: None;} + +div.exception { + background-color: #bb2222; + padding: 5 5 5 5; + color: white; + font-weight: bold; +} +pre.exception { + font-size: 110%; + padding: 1em; + border: 1px solid #8cacbb; + color: Black; + background-color: #dee7ec; + background-color: #cccccc; +} + +/* defines for navgiation bar (documentation) */ + + +div.direntry { + padding-top: 0.3em; + padding-bottom: 0.3em; + margin-right: 1em; + font-weight: bold; + background-color: #dee7ec; + font-size: 110%; +} + +div.fileentry { + font-family: Verdana, Helvetica, Arial, sans-serif; + padding-bottom: 0.3em; + white-space: nowrap; + line-height: 150%; +} + +a.fileentry { + white-space: nowrap; +} + + +span.left { + text-align: left; +} +span.right { + text-align: right; +} + +div.navbar { + /*margin: 0;*/ + font-size: 80% /*smaller*/; + font-weight: bold; + text-align: left; + /* position: fixed; */ + top: 100pt; + left: 0pt; /* auto; */ + width: 120pt; + /* right: auto; + right: 0pt; 2em; */ +} + + +div.history a { + /* font-size: 70%; */ +} + +div.wikiactiontitle { + font-weight: bold; +} + +/* REST defines */ + +div.document { + margin: 0; +} + +h1.title { + margin: 0; +} + +td.toplist { + vertical-align: top; +} + +img#pyimg { + position: absolute; + top: 4px; + left: 4px; +} + +div#navspace { + position: absolute; + top: 130px; + left: 11px; + font-size: 100%; + width: 150px; + overflow: hidden; /* scroll; */ +} + +div#metaspace { + position: absolute; + top: 40px; + left: 170px; +} + +div#errorline { + position: relative; + top: 5px; + float: right; +} + +div#contentspace { + position: absolute; + /* font: 120% "Times New Roman", serif;*/ + font: 110% Verdana, Helvetica, Arial, sans-serif; + top: 130px; + left: 170px; + margin-right: 5px; +} + +div#menubar { +/* width: 400px; */ + float: left; +} + +/* for the documentation page */ +div#docinfoline { + position: relative; + top: 5px; + left: 0px; + + /*background-color: #dee7ec; */ + padding: 5pt; + padding-bottom: 1em; + color: black; + /*border-width: 1pt; + border-style: solid;*/ + +} + +div#docnavlist { + /*background-color: #dee7ec; */ + padding: 5pt; + padding-bottom: 2em; + color: black; + border-width: 1pt; + /*border-style: solid;*/ +} + + +/* text markup */ + +div.listtitle { + color: Black; + clear: left; + font: 120% Verdana, Helvetica, Arial, sans-serif; + margin: 0; + padding-left: 0em; + padding-top: 0em; + padding-bottom: 0.2em; + margin-right: 0.5em; + border-bottom: 1px solid #8CACBB; +} + +div.actionbox h3 { + padding-top: 0; + padding-right: 0.5em; + padding-left: 0.5em; + background-color: #fabf00; + text-align: center; + border: 1px solid black; /* 8cacbb; */ +} + +div.actionbox a { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; +} + +div.actionbox a.history { + display: block; + padding-bottom: 0.5em; + padding-top: 0.5em; + margin-left: 0.5em; + font-size: 90%; +} + +div.actionbox { + margin-bottom: 2em; + padding-bottom: 1em; + overflow: hidden; /* scroll; */ +} + +/* taken from docutils (oh dear, a bit senseless) */ +ol.simple, ul.simple { + margin-bottom: 1em } + +ol.arabic { + list-style: decimal } + +ol.loweralpha { + list-style: lower-alpha } + +ol.upperalpha { + list-style: upper-alpha } + +ol.lowerroman { + list-style: lower-roman } + +ol.upperroman { + list-style: upper-roman } + + +/* +:Author: David Goodger +:Contact: goodger at users.sourceforge.net +:date: $Date: 2003/01/22 22:26:48 $ +:version: $Revision: 1.29 $ +:copyright: This stylesheet has been placed in the public domain. + +Default cascading style sheet for the HTML output of Docutils. +*/ +/* +.first { + margin-top: 0 } + +.last { + margin-bottom: 0 } + +a.toc-backref { + text-decoration: none ; + color: black } + +dd { + margin-bottom: 0.5em } + +div.abstract { + margin: 2em 5em } + +div.abstract p.topic-title { + font-weight: bold ; + text-align: center } + +div.attention, div.caution, div.danger, div.error, div.hint, +div.important, div.note, div.tip, div.warning { + margin: 2em ; + border: medium outset ; + padding: 1em } + +div.attention p.admonition-title, div.caution p.admonition-title, +div.danger p.admonition-title, div.error p.admonition-title, +div.warning p.admonition-title { + color: red ; + font-weight: bold ; + font-family: sans-serif } + +div.hint p.admonition-title, div.important p.admonition-title, +div.note p.admonition-title, div.tip p.admonition-title { + font-weight: bold ; + font-family: sans-serif } + +div.dedication { + margin: 2em 5em ; + text-align: center ; + font-style: italic } + +div.dedication p.topic-title { + font-weight: bold ; + font-style: normal } + +div.figure { + margin-left: 2em } + +div.footer, div.header { + font-size: smaller } + +div.system-messages { + margin: 5em } + +div.system-messages h1 { + color: red } + +div.system-message { + border: medium outset ; + padding: 1em } + +div.system-message p.system-message-title { + color: red ; + font-weight: bold } + +div.topic { + margin: 2em } + +h1.title { + text-align: center } + +h2.subtitle { + text-align: center } + +hr { + width: 75% } + +p.caption { + font-style: italic } + +p.credits { + font-style: italic ; + font-size: smaller } + +p.label { + white-space: nowrap } + +p.topic-title { + font-weight: bold } + +pre.address { + margin-bottom: 0 ; + margin-top: 0 ; + font-family: serif ; + font-size: 100% } + +pre.line-block { + font-family: serif ; + font-size: 100% } + +pre.literal-block, pre.doctest-block { + margin-left: 2em ; + margin-right: 2em ; + background-color: #eeeeee } + +span.classifier { + font-family: sans-serif ; + font-style: oblique } + +span.classifier-delimiter { + font-family: sans-serif ; + font-weight: bold } + +span.interpreted { + font-family: sans-serif } + +span.option { + white-space: nowrap } + +span.option-argument { + font-style: italic } + +span.pre { + white-space: pre } + +span.problematic { + color: red } + +table { + margin-top: 0.5em ; + margin-bottom: 0.5em } + +table.citation { + border-left: solid thin gray ; + padding-left: 0.5ex } + +table.docinfo { + margin: 2em 4em } + +table.footnote { + border-left: solid thin black ; + padding-left: 0.5ex } + +td, th { + padding-left: 0.5em ; + padding-right: 0.5em ; + vertical-align: top } + +th.docinfo-name, th.field-name { + font-weight: bold ; + text-align: left ; + white-space: nowrap } + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + font-size: 100% } + +tt { + background-color: #eeeeee } + +ul.auto-toc { + list-style-type: none } +*/ + +div.section { + margin-top: 1.0em ; +} From hpk at codespeak.net Tue Jul 19 13:53:01 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 13:53:01 +0200 (CEST) Subject: [pypy-svn] r14763 - pypy/dist/pypy/documentation Message-ID: <20050719115301.4BEF427B48@code1.codespeak.net> Author: hpk Date: Tue Jul 19 13:53:00 2005 New Revision: 14763 Modified: pypy/dist/pypy/documentation/getting_started.txt Log: fixed a wrong link Modified: pypy/dist/pypy/documentation/getting_started.txt ============================================================================== --- pypy/dist/pypy/documentation/getting_started.txt (original) +++ pypy/dist/pypy/documentation/getting_started.txt Tue Jul 19 13:53:00 2005 @@ -283,7 +283,7 @@ from the lib-python-2.3.4/test directory. -.. _`installed py.test`: http://codespeak.net/py/current/doc/getting_started.html +.. _`installed py.test`: http://codespeak.net/py/current/doc/getting-started.html Demos +++++ From hpk at codespeak.net Tue Jul 19 14:06:17 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 14:06:17 +0200 (CEST) Subject: [pypy-svn] r14764 - pypy/dist/pypy/documentation Message-ID: <20050719120617.1184627B55@code1.codespeak.net> Author: hpk Date: Tue Jul 19 14:06:15 2005 New Revision: 14764 Modified: pypy/dist/pypy/documentation/_ref.txt pypy/dist/pypy/documentation/coding-guide.txt pypy/dist/pypy/documentation/index.txt pypy/dist/pypy/documentation/interpreter.txt Log: issue66 in-progress implemented a first draft of the interpreter documentation still missing bits and pieces (it's a bit hard to draw the lines). also fixed some links here and there and inserted the bytecode interpreter into the index.txt. feedback already welcome. Modified: pypy/dist/pypy/documentation/_ref.txt ============================================================================== --- pypy/dist/pypy/documentation/_ref.txt (original) +++ pypy/dist/pypy/documentation/_ref.txt Tue Jul 19 14:06:15 2005 @@ -8,6 +8,14 @@ .. _`documentation/website/`: http://codespeak.net/svn/pypy/dist/pypy/documentation/website .. _`pypy/interpreter`: .. _`interpreter/`: http://codespeak.net/svn/pypy/dist/pypy/interpreter +.. _`pypy/interpreter/argument.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/argument.py +.. _`pypy/interpreter/function.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/function.py +.. _`pypy/interpreter/gateway.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/gateway.py +.. _`pypy/interpreter/generator.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/generator.py +.. _`pypy/interpreter/mixedmodule.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/mixedmodule.py +.. _`pypy/interpreter/nestedscope.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/nestedscope.py +.. _`pypy/interpreter/pyopcode.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py +.. _`pypy/interpreter/typedef.py`: http://codespeak.net/svn/pypy/dist/pypy/interpreter/typedef.py .. _`lib/`: .. _`pypy/lib/`: http://codespeak.net/svn/pypy/dist/pypy/lib .. _`lib/test2/`: @@ -26,8 +34,8 @@ .. _`pypy/objspace/std`: .. _`objspace/std/`: http://codespeak.net/svn/pypy/dist/pypy/objspace/std .. _`objspace/thunk.py`: http://codespeak.net/svn/pypy/dist/pypy/objspace/thunk.py -.. _`pypy/objspace/trace.py`: -.. _`objspace/trace.py`: http://codespeak.net/svn/pypy/dist/pypy/objspace/trace.py +.. _`objspace/trace.py`: +.. _`pypy/objspace/trace.py`: http://codespeak.net/svn/pypy/dist/pypy/objspace/trace.py .. _`rpython/`: http://codespeak.net/svn/pypy/dist/pypy/rpython .. _`rpython/lltype.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/lltype.py .. _`rpython/rint.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/rint.py @@ -40,7 +48,7 @@ .. _`pypy/translator`: .. _`translator/`: http://codespeak.net/svn/pypy/dist/pypy/translator .. _`pypy/translator/annrpython.py`: http://codespeak.net/svn/pypy/dist/pypy/translator/annrpython.py -.. _`translator/genc/`: http://codespeak.net/svn/pypy/dist/pypy/translator/genc +.. _`translator/c/`: http://codespeak.net/svn/pypy/dist/pypy/translator/c .. _`translator/java/`: http://codespeak.net/svn/pypy/dist/pypy/translator/java .. _`translator/llvm/`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm .. _`translator/tool/`: http://codespeak.net/svn/pypy/dist/pypy/translator/tool \ No newline at end of file Modified: pypy/dist/pypy/documentation/coding-guide.txt ============================================================================== --- pypy/dist/pypy/documentation/coding-guide.txt (original) +++ pypy/dist/pypy/documentation/coding-guide.txt Tue Jul 19 14:06:15 2005 @@ -483,6 +483,7 @@ ``space.call_method(w_dict, 'iterkeys')`` returns a wrapped iterable that you can decode with ``space.unpackiterable()``. +.. _`applevel-exceptions`: Application-level exceptions ---------------------------- Modified: pypy/dist/pypy/documentation/index.txt ============================================================================== --- pypy/dist/pypy/documentation/index.txt (original) +++ pypy/dist/pypy/documentation/index.txt Tue Jul 19 14:06:15 2005 @@ -14,6 +14,9 @@ `object spaces`_ discusses the object space interface and several implementations. +`bytecode interpreter`_ explains the basic mechanisms +of the bytecode interpreter and virtual machine. + `translation`_ offers the beginnings of documentation about our low level code generator backends. @@ -35,7 +38,7 @@ .. _`revision report`: http://codespeak.net/pypy/rev/current .. _`getting started`: getting_started.html .. _`theory`: theory.html - +.. _`bytecode interpreter`: interpreter.html .. _`directory reference`: @@ -56,7 +59,7 @@ `documentation/website/`_ text versions of the navigation webpages -`interpreter/`_ bytecode interpreter and related objects (frames, functions, modules,...) +`interpreter/`_ `bytecode interpreter`_ and related objects (frames, functions, modules,...) `lib/`_ PyPy's wholesale reimplementations of CPython modules_ @@ -97,7 +100,7 @@ `translator/`_ translation_ backends and support code -`translator/genc/`_ the `GenC backend`_ producing a CPython C-extension +`translator/c/`_ the `GenC backend`_ producing a CPython C-extension module from a given RPython program. `translator/java/`_ experimental code to utilize Java for annotation @@ -114,6 +117,7 @@ level to interpreterlevel`_ code. ============================ =========================================== +.. _`bytecode interpreter`: interpreter.html .. _`translating application level to interpreterlevel`: translation.html#python-back-end .. _documentation: index.html .. _`Testing in PyPy`: coding-guide.html#testing-in-pypy Modified: pypy/dist/pypy/documentation/interpreter.txt ============================================================================== --- pypy/dist/pypy/documentation/interpreter.txt (original) +++ pypy/dist/pypy/documentation/interpreter.txt Tue Jul 19 14:06:15 2005 @@ -12,40 +12,47 @@ ============ This document describes the implementation of PyPy's -`Bytecode Interpreter`_ and related basic VM functionalities. +`Bytecode Interpreter`_ and related Virtual Machine functionalities. Overview ============ PyPy's bytecode interpreter has a structure reminiscent of -CPython's VM implementation: Source code is parsed and -compiled into code objects which encapsulate information about -their respective functions, class and module body source -codes. Interpreting such code objects means instantiating and +CPython's Virtual Machine: Source code is parsed and compiled +into code objects which encapsulate information about their +respective functions, class and module body source codes. +Interpreting such code objects means instantiating and initializing a `Frame class`_ and then calling its ``frame.eval()`` method. This entry point then interprets each bytecode. -The bytecode interpreter is only responsible for implementing -control flow and putting and pulling black box objects to and -from the value stack. It does not know how to perform -operations on those black box (`wrapped`_) objects for which -it defers to the `object space`_. In order to implement a -branch in a program's execution, however, it needs to gain -minimal knowledge about a wrapped object. Thus, each object -space offers a ``is_true(w_obj)`` method which returns an -interpreter-level boolean value. +CPython as well as PyPy are stack-based virtual machines, i.e. +they don't have registers but put object to and pull objects +from a stack. The bytecode interpreter is only responsible +for implementing control flow and putting and pulling black +box objects to and from the value stack. It does not know how +to perform operations on those black box (`wrapped`_) objects +for which it delegates to the `object space`_. In order to +implement a branch in a program's execution, however, it needs +to gain minimal knowledge about a wrapped object. Thus, each +object space has to offer a ``is_true(w_obj)`` operation which +returns an interpreter-level boolean value. For the understanding of the interpreter's inner workings it is crucial to recognize the concepts of `interpreter-level and application-level`_ code. In short, interpreter-level is executed directly on the machine and invoking application-level functions -leads to the full prescribed bytecode interpretation indirection. +leads to an bytecode interpretation indirection. However, +special care must be taken regarding exceptions because +application level exceptions are wrapped into ``OperationErrors`` +which are thus distinguished from plain interpreter-level exceptions. +See `application level exceptions`_ for some more information +on ``OperationErrors``. The interpreter implementation offers mechanisms to allow a caller to be unaware if a particular function invocation leads to bytecode interpretation or is executed directly at -intepreter-level. The two basic kinds of `Gateway classes`_ +interpreter-level. The two basic kinds of `Gateway classes`_ expose either an interpreter-level function to application-level execution (``interp2app``) or allow transparent invocation of application-level helpers @@ -54,51 +61,319 @@ Another task of the interpreter is to expose its basic code, frame, module and function objects to application-level code. Such runtime introspection and modification abilities are -implemented via descriptors. +implemented via `interpreter descriptors`_ (also see Raymond Hettingers +`how-to guide for descriptors`_ in Python, PyPy uses this model extensively). -A significant complexity lies in the `argument parsing`_ -implementation. Python as a language offers very flexible -ways of providing and receiving arguments for a particular -function invocation. Not only does it take care to get this -right, it also presents difficulties for the `annotation +A significant complexity lies in `argument parsing`_. Python as a +language offers very flexible ways of providing and receiving arguments +for a particular function invocation. Not only does it take special care +to get this right, it also presents difficulties for the `annotation pass`_ which performs a whole-program analysis on the -bytecode interpreter, argument parsing and gateway-code -in order to infer the types of all values. +bytecode interpreter, argument parsing and gatewaying code +in order to infer the types of all flowing values. -It is for this reason that PyPy sometimes resorts to generate +It is for this reason that PyPy resorts to generate specialized frame classes and functions at `initialization time`_ in order to let the annotator only see static program flows with homogenous name-value assignments on e.g. function invocations. +.. _`how-to guide for descriptors`: http://users.rcn.com/python/download/Descriptor.htm .. _`annotation pass`: translation.html#the-annotation-pass .. _`initialization time`: architecture.html#initialization-time .. _`interpreter-level and application-level`: architecture.html#interpreter-level .. _`wrapped`: coding-guide.html#wrapping-rules .. _`object space`: architecture.html#objectspace +.. _`application level exceptions`: coding-guide.html#applevel-exceptions + + +Interpreter Implementation Classes +====================================== .. _`Frame class`: +.. _`Frame`: Frame classes -======================== -XXX +----------------- -the eval loop ---------------------- +The concept of Frames is pervasive in executing programs and +virtual machines in particular. They are sometimes called +*execution frame* because they hold crucial information +regarding the execution of a Code_ object, which in turn is +often directly related to a Python `Function`_. Frame +instances hold the following state: + +- the local scope holding name-value bindings, usually implemented + via a "fast scope" which is an array of wrapped objects + +- a blockstack which has (nested) information regarding the + control flow of a function (such as ``while`` and ``try`` constructs) + +- a value stack where bytecode interpretation pulls object + from and puts results on. + +- a reference to the *globals* dictionary, containing + module-level name-value bindings + +- debugging information from which a current line-number and + file location can be constructed for tracebacks + +Moreover the Frame class itself has a number of methods which implement +the actual bytecodes found in a code object. In fact, PyPy already constructs +four specialized Frame class variants depending on the code object: + +- PyInterpFrame (in `pypy/interpreter/pyopcode.py`_) for + basic simple code objects (not involving generators or nested scopes) + +- PyNestedScopeFrame (in `pypy/interpreter/nestedscope.py`_) + for code objects that reference nested scopes, inherits from PyInterpFrame + +- PyGeneratorFrame (in `pypy/interpreter/generator.py`_) + for code objects that yield values to the caller, inherits from PyInterpFrame + +- PyNestedScopeGeneratorFrame for code objects that reference + nested scopes and yield values to the caller, inherits from both PyNestedScopeFrame + and PyGeneratorFrame + +.. _Code: + +Code Class +------------ + +PyPy's code objects contain the same information found in CPython's code objects. +the differ from Function_ objects in that they are only immutable representations +of source code and don't contain execution state or references to the execution +environment found in `Frames`. Frames and Functions have references +to a code object. Here is a list of Code attributes: + +* ``co_flags`` flags if this code object has nested scopes/generators +* ``co_stacksize`` flags if this code object has nested scopes/generators +* ``co_code`` the actual bytecode string + +* ``co_argcount`` number of arguments this code object expects +* ``co_varnames`` a tuple of all argument names pass to this code object +* ``co_nlocals`` number of local variables +* ``co_names`` a tuple of all names used in the code object +* ``co_consts`` a tuple of prebuilt constant objects ("literals") used in the code object +* ``co_cellvars`` a tuple of Cells containing values for access from nested scopes +* ``co_freevars`` a tuple of Cell names from "above" scopes + +* ``co_filename`` source file this code object was compiled from +* ``co_firstlineno`` the first linenumber of the code object in its source file +* ``co_name`` name of the code object (often the function name) +* ``co_lnotab`` a helper table to compute the line-numbers corresponding to bytecodes + +In PyPy, code objects also have the responsibility of creating their Frame_ objects +via the `'create_frame()`` method. With proper parser and compiler support this should +allow to create custom Frame objects extending the execution of functions +in various ways. The several Frame_ classes already utilize this flexibility +in order to implement Generators and Nested Scopes. + +.. _Function: + +Function and Method classes +---------------------------- + +The PyPy ``Function`` class (in `pypy/interpreter/function.py`_) +represents a Python function. A ``Function`` carries the following +main attributes: + +* ``func_doc`` the docstring (or None) +* ``func_name`` the name of the function +* ``func_code`` the Code_ object representing the function source code +* ``func_defaults`` default values for the function (built at function definition time) +* ``func_dict`` dictionary for additional (user-defined) function attributes +* ``func_globals`` reference to the globals dictionary +* ``func_closure`` a tuple of Cell references + +``Functions`` classes also provide a ``__get__`` descriptor which creates a Method +object holding a binding to an instance or a class. Finally, ``Functions`` +and ``Methods`` both offer a ``call_args()`` method which executes +the function given an `Arguments`_ class instance. +.. _Arguments: .. _`argument parsing`: -Argument Parsing -======================= +Arguments Class +-------------------- + +The Argument class (in `pypy/interpreter/argument.py`_) is +responsible for parsing arguments passed to functions. +Python has rather complex argument-passing concepts: + +- positional arguments + +- keyword arguments specified by name + +- default values for positional arguments, defined at function + definition time + +- "star args" allowing a function to accept remaining + positional arguments + +- "star keyword args" allow a function to accept additional + arbitrary name-value bindings -XXX +Moreover, a Function_ object can get bound to a class or instance +in which case the first argument to the underlying function becomes +the bound object. The ``Arguments`` provides means to allow all +this argument parsing and also cares for error reporting. + + +.. _`Module`: + +Module Class +------------------- + +A ``Module`` instance represents execution state usually constructed +from executing the module's source file. In addition to such a module's +global ``__dict__`` dictionary it has the following application level +attributes: + +* ``__doc__`` the docstring of the module +* ``__file__`` the source filename from which this module was instantiated +* ``__path__`` state used for relative imports + +Apart from the basic Module used for importing application-level files +there is a more refined ``MixedModule`` class (see `pypy/interpreter/mixedmodule.py`_) +which allows to define name-value bindings both at application level +and an intepreter level. See the ``__builtin__`` module's +`pypy/module/__builtin__/__init__.py`_ file for an example +and the higher level `chapter on Modules in the coding guide`_. + +.. _`__builtin__ module`: http://codespeak.net/svn/pypy/dist/pypy/module/ +.. _`chapter on Modules in the coding guide`: coding-guide.html#modules .. _`Gateway classes`: Gateway classes -======================= - -XXX +---------------------- +A unique PyPy property is the ability to easily cross the barrier +between interpreted code and machine-level code. Both codes are +implemented via Python source code but they usually look differently. +Be aware that the according code (in `pypy/interpreter/gateway.py`_) +for crossing the barrier in both directions is somewhat involved, mostly +due to the fact that the type-infering annotator needs to keep +track of the types of objects flowing across those barriers. + +Making interpreter-level functions available at application-level ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +In order to make an interpreter-level function available at +application level, one invokes ``pypy.interpreter.gateway.interp2app(func)``. +Such a function usually takes a ``space`` argument and any number +of positional arguments. Additionally, such functions can define +an ``unwrap_spec`` telling the ``interp2app`` logic how +application-level provided arguments should be unwrapped +before the actual interpreter-level function is invoked. +For example, `interpreter descriptors`_ such as the ``Module.__new__`` +method for allocating and constructing a Module instance is +defined with this code:: + + Module.typedef = TypeDef("module", + __new__ = interp2app(Module.descr_module__new__.im_func, + unwrap_spec=[ObjSpace, W_Root, Arguments]), + __init__ = interp2app(Module.descr_module__init__), + # module dictionaries are readonly attributes + __dict__ = GetSetProperty(descr_get_dict, cls=Module), + __doc__ = 'module(name[, doc])\n\nCreate a module object...' + ) + +The actual ``Module.descr_module__new__`` interpreter-level method +referenced from the ``__new__`` keyword argument above is defined +like this:: + + def descr_module__new__(space, w_subtype, __args__): + module = space.allocate_instance(Module, w_subtype) + Module.__init__(module, space, None) + return space.wrap(module) + +Summarizing, the ``interp2app`` mechanism takes care to route +an application level access or call to an internal interpreter-level +object appropriately to the descriptor, providing enough precision +and hints to keep the type-infering annotator happy. + + +Calling into application level code from interpreter-level ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Application level code is `often preferable`_. Therefore, +we often like to invoke application level code from interpreter-level. +This is done via the Gateway's ``app2interp`` mechanism +which we usually invoke at definition time in a module. +It generates a hook which looks like an intepreter-level +function accepting a space and an arbitrary number of arguments. +When calling a function at interpreter-level the caller side +does usually not need to be aware if its invoked function +is run through the PyPy interpreter or if it will directly +execute on the machine (after translation). + +Here is an example showing how we implement the Metaclass +finding algorithm of the Python language in PyPy:: + + app = gateway.applevel(r''' + def find_metaclass(bases, namespace, globals, builtin): + if '__metaclass__' in namespace: + return namespace['__metaclass__'] + elif len(bases) > 0: + base = bases[0] + if hasattr(base, '__class__'): + return base.__class__ + else: + return type(base) + elif '__metaclass__' in globals: + return globals['__metaclass__'] + else: + try: + return builtin.__metaclass__ + except AttributeError: + return type + ''', filename=__file__) + + find_metaclass = app.interphook('find_metaclass') + +The ``find_metaclass`` interpreter-level hook is invoked +with five arguments from the ``BUILD_CLASS`` opcode implementation +in `pypy/interpreter/pyopcode.py`_:: + + def BUILD_CLASS(f): + w_methodsdict = f.valuestack.pop() + w_bases = f.valuestack.pop() + w_name = f.valuestack.pop() + w_metaclass = find_metaclass(f.space, w_bases, + w_methodsdict, f.w_globals, + f.space.wrap(f.builtin)) + w_newclass = f.space.call_function(w_metaclass, w_name, + w_bases, w_methodsdict) + f.valuestack.push(w_newclass) + +Note that at a later point we might rewrite the ``find_metaclass`` +implementation at interpreter-level but we would not have +to modify the calling sides at all. + +.. _`often preferable`: architecture.html#app-preferable +.. _`interpreter descriptors`: + +Introspection and Descriptors +------------------------------ + +Python traditionally has a very far-reaching introspection model +for interpreter related objects. In PyPy and in CPython read +and write accesses to such objects are routed to descriptors. +Of course, in CPython those are implemented in ``C`` while in +PyPy they are implemented in interpreter-level Python code. + +All instances of a Function_, Code_, Frame_ or Module_ class +are ``Wrappable`` instances and can thus be represented at +application level. These days, a PyPy object space needs to +work with a basic descriptor lookup when it encounters +accesses to an interpreter-level object. An object space ask +a wrapped object for its type via a ``getclass`` method and then +calls its ``lookup(name)`` function in order to receive a descriptor function. +Most of PyPy's internal object descriptors are defined at the +end of `pypy/interpreter/typedef.py`_. You can use this as a reference +for the exact attributes visible at application level. +.. include:: _ref.txt From hpk at codespeak.net Tue Jul 19 14:09:19 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 14:09:19 +0200 (CEST) Subject: [pypy-svn] r14765 - pypy/dist/pypy/documentation Message-ID: <20050719120919.94D0B27B55@code1.codespeak.net> Author: hpk Date: Tue Jul 19 14:09:18 2005 New Revision: 14765 Modified: pypy/dist/pypy/documentation/interpreter.txt Log: merged introduction and overview Modified: pypy/dist/pypy/documentation/interpreter.txt ============================================================================== --- pypy/dist/pypy/documentation/interpreter.txt (original) +++ pypy/dist/pypy/documentation/interpreter.txt Tue Jul 19 14:09:18 2005 @@ -8,15 +8,12 @@ .. _`Bytecode Interpreter`: architecture.html#the-bytecode-interpreter -Introduction -============ +Introduction and Overview +=============================== This document describes the implementation of PyPy's `Bytecode Interpreter`_ and related Virtual Machine functionalities. -Overview -============ - PyPy's bytecode interpreter has a structure reminiscent of CPython's Virtual Machine: Source code is parsed and compiled into code objects which encapsulate information about their From cfbolz at codespeak.net Tue Jul 19 14:25:54 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Jul 2005 14:25:54 +0200 (CEST) Subject: [pypy-svn] r14766 - pypy/dist/pypy/documentation Message-ID: <20050719122554.061C527B50@code1.codespeak.net> Author: cfbolz Date: Tue Jul 19 14:25:53 2005 New Revision: 14766 Modified: pypy/dist/pypy/documentation/translation.txt Log: removed documentation about llvm1 Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Tue Jul 19 14:25:53 2005 @@ -864,130 +864,9 @@ The LLVM Back-End ================= -http://codespeak.net/svn/pypy/dist/pypy/translator/llvm/ +http://codespeak.net/svn/pypy/dist/pypy/translator/llvm2/ - -Overview --------- - -Note that the LLVM back-end is in a state of constant flux and thus this are -preliminary notes only. - -The task of GenLLVM is to convert a flow graph into `LLVM code`_, which can -then be optimized and compiled by LLVM. GenLLVM depends heavily on the -annotations, functions without annotations cannot be translated. The flowgraph -is not changed by GenLLVM in contrast to GenC. After the generation and -compilation of the LLVM code a wrapper is generated (at the moment with the -help of Pyrex) wich performs the conversion of arguments and return value of -the entry function to the types used by LLVM. Thus it is possible to call the -entry function from Python. - -GenLLVM does not depend on the CPython runtime which has the drawback that most -functions with SomeObject annotations cannot be compiled properly -- the only -operations that are allowed on variables with SomeObject annotations are -``isinstance`` and ``type``. - -GenLLVM creates for every object in the flow graph (e.g. constants, variables, -blocks...) an LLVM 'representation'. This representation knows how to -represent the corresponding object in LLVM and knows what code to generate for -space operations on the object, what global definitions the object needs etc. - -Some examples to make this clearer: A `ClassRepr`_ object represents a class, a -`FuncRepr`_ object represent a function (or method). The following happens if -the space operation ``simple_call`` is performed on a function: An appropriate -``FuncRepr`` object is constructed which generates LLVM code for the function -it represents. Then the ``FuncRepr`` inserts the appropriate LLVM instructions -into the LLVM code of the function it is called from (sometime this is more -than just a call: the arguments have to be casted, etc). Something similar -happens if a class is instantiated: A ``ClassRepr`` is created which then -generates LLVM code that allocates enough memory for an instance of the class -and then (if the class or a base class has an ``__init__`` method) tells the -``FuncRepr`` of the appropriate ``__init__`` method to generate the code for -the call to it. - -Every representation object has some other representations it depends on: A -``ListRepr`` of lists instances of a class depends on the ``ClassRepr`` of -that class. To ensure that the typedef of the class is written to the llvm -file before the typedef of the list, the dependency tree of representations -traversed depth first when the LLVM code is written to a file. - -.. _`LLVM code`: http://www.llvm.org -.. _`ClassRepr`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm/classrepr.py -.. _`FuncRepr`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm/funcrepr.py - - -Details about the representations ---------------------------------- - -Simple representations -++++++++++++++++++++++ - -There are some objects that have direct counterparts in LLVM: ints, floats, -chars (strings of length 1), bools. Most space operations involving those are -implemented as `tiny function`_ (LLVM doesn't support macros since LLVM's .ll -files correspond directly to its bytecode format so that round trip -conversions are nearly lossless). These are so simple that they are always -inlined by the LLVM optimizer so this doesn't lead to any performance penalty. - - -Function representation -+++++++++++++++++++++++ - -The representation of function in LLVM code is relatively easy since LLVM as -well as flow graph use SSA form. Furthermore LLVM supports exactly the kind of -control structures that the flow graphs feature: A function consists of basic -blocks that end with links to other blocks, data flows along these links. The -data flow is handled in LLVM by phi nodes: at the beginning of every block phi -nodes may be inserted. Those determine the value of a variable depending on -which block branched to the currect block. Example:: - - block1: - %b = phi int [1, %block0], [2, %block2] - -Here %b is 1 if control came from block0 and 2 if control came from block2. - -The following code is generated for the function ``g`` defined above_:: - - int %g(int %n1) { - block0: - br label %block1 - block1: - %n2 = phi int [%n1, %block0], [%m3, %block3] - %i2 = phi int [0, %block0], [%j3, %block3] - %v2 = call bool %std.is_true(int %n2) - br bool %v2, label %block3, label %block2 - block2: - %i4 = phi int [%i2, %block1] - ret int %i4 - block3: - %n3 = phi int [%n2, %block1] - %i3 = phi int [%i2, %block1] - %j3 = call int %std.add(int %i3, int %n3) - %m3 = call int %std.sub(int %n3, int 1) - br label %block1 - } - -Note how the phi nodes correspond to the links in the control flow graph. - -List representation -+++++++++++++++++++ - -Lists are represented as arrays. The code for the basic operation on lists -(``getitem``, ``setitem``, ``add``, ``mul``, ``append``, ``pop``...) is -`written in C`_. This C code is then compiled to LLVM code with the help of -the LLVM C-front-end. The resulting LLVM code is then transformed (with search -and replace) to fit in with the rest of GenLLVM. To support lists with -different types of items the C code implements lists as arrays of pointers to -``item``, where ``item`` is a dummy struct that is replaced with whatever type -is wanted. - - -XXX More to come. - - - -.. _`tiny function`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm/operations.ll -.. _`written in C`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm/list.c +XXX to be written .. _`Python again`: .. _`Python back-end`: From cfbolz at codespeak.net Tue Jul 19 14:45:54 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Jul 2005 14:45:54 +0200 (CEST) Subject: [pypy-svn] r14767 - pypy/dist/pypy/translator Message-ID: <20050719124554.64E5527B49@code1.codespeak.net> Author: cfbolz Date: Tue Jul 19 14:45:53 2005 New Revision: 14767 Modified: pypy/dist/pypy/translator/translator.py Log: changed Translator to use llvm2: preparing removal of old llvm. Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Tue Jul 19 14:45:53 2005 @@ -199,11 +199,11 @@ Returns LLVM translation. """ - from pypy.translator.llvm import genllvm + from pypy.translator.llvm2 import genllvm if self.annotator is None: - raise genllvm.CompileError, "function has to be annotated." - gen = genllvm.LLVMGenerator(self) - return str(gen) + raise ValueError, "function has to be annotated." + gen = genllvm.GenLLVM(self) + return str(gen.compile()) def generatecode(self, gencls, input_arg_types, func): if input_arg_types is None: @@ -269,11 +269,10 @@ Returns LLVM translation with or without optimization. """ - from pypy.translator.llvm import genllvm + from pypy.translator.llvm2 import genllvm if self.annotator is None: - raise genllvm.CompileError, "function has to be annotated." - gen = genllvm.LLVMGenerator(self) - return gen.compile(optimize) + raise ValueError, "function has to be annotated." + return genllvm.genllvm(self) def call(self, *args): """Calls underlying Python function.""" From cfbolz at codespeak.net Tue Jul 19 14:59:31 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Jul 2005 14:59:31 +0200 (CEST) Subject: [pypy-svn] r14768 - pypy/dist/pypy/translator/llvm Message-ID: <20050719125931.6BB1427B53@code1.codespeak.net> Author: cfbolz Date: Tue Jul 19 14:59:30 2005 New Revision: 14768 Removed: pypy/dist/pypy/translator/llvm/ Log: removing the old llvm backend, which should no longer be used. It was quite broken since I tried to refactor it to use lltypes. For the record: the last revision where it worked was r12313. From cfbolz at codespeak.net Tue Jul 19 15:45:19 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 19 Jul 2005 15:45:19 +0200 (CEST) Subject: [pypy-svn] r14773 - pypy/dist/pypy/documentation Message-ID: <20050719134519.2652327B49@code1.codespeak.net> Author: cfbolz Date: Tue Jul 19 15:45:18 2005 New Revision: 14773 Modified: pypy/dist/pypy/documentation/interpreter.txt Log: fixed some typos and changed wrong description for co_stacksize (thanks mwh, pedronis) Modified: pypy/dist/pypy/documentation/interpreter.txt ============================================================================== --- pypy/dist/pypy/documentation/interpreter.txt (original) +++ pypy/dist/pypy/documentation/interpreter.txt Tue Jul 19 15:45:18 2005 @@ -139,13 +139,13 @@ ------------ PyPy's code objects contain the same information found in CPython's code objects. -the differ from Function_ objects in that they are only immutable representations +They differ from Function_ objects in that they are only immutable representations of source code and don't contain execution state or references to the execution environment found in `Frames`. Frames and Functions have references to a code object. Here is a list of Code attributes: * ``co_flags`` flags if this code object has nested scopes/generators -* ``co_stacksize`` flags if this code object has nested scopes/generators +* ``co_stacksize`` the maximum depth the stack can reach while executing the code * ``co_code`` the actual bytecode string * ``co_argcount`` number of arguments this code object expects @@ -235,7 +235,7 @@ Apart from the basic Module used for importing application-level files there is a more refined ``MixedModule`` class (see `pypy/interpreter/mixedmodule.py`_) which allows to define name-value bindings both at application level -and an intepreter level. See the ``__builtin__`` module's +and at intepreter level. See the ``__builtin__`` module's `pypy/module/__builtin__/__init__.py`_ file for an example and the higher level `chapter on Modules in the coding guide`_. From hpk at codespeak.net Tue Jul 19 16:00:50 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 16:00:50 +0200 (CEST) Subject: [pypy-svn] r14774 - pypy/dist/pypy/documentation Message-ID: <20050719140050.3B09527B50@code1.codespeak.net> Author: hpk Date: Tue Jul 19 16:00:49 2005 New Revision: 14774 Modified: pypy/dist/pypy/documentation/interpreter.txt Log: fix typos and grammar a bit (my favourite typo is 'intepreter') Modified: pypy/dist/pypy/documentation/interpreter.txt ============================================================================== --- pypy/dist/pypy/documentation/interpreter.txt (original) +++ pypy/dist/pypy/documentation/interpreter.txt Tue Jul 19 16:00:49 2005 @@ -235,7 +235,7 @@ Apart from the basic Module used for importing application-level files there is a more refined ``MixedModule`` class (see `pypy/interpreter/mixedmodule.py`_) which allows to define name-value bindings both at application level -and at intepreter level. See the ``__builtin__`` module's +and at interpreter level. See the ``__builtin__`` module's `pypy/module/__builtin__/__init__.py`_ file for an example and the higher level `chapter on Modules in the coding guide`_. @@ -266,8 +266,8 @@ application-level provided arguments should be unwrapped before the actual interpreter-level function is invoked. For example, `interpreter descriptors`_ such as the ``Module.__new__`` -method for allocating and constructing a Module instance is -defined with this code:: +method for allocating and constructing a Module instance are +defined with such code:: Module.typedef = TypeDef("module", __new__ = interp2app(Module.descr_module__new__.im_func, @@ -300,7 +300,7 @@ we often like to invoke application level code from interpreter-level. This is done via the Gateway's ``app2interp`` mechanism which we usually invoke at definition time in a module. -It generates a hook which looks like an intepreter-level +It generates a hook which looks like an interpreter-level function accepting a space and an arbitrary number of arguments. When calling a function at interpreter-level the caller side does usually not need to be aware if its invoked function @@ -312,21 +312,21 @@ app = gateway.applevel(r''' def find_metaclass(bases, namespace, globals, builtin): - if '__metaclass__' in namespace: - return namespace['__metaclass__'] + if '__metaclass__' in namespace: + return namespace['__metaclass__'] elif len(bases) > 0: - base = bases[0] + base = bases[0] if hasattr(base, '__class__'): return base.__class__ else: return type(base) elif '__metaclass__' in globals: - return globals['__metaclass__'] + return globals['__metaclass__'] else: - try: - return builtin.__metaclass__ + try: + return builtin.__metaclass__ except AttributeError: - return type + return type ''', filename=__file__) find_metaclass = app.interphook('find_metaclass') @@ -346,9 +346,9 @@ w_bases, w_methodsdict) f.valuestack.push(w_newclass) -Note that at a later point we might rewrite the ``find_metaclass`` -implementation at interpreter-level but we would not have -to modify the calling sides at all. +Note that at a later point we can rewrite the ``find_metaclass`` +implementation at interpreter-level and we would not have +to modify the calling side at all. .. _`often preferable`: architecture.html#app-preferable .. _`interpreter descriptors`: @@ -362,15 +362,16 @@ Of course, in CPython those are implemented in ``C`` while in PyPy they are implemented in interpreter-level Python code. -All instances of a Function_, Code_, Frame_ or Module_ class -are ``Wrappable`` instances and can thus be represented at -application level. These days, a PyPy object space needs to +All instances of a Function_, Code_, Frame_ or Module_ classes +are also ``Wrappable`` instances which means they can be represented +at application level. These days, a PyPy object space needs to work with a basic descriptor lookup when it encounters -accesses to an interpreter-level object. An object space ask +accesses to an interpreter-level object: an object space asks a wrapped object for its type via a ``getclass`` method and then -calls its ``lookup(name)`` function in order to receive a descriptor function. -Most of PyPy's internal object descriptors are defined at the -end of `pypy/interpreter/typedef.py`_. You can use this as a reference -for the exact attributes visible at application level. +calls the type's ``lookup(name)`` function in order to receive a descriptor +function. Most of PyPy's internal object descriptors are defined at the +end of `pypy/interpreter/typedef.py`_. You can use these definitions +as a reference for the exact attributes of interpreter classes visible +at application level. .. include:: _ref.txt From pedronis at codespeak.net Tue Jul 19 16:14:42 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 16:14:42 +0200 (CEST) Subject: [pypy-svn] r14775 - in pypy/dist/pypy: rpython translator/goal Message-ID: <20050719141442.0F4D727B50@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 16:14:38 2005 New Revision: 14775 Added: pypy/dist/pypy/translator/goal/module-list.pedronis (contents, props changed) Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/goal/order.py Log: - let use comments in the module-list and ignore blank lines - let's specify a module-list file, like RTYPEORDER=order,module-list.pedronis ... - I'm checking in my module-list as module-list.pedronis, at the end you can see modules that are known to specialize fine Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 19 16:14:38 2005 @@ -59,14 +59,17 @@ print '*' * len(s) except: self.seed = 0 - try: - self.order = __import__(os.getenv('RTYPERORDER'), {}, {}, ['*']).order + self.order = None + RTYPERORDER = os.getenv('RTYPERORDER') + if RTYPERORDER: + order_module = RTYPERORDER.split(',')[0] + self.order = __import__(order_module, {}, {}, ['*']).order s = 'Using %s.%s for order' % (self.order.__module__, self.order.__name__) print '*' * len(s) print s print '*' * len(s) - except: - self.order = None + + def getexceptiondata(self): Added: pypy/dist/pypy/translator/goal/module-list.pedronis ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/module-list.pedronis Tue Jul 19 16:14:38 2005 @@ -0,0 +1,73 @@ +# +pypy.objspace.std.listobject +pypy.objspace.std.listobject:unwrap +pypy.interpreter.argument +pypy.interpreter.baseobjspace +pypy.interpreter.compiler +pypy.interpreter.error +pypy.interpreter.eval +pypy.interpreter.executioncontext +pypy.interpreter.function +pypy.interpreter.generator +pypy.interpreter.mixedmodule +pypy.interpreter.module +pypy.interpreter.nestedscope +pypy.interpreter.pycode +pypy.interpreter.pyframe +pypy.interpreter.pytraceback +pypy.interpreter.special +pypy.interpreter.typedef +pypy.module.__builtin__ +pypy.module.__builtin__.compiling +pypy.module.__builtin__.importing +pypy.module.__builtin__.operation +pypy.module.sys +pypy.module.sys.hook +pypy.module.sys.state +pypy.module.sys.vm +pypy.module.unicodedata.function +pypy.module.unicodedata.unicodedb +pypy.objspace.descroperation +pypy.objspace.std.boolobject +pypy.objspace.std.booltype +pypy.objspace.std.default +pypy.objspace.std.dictobject +pypy.objspace.std.dictproxyobject +pypy.objspace.std.dictproxytype +pypy.objspace.std.dicttype +pypy.objspace.std.fake +pypy.objspace.std.floatobject +pypy.objspace.std.floattype +pypy.objspace.std.intobject +pypy.objspace.std.inttype +pypy.objspace.std.iterobject +pypy.objspace.std.listsort +pypy.objspace.std.listtype +pypy.objspace.std.longobject +pypy.objspace.std.longtype +pypy.objspace.std.model +pypy.objspace.std.multimethod +pypy.objspace.std.noneobject +pypy.objspace.std.objecttype +pypy.objspace.std.objspace +pypy.objspace.std.register_all +pypy.objspace.std.sliceobject +pypy.objspace.std.slicetype +pypy.objspace.std.stdtypedef +pypy.objspace.std.stringobject +pypy.objspace.std.stringtype +pypy.objspace.std.strutil +pypy.objspace.std.tupleobject +pypy.objspace.std.tupletype +pypy.objspace.std.typeobject +pypy.objspace.std.typetype +pypy.objspace.std.unicodeobject +pypy.objspace.std.unicodetype +# specialize fine: +None +posixpath +pypy._cache._exceptions_ +pypy.rpython.normalizecalls +pypy.interpreter.miscutils +pypy.interpreter.gateway +pypy.interpreter.pyopcode Modified: pypy/dist/pypy/translator/goal/order.py ============================================================================== --- pypy/dist/pypy/translator/goal/order.py (original) +++ pypy/dist/pypy/translator/goal/order.py Tue Jul 19 16:14:38 2005 @@ -1,12 +1,22 @@ import sys import os -lst = open('module-list', 'r') +RTYPERORDER = os.getenv('RTYPERORDER').split(',') +if len(RTYPERORDER) == 2: + module_list = RTYPERORDER[1] +else: + module_list = 'module-list' + +lst = open(module_list, 'r') try: - prefixes = lst.read().split() + print "reading module-list: %s" % module_list + prefixes = lst.readlines() finally: lst.close() +prefixes = [line.strip() for line in prefixes] +prefixes = [line for line in prefixes if line and not line.startswith('#')] + NOMATCH = sys.maxint def order(annotator, pending): @@ -40,7 +50,7 @@ def track(block): module = annotated[block].__module__ if module != cur_module[0]: - print "Specializing blocks in module: %s" % module + print "--- Specializing blocks in module: %s" % module cur_module[0] = module return track From hpk at codespeak.net Tue Jul 19 17:09:57 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 17:09:57 +0200 (CEST) Subject: [pypy-svn] r14776 - pypy/dist/pypy/tool/pytest Message-ID: <20050719150957.5E24027B5D@code1.codespeak.net> Author: hpk Date: Tue Jul 19 17:09:57 2005 New Revision: 14776 Modified: pypy/dist/pypy/tool/pytest/result.py Log: default to utf8 encoding for mime messages Modified: pypy/dist/pypy/tool/pytest/result.py ============================================================================== --- pypy/dist/pypy/tool/pytest/result.py (original) +++ pypy/dist/pypy/tool/pytest/result.py Tue Jul 19 17:09:57 2005 @@ -25,7 +25,7 @@ return self._headers.items() def addnamedtext(self, name, text): - assert isinstance(text, str) + assert isinstance(text, basestring) assert isinstance(name, str) self._blocknames.append(name) self._blocks[name] = text @@ -104,7 +104,7 @@ assert submsg.get_main_type() == 'text' fn = submsg.get_filename() assert fn - self.addnamedtext(fn, submsg.get_payload()) + self.addnamedtext(fn, unicode(submsg.get_payload(), 'utf8')) def ismodifiedtest(self): # XXX we need proper cross-platform paths! From hpk at codespeak.net Tue Jul 19 17:46:26 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 17:46:26 +0200 (CEST) Subject: [pypy-svn] r14777 - pypy/dist/pypy/tool/pytest/test Message-ID: <20050719154626.396B027B5F@code1.codespeak.net> Author: hpk Date: Tue Jul 19 17:46:18 2005 New Revision: 14777 Modified: pypy/dist/pypy/tool/pytest/test/test_overview.py Log: don't test for a particular test to have passed Modified: pypy/dist/pypy/tool/pytest/test/test_overview.py ============================================================================== --- pypy/dist/pypy/tool/pytest/test/test_overview.py (original) +++ pypy/dist/pypy/tool/pytest/test/test_overview.py Tue Jul 19 17:46:18 2005 @@ -18,6 +18,6 @@ meth = getattr(result, 'is'+type) assert meth() - def test_getlatest_datetime(self): - result = self.rc.getlatest('test_datetime', ok=1) - assert result + #def test_getlatest_datetime(self): + # result = self.rc.getlatest('test_datetime', ok=1) + # assert result From hpk at codespeak.net Tue Jul 19 17:54:25 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 17:54:25 +0200 (CEST) Subject: [pypy-svn] r14778 - in pypy/dist/pypy/interpreter: . test Message-ID: <20050719155425.202ED27B5F@code1.codespeak.net> Author: hpk Date: Tue Jul 19 17:54:19 2005 New Revision: 14778 Modified: pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/test/test_pyframe.py pypy/dist/pypy/interpreter/typedef.py Log: - allow 'del frame.f_trace', should fix some compliance tests - unindent a test and note that it doesn't really test much Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Tue Jul 19 17:54:19 2005 @@ -291,6 +291,9 @@ self.w_f_trace = w_trace self.f_lineno = self.get_last_lineno() + def fdel_f_trace(space, self): + self.w_f_trace = None + def fget_f_exc_type(space, self): if self.last_exception is not None: f = self.f_back Modified: pypy/dist/pypy/interpreter/test/test_pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pyframe.py (original) +++ pypy/dist/pypy/interpreter/test/test_pyframe.py Tue Jul 19 17:54:19 2005 @@ -27,6 +27,12 @@ return f.f_code assert g() is g.func_code + def test_f_trace_del(self): + import sys + f = sys._getframe() + del f.f_trace + assert f.f_trace is None + def test_f_lineno(self): def g(): import sys @@ -39,18 +45,18 @@ assert g() == [origin+3, origin+4, origin+5] def test_f_back(self): - import sys - def trace(a,b,c): return trace - def f(): - f_frame = sys._getframe() - return g(f_frame) - def g(f_frame): - g_frame = sys._getframe() - print g_frame - print g_frame.f_back - print g_frame.f_back.f_code.co_name, f_frame.f_code.co_name - sys.settrace(trace) - f() + import sys + def trace(a,b,c): return trace + def f(): + f_frame = sys._getframe() + return g(f_frame) + def g(f_frame): + g_frame = sys._getframe() + print g_frame + print g_frame.f_back + print g_frame.f_back.f_code.co_name, f_frame.f_code.co_name + sys.settrace(trace) + f() # XXX actually test something? def test_f_exc_xxx(self): import sys Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Tue Jul 19 17:54:19 2005 @@ -396,7 +396,8 @@ f_lineno = GetSetProperty(PyFrame.fget_f_lineno, PyFrame.fset_f_lineno), f_back = GetSetProperty(PyFrame.fget_f_back), f_lasti = GetSetProperty(PyFrame.fget_f_lasti), - f_trace = GetSetProperty(PyFrame.fget_f_trace, PyFrame.fset_f_trace), + f_trace = GetSetProperty(PyFrame.fget_f_trace, PyFrame.fset_f_trace, + PyFrame.fdel_f_trace), f_exc_type = GetSetProperty(PyFrame.fget_f_exc_type), f_exc_value = GetSetProperty(PyFrame.fget_f_exc_value), f_exc_traceback = GetSetProperty(PyFrame.fget_f_exc_traceback), From hpk at codespeak.net Tue Jul 19 18:22:53 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 19 Jul 2005 18:22:53 +0200 (CEST) Subject: [pypy-svn] r14780 - pypy/dist/pypy/documentation Message-ID: <20050719162253.2AF1327B5E@code1.codespeak.net> Author: hpk Date: Tue Jul 19 18:22:39 2005 New Revision: 14780 Modified: pypy/dist/pypy/documentation/_ref.txt pypy/dist/pypy/documentation/extradoc.txt pypy/dist/pypy/documentation/index.txt Log: fixed a couple of remote references (which failed the 'py.test -R' test in the documentation directory) Modified: pypy/dist/pypy/documentation/_ref.txt ============================================================================== --- pypy/dist/pypy/documentation/_ref.txt (original) +++ pypy/dist/pypy/documentation/_ref.txt Tue Jul 19 18:22:39 2005 @@ -50,5 +50,5 @@ .. _`pypy/translator/annrpython.py`: http://codespeak.net/svn/pypy/dist/pypy/translator/annrpython.py .. _`translator/c/`: http://codespeak.net/svn/pypy/dist/pypy/translator/c .. _`translator/java/`: http://codespeak.net/svn/pypy/dist/pypy/translator/java -.. _`translator/llvm/`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm +.. _`translator/llvm2/`: http://codespeak.net/svn/pypy/dist/pypy/translator/llvm2 .. _`translator/tool/`: http://codespeak.net/svn/pypy/dist/pypy/translator/tool \ No newline at end of file Modified: pypy/dist/pypy/documentation/extradoc.txt ============================================================================== --- pypy/dist/pypy/documentation/extradoc.txt (original) +++ pypy/dist/pypy/documentation/extradoc.txt Tue Jul 19 18:22:39 2005 @@ -64,7 +64,6 @@ .. _`Iron Python`: http://www.gotdotnet.com/workspaces/workspace.aspx?id=ad7acff7-ab1e-4bcb-99c0-57ac5a3a9742 .. _`transparent dynamic optimization`: http://www.hpl.hp.com/techreports/1999/HPL-1999-77.pdf .. _Dynamo: http://www.hpl.hp.com/techreports/1999/HPL-1999-78.pdf -.. _optionaltool: http://codespeak.net/pypy/index.cgi?doc/optionaltool.html .. _testdesign: http://codespeak.net/pypy/index.cgi?doc/testdesign.html .. _feasible: http://codespeak.net/pipermail/pypy-dev/2004q2/001289.html .. _rock: http://codespeak.net/pipermail/pypy-dev/2004q1/001255.html Modified: pypy/dist/pypy/documentation/index.txt ============================================================================== --- pypy/dist/pypy/documentation/index.txt (original) +++ pypy/dist/pypy/documentation/index.txt Tue Jul 19 18:22:39 2005 @@ -105,7 +105,7 @@ `translator/java/`_ experimental code to utilize Java for annotation -`translator/llvm/`_ contains the `LLVM backend`_ producing LLVM assembler +`translator/llvm2/`_ contains the `LLVM backend`_ producing LLVM assembler from fully annotated RPython programs `translator/tool/`_ helper tools for translation From pedronis at codespeak.net Tue Jul 19 18:29:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 18:29:55 +0200 (CEST) Subject: [pypy-svn] r14781 - in pypy/dist/pypy: rpython translator translator/goal Message-ID: <20050719162955.9ED2327B5D@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 18:29:37 2005 New Revision: 14781 Modified: pypy/dist/pypy/rpython/callparse.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/translator.py Log: - changes to support continuing rtyping even in the presence of errors (along the lines of this mail http://codespeak.net/pipermail/pypy-dev/2005q3/002210.html , Thanks to the poster) - '-t-insist' option for translate_pypy to continue specializing even after errors Modified: pypy/dist/pypy/rpython/callparse.py ============================================================================== --- pypy/dist/pypy/rpython/callparse.py (original) +++ pypy/dist/pypy/rpython/callparse.py Tue Jul 19 18:29:37 2005 @@ -2,8 +2,9 @@ from pypy.interpreter.argument import Arguments, ArgErr from pypy.annotation import model as annmodel from pypy.rpython import rtuple +from pypy.rpython.rmodel import TyperError -class CallPatternTooComplex(Exception): +class CallPatternTooComplex(TyperError): pass @@ -47,7 +48,7 @@ try: holders = arguments.match_signature(signature, defs_h) except ArgErr, e: - raise TypeError, "signature mismatch: %s" % e.getmsg(arguments, func.__name__) + raise TyperError, "signature mismatch: %s" % e.getmsg(arguments, func.__name__) assert len(holders) == len(rinputs), "argument parsing mismatch" vlist = [] Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 19 18:29:37 2005 @@ -56,6 +56,12 @@ def get_ll_eq_function(self): raise TyperError, 'no equality function for %r' % self + def rtype_bltn_list(self, hop): + raise TyperError, 'no list() support for %r' % self + + def rtype_unichr(self, hop): + raise TyperError, 'no unichr() support for %r' % self + # default implementation of some operations def rtype_getattr(self, hop): @@ -165,7 +171,9 @@ for opname in annmodel.BINARY_OPERATIONS: setattr_default(pairtype(Repr, Repr), 'rtype_' + opname, missing_rtype_operation) - +# not in BINARY_OPERATIONS + setattr_default(pairtype(Repr, Repr), + 'rtype_contains', missing_rtype_operation) class __extend__(pairtype(Repr, Repr)): def convert_from_to((r_from, r_to), v, llops): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jul 19 18:29:37 2005 @@ -264,7 +264,8 @@ if curstr: r.append(curstr) curstr = '' - assert f in 'xdsrf' + if f not in 'xdsrf': + raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt)) r.append((f,)) else: @@ -294,6 +295,8 @@ code = thing[0] vitem, r_arg = argsiter.next() rep = inputconst(Void, r_arg) + 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, rep) elif code == 'd': Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 19 18:29:37 2005 @@ -31,7 +31,7 @@ log = py.log.Producer("rtyper") py.log.setconsumer("rtyper", None) -crash_on_first_typeerror = True + class RPythonTyper: @@ -44,7 +44,8 @@ self.instance_reprs = {} self.pbc_reprs = {} self.class_pbc_attributes = {} - self.typererror = None + self.typererrors = [] + 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: @@ -68,7 +69,7 @@ print '*' * len(s) print s print '*' * len(s) - + self.crash_on_first_typeerror = True @@ -98,8 +99,9 @@ def bindingrepr(self, var): return self.getrepr(self.binding(var)) - def specialize(self, dont_simplify_again=False): + def specialize(self, dont_simplify_again=False, crash_on_first_typeerror = True): """Main entry point: specialize all annotated blocks of the program.""" + self.crash_on_first_typeerror = crash_on_first_typeerror # specialize depends on annotator simplifications if not dont_simplify_again: self.annotator.simplify() @@ -141,17 +143,29 @@ n = len(self.already_seen) if n % 100 == 0: total = len(self.annotator.annotated) - print 'specializing: %d / %d blocks (%d%%)' % ( - n, total, 100 * n // total) + if self.typererror_count: + error_report = " but %d errors" % self.typererror_count + else: + error_report = '' + print 'specializing: %d / %d blocks (%d%%)%s' % ( + n, total, 100 * n // total, error_report) # make sure all reprs so far have had their setup() called self.call_all_setups() - # re-raise the first TyperError caught - if self.typererror: - exc, value, tb = self.typererror - self.typererror = None - #self.annotator.translator.view() - raise exc, value, tb + if self.typererrors: + c = 1 + for err in self.typererrors: + block, position = err.where + func = self.annotator.annotated.get(block, None) + if func: + func = "(%s:%s)" %(func.__module__ or '?', func.__name__) + else: + func = "(?:?)" + print "TyperError-%d: %s %r {%s}" % (c, func, block, position) + print str(err) + c += 1 + 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.flowgraphs.values(): v = graph.getreturnvar() @@ -203,7 +217,12 @@ def specialize_block(self, block): # give the best possible types to the input args - self.setup_block_entry(block) + try: + self.setup_block_entry(block) + except TyperError, e: + self.gottypererror(e, block, "block-entry", None) + return # cannot continue this block + # specialize all the operations, as far as possible if block.operations == (): # return or except block @@ -272,6 +291,7 @@ new_a1 = newops.convertvar(a1, r_a1, r_a2) except TyperError, e: self.gottypererror(e, block, link, newops) + continue # try other args if new_a1 != a1: newlinkargs[i] = new_a1 @@ -347,12 +367,13 @@ Put a 'TyperError' operation in the graph instead. """ e.where = (block, position) - if crash_on_first_typeerror: + self.typererror_count += 1 + if self.crash_on_first_typeerror: raise - if self.typererror is None: - self.typererror = sys.exc_info() - c1 = inputconst(Void, Exception.__str__(e)) - llops.genop('TYPER ERROR', [c1], resulttype=Void) + self.typererrors.append(e) + if llops: + c1 = inputconst(Void, Exception.__str__(e)) + llops.genop('TYPER ERROR', [c1], resulttype=Void) # __________ regular operations __________ Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Tue Jul 19 18:29:37 2005 @@ -14,6 +14,7 @@ -text Don't start the Pygame viewer -no-a Don't infer annotations, just translate everything -no-t Don't type-specialize the graph operations with the C typer + -t-insist Specialize should not stop at the first error -no-o Don't do backend-oriented optimizations -no-c Don't generate the C code -fork (UNIX) Create a restartable checkpoint after annotation @@ -112,7 +113,8 @@ unixcheckpoint.restartable_point(auto='run') if a and not options['-no-t']: print 'Specializing...' - t.specialize(dont_simplify_again=True) + t.specialize(dont_simplify_again=True, + crash_on_first_typeerror=not options['-t-insist']) if not options['-no-o']: print 'Back-end optimizations...' t.backend_optimizations() @@ -257,6 +259,7 @@ '-no-mark-some-objects': False, '-no-a': False, '-no-t': False, + '-t-insist': False, '-no-o': False, '-tcc': False, '-d': False, Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Tue Jul 19 18:29:37 2005 @@ -138,14 +138,14 @@ for graph in self.flowgraphs.itervalues(): checkgraph(graph) - def specialize(self, dont_simplify_again=False): + def specialize(self, **flags): if self.annotator is None: raise ValueError("you need to call annotate() first") if self.rtyper is not None: raise ValueError("cannot specialize() several times") from pypy.rpython.rtyper import RPythonTyper self.rtyper = RPythonTyper(self.annotator) - self.rtyper.specialize(dont_simplify_again=dont_simplify_again) + self.rtyper.specialize(**flags) def backend_optimizations(self): from pypy.translator.backendoptimization import backend_optimizations From pedronis at codespeak.net Tue Jul 19 19:14:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 19:14:28 +0200 (CEST) Subject: [pypy-svn] r14785 - pypy/dist/pypy/objspace/std Message-ID: <20050719171428.5384E27B5E@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 19:14:13 2005 New Revision: 14785 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: revert to use r_uint for now to get currently annotable code. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 19 19:14:13 2005 @@ -218,16 +218,16 @@ if w_value.sign == -1: raise OperationError(space.w_ValueError, space.wrap( "cannot convert negative integer to unsigned int")) - x = 0 + x = r_uint(0) i = len(w_value.digits) - 1 while i >= 0: prev = x - x = ((x << SHIFT) + w_value.digits[i]) & LONG_MASK + x = (x << SHIFT) + w_value.digits[i] if (x >> SHIFT) != prev: raise OperationError(space.w_OverflowError, space.wrap( "long int too large to convert to unsigned int")) i -= 1 - return r_uint(x) # XXX r_uint should go away + return x def repr__Long(space, w_long): return space.wrap(_format(w_long, 10, True)) @@ -621,7 +621,7 @@ digits = [] i = 0 while l: - digits.append(l & MASK) + digits.append(intmask(l & MASK)) l = l >> SHIFT if sign == 0: digits = [0] @@ -1574,10 +1574,10 @@ sign = v.sign if not sign: return 0 - x = 0 + x = r_uint(0) while i >= 0: prev = x - x = ((x << SHIFT) + v.digits[i]) & LONG_MASK + x = (x << SHIFT) + v.digits[i] if (x >> SHIFT) != prev: raise OverflowError i -= 1 @@ -1586,9 +1586,9 @@ # trouble *unless* this is the min negative number. So, # trouble iff sign bit set && (positive || some bit set other # than the sign bit). - if intmask(x) < 0 and (sign > 0 or (x << 1) & LONG_MASK != 0): + if intmask(x) < 0 and (sign > 0 or (x << 1) != 0): raise OverflowError - return intmask(int(x) * sign) + return intmask(x*sign) def _hash(v): # This is designed so that Python ints and longs with the From pedronis at codespeak.net Tue Jul 19 19:38:51 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 19:38:51 +0200 (CEST) Subject: [pypy-svn] r14788 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050719173851.8656927B57@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 19:38:41 2005 New Revision: 14788 Removed: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Log: about to substitute it with the one from trunk (which provokes less rtyper problems) Deleted: /pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py ============================================================================== --- /pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Tue Jul 19 19:38:41 2005 +++ (empty file) @@ -1,658 +0,0 @@ -import sys, operator -from pypy.objspace.std.objspace import * -from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.std.floatobject import W_FloatObject -from pypy.objspace.std.noneobject import W_NoneObject -from pypy.rpython.rarithmetic import intmask, r_uint, LONG_MASK -from pypy.rpython.rarithmetic import LONG_BIT - -import math - -SHORT_BIT = int(LONG_BIT // 2) -SHORT_MASK = int(LONG_MASK >> SHORT_BIT) - -SIGN_BIT = LONG_BIT-1 -SIGN_MASK = r_uint(1) << SIGN_BIT -NONSIGN_MASK = ~SIGN_MASK - -# XXX some operations below return one of their input arguments -# without checking that it's really of type long (and not a subclass). - -class W_LongObject(W_Object): - """This is a reimplementation of longs using a list of r_uints.""" - #All functions that still rely on the underlying Python's longs are marked - #with YYYYYY - from pypy.objspace.std.longtype import long_typedef as typedef - - def __init__(w_self, space, digits, sign=0): - W_Object.__init__(w_self, space) - if isinstance(digits, long): #YYYYYY - digits, sign = args_from_long(digits) - w_self.digits = digits - w_self.sign = sign - assert len(w_self.digits) - - def longval(self): #YYYYYY - l = 0 - digits = list(self.digits) - digits.reverse() - for d in digits: - l = l << LONG_BIT - l += long(d) - return l * self.sign - - def unwrap(w_self): #YYYYYY - return w_self.longval() - - def _normalize(self): - if len(self.digits) == 0: - self.sign = 0 - self.digits = [r_uint(0)] - return - i = len(self.digits) - 1 - while i != 0 and self.digits[i] == 0: - self.digits.pop(-1) - i -= 1 - if len(self.digits) == 1 and self.digits[0] == 0: - self.sign = 0 - - def _getshort(self, index): - a = self.digits[index // 2] - if index % 2 == 0: - return a & SHORT_MASK - else: - return a >> SHORT_BIT - - def _setshort(self, index, short): - a = self.digits[index // 2] - assert isinstance(short, r_uint) - if index % 2 == 0: - self.digits[index // 2] = ((a >> SHORT_BIT) << SHORT_BIT) + short - else: - self.digits[index // 2] = (a & SHORT_MASK) + (short << SHORT_BIT) - - - - -registerimplementation(W_LongObject) - -# bool-to-long -def delegate_Bool2Long(w_bool): - return W_LongObject(w_bool.space, [r_uint(w_bool.boolval)], - int(w_bool.boolval)) - -# int-to-long delegation -def delegate_Int2Long(w_intobj): - if w_intobj.intval < 0: - sign = -1 - elif w_intobj.intval > 0: - sign = 1 - else: - sign = 0 - digits = [r_uint(abs(w_intobj.intval))] - return W_LongObject(w_intobj.space, digits, sign) - -# long-to-float delegation -def delegate_Long2Float(w_longobj): #YYYYYY - try: - return W_FloatObject(w_longobj.space, float(w_longobj.longval())) - except OverflowError: - raise OperationError(w_longobj.space.w_OverflowError, - w_longobj.space.wrap("long int too large to convert to float")) - - -# long__Long is supposed to do nothing, unless it has -# a derived long object, where it should return -# an exact one. -def long__Long(space, w_long1): - if space.is_w(space.type(w_long1), space.w_long): - return w_long1 - digits = w_long1.digits - sign = w_long1.sign - return W_LongObject(space, digits, sign) - -def long__Int(space, w_intobj): - if w_intobj.intval < 0: - sign = -1 - elif w_intobj.intval > 0: - sign = 1 - else: - sign = 0 - return W_LongObject(space, [r_uint(abs(w_intobj.intval))], sign) - -def int__Long(space, w_value): - if len(w_value.digits) == 1: - if w_value.digits[0] & SIGN_MASK == 0: - return space.newint(int(w_value.digits[0]) * w_value.sign) - elif w_value.sign == -1 and w_value.digits[0] & NONSIGN_MASK == 0: - return space.newint(intmask(w_value.digits[0])) - #subtypes of long are converted to long! - return long__Long(space, w_value) - -def float__Long(space, w_longobj): #YYYYYY - try: - return space.newfloat(float(w_longobj.longval())) - except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("long int too large to convert to float")) - -def long__Float(space, w_floatobj): #YYYYYY - return W_LongObject(space, *args_from_long(long(w_floatobj.floatval))) - -def int_w__Long(space, w_value): - if len(w_value.digits) == 1: - if w_value.digits[0] & SIGN_MASK == 0: - return int(w_value.digits[0]) * w_value.sign - elif w_value.sign == -1 and w_value.digits[0] & NONSIGN_MASK == 0: - return intmask(w_value.digits[0]) - raise OperationError(space.w_OverflowError, - space.wrap("long int too large to convert to int")) - -def uint_w__Long(space, w_value): - if w_value.sign == -1: - raise OperationError(space.w_ValueError, - space.wrap("cannot convert negative integer to unsigned")) - if len(w_value.digits) == 1: - return w_value.digits[0] - raise OperationError(space.w_OverflowError, - space.wrap("long int too large to convert to unsigned int")) - -def repr__Long(space, w_long): #YYYYYY - return space.wrap(repr(w_long.longval())) - -def str__Long(space, w_long): #YYYYYY - return space.wrap(str(w_long.longval())) - -def eq__Long_Long(space, w_long1, w_long2): - if (w_long1.sign != w_long2.sign or - len(w_long1.digits) != len(w_long2.digits)): - return space.newbool(False) - i = 0 - ld = len(w_long1.digits) - while i < ld: - if w_long1.digits[i] != w_long2.digits[i]: - return space.newbool(False) - i += 1 - return space.newbool(True) - -def lt__Long_Long(space, w_long1, w_long2): - if w_long1.sign > w_long2.sign: - return space.newbool(False) - if w_long1.sign < w_long2.sign: - return space.newbool(True) - ld1 = len(w_long1.digits) - ld2 = len(w_long2.digits) - if ld1 > ld2: - if w_long2.sign > 0: - return space.newbool(False) - else: - return space.newbool(True) - elif ld1 < ld2: - if w_long2.sign > 0: - return space.newbool(True) - else: - return space.newbool(False) - i = ld1 - 1 - while i >= 0: - d1 = w_long1.digits[i] - d2 = w_long2.digits[i] - if d1 < d2: - if w_long2.sign > 0: - return space.newbool(True) - else: - return space.newbool(False) - elif d1 > d2: - if w_long2.sign > 0: - return space.newbool(False) - else: - return space.newbool(True) - i -= 1 - return space.newbool(False) - -def hash__Long(space,w_value): #YYYYYY - ## %reimplement% - # real Implementation should be taken from _Py_HashDouble in object.c - return space.wrap(hash(w_value.longval())) - -# coerce -def coerce__Long_Long(space, w_long1, w_long2): - return space.newtuple([w_long1, w_long2]) - - -def add__Long_Long(space, w_long1, w_long2): - if w_long1.sign < 0: - if w_long2.sign < 0: - result = _x_add(w_long1, w_long2, space) - if result.sign != 0: - result.sign = -result.sign - else: - result = _x_sub(w_long2, w_long1, space) - else: - if w_long2.sign < 0: - result = _x_sub(w_long1, w_long2, space) - else: - result = _x_add(w_long1, w_long2, space) - result._normalize() - return result - -def sub__Long_Long(space, w_long1, w_long2): - if w_long1.sign < 0: - if w_long2.sign < 0: - result = _x_sub(w_long1, w_long2, space) - else: - result = _x_add(w_long1, w_long2, space) - result.sign = -result.sign - else: - if w_long2.sign < 0: - result = _x_add(w_long1, w_long2, space) - else: - result = _x_sub(w_long1, w_long2, space) - result._normalize() - return result - -def mul__Long_Long(space, w_long1, w_long2): - result = _x_mul(w_long1, w_long2, space) - result.sign = w_long1.sign * w_long2.sign - return result - -def truediv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - try: - z = operator.truediv(x, y) - except OverflowError: - raise OperationError(space.w_OverflowError, - space.wrap("long/long too large for a float")) - return space.newfloat(float(z)) - -def floordiv__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long division")) - z = x // y - return W_LongObject(space, *args_from_long(z)) - -old_style_div = 1 / 2 == 1 // 2 -def div__Long_Long(space, w_long1, w_long2): #YYYYYY - # Select the proper div - if old_style_div: - return floordiv__Long_Long(space, w_long1, w_long2) - else: - return truediv__Long_Long(space, w_long1, w_long2) - - -def mod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z = x % y - return W_LongObject(space, *args_from_long(z)) - -def divmod__Long_Long(space, w_long1, w_long2): #YYYYYY - x = w_long1.longval() - y = w_long2.longval() - if not y: - raise OperationError(space.w_ZeroDivisionError, - space.wrap("long modulo")) - z1, z2 = divmod(x, y) - w_result1 = W_LongObject(space, *args_from_long(z1)) - w_result2 = W_LongObject(space, *args_from_long(z2)) - return space.newtuple([w_result1, w_result2]) - -# helper for pow() #YYYYYY: still needs longval if second argument is negative -def _impl_long_long_pow(space, lv, lw, lz=None): - if lw.sign < 0: - if lz is not None: - raise OperationError(space.w_TypeError, - space.wrap("pow() 2nd argument " - "cannot be negative when 3rd argument specified")) - return space.pow(space.newfloat(float(lv.longval())), - space.newfloat(float(lw.longval())), - space.w_None) - if lz is not None: - if lz.sign == 0: - raise OperationError(space.w_ValueError, - space.wrap("pow() 3rd argument cannot be 0")) - result = W_LongObject(space, [r_uint(1)], 1) - if lw.sign == 0: - if lz is not None: - result = mod__Long_Long(space, result, lz) - return result - if lz is not None: - temp = mod__Long_Long(space, lv, lz) - else: - temp = lv - i = 0 - #Treat the most significant digit specially to reduce multiplications - while i < len(lw.digits) - 1: - j = 0 - m = r_uint(1) - di = lw.digits[i] - while j < LONG_BIT: - if di & m: - result = mul__Long_Long(space, result, temp) - temp = mul__Long_Long(space, temp, temp) - if lz is not None: - result = mod__Long_Long(space, result, lz) - temp = mod__Long_Long(space, temp, lz) - m = m << 1 - j += 1 - i += 1 - m = r_uint(1) << (LONG_BIT - 1) - highest_set_bit = LONG_BIT - j = LONG_BIT - 1 - di = lw.digits[i] - while j >= 0: - if di & m: - highest_set_bit = j - break - m = m >> 1 - j -= 1 - assert highest_set_bit != LONG_BIT, "long not normalized" - j = 0 - m = r_uint(1) - while j <= highest_set_bit: - if di & m: - result = mul__Long_Long(space, result, temp) - temp = mul__Long_Long(space, temp, temp) - if lz is not None: - result = mod__Long_Long(space, result, lz) - temp = mod__Long_Long(space, temp, lz) - m = m << 1 - j += 1 - if lz: - result = mod__Long_Long(space, result, lz) - return result - - -def pow__Long_Long_Long(space, w_long1, w_long2, w_long3): - return _impl_long_long_pow(space, w_long1, w_long2, w_long3) - -def pow__Long_Long_None(space, w_long1, w_long2, w_long3): - return _impl_long_long_pow(space, w_long1, w_long2, None) - -def neg__Long(space, w_long1): - return W_LongObject(space, 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)) - -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, [r_uint(1)], 1)) - return neg__Long(space, w_lpp) - -def lshift__Long_Long(space, w_long1, w_long2): - if w_long2.sign < 0: - raise OperationError(space.w_ValueError, - space.wrap("negative shift count")) - elif w_long2.sign == 0: - return w_long1 - try: - b = int_w__Long(space, w_long2) - except OverflowError: # b too big - raise OperationError(space.w_OverflowError, - space.wrap("shift count too large")) - wordshift = b // LONG_BIT - remshift = r_uint(b) % LONG_BIT - oldsize = len(w_long1.digits) - newsize = oldsize + wordshift - if remshift != 0: - newsize += 1 - w_result = W_LongObject(space, [r_uint(0)] * newsize, w_long1.sign) - rightshift = LONG_BIT - remshift - LOWER_MASK = (r_uint(1) << r_uint(rightshift)) - 1 - UPPER_MASK = ~LOWER_MASK - accum = r_uint(0) - i = wordshift - j = 0 - while j < oldsize: - digit = w_long1.digits[j] - w_result.digits[i] = (accum | (digit << remshift)) - accum = (digit & UPPER_MASK) >> rightshift - i += 1 - j += 1 - if remshift: - w_result.digits[i] = accum - else: - assert not accum - w_result._normalize() - return w_result - -def rshift__Long_Long(space, w_long1, w_long2): #YYYYYY - if w_long2.sign < 0: - raise OperationError(space.w_ValueError, - space.wrap("negative shift count")) - elif w_long2.sign == 0: - return w_long1 - if w_long1.sign == -1: - w_a1 = invert__Long(space, w_long1) - w_a2 = rshift__Long_Long(space, w_a1, w_long2) - return invert__Long(space, w_a2) - try: - b = int_w__Long(space, w_long2) - except OverflowError: # b too big # XXX maybe just return 0L instead? - raise OperationError(space.w_OverflowError, - space.wrap("shift count too large")) - wordshift = b // LONG_BIT - remshift = r_uint(b) % LONG_BIT - oldsize = len(w_long1.digits) - newsize = oldsize - wordshift - if newsize <= 0: - return W_LongObject(space, [r_uint(0)], 0) - w_result = W_LongObject(space, [r_uint(0)] * newsize, 1) - leftshift = LONG_BIT - remshift - LOWER_MASK = (r_uint(1) << r_uint(remshift)) - 1 - UPPER_MASK = ~LOWER_MASK - accum = r_uint(0) - i = newsize - 1 - j = oldsize - 1 - while i >= 0: - digit = w_long1.digits[j] - w_result.digits[i] = (accum | (digit >> remshift)) - accum = (digit & LOWER_MASK) << leftshift - i -= 1 - j -= 1 - w_result._normalize() - return w_result - -def and__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a & b - return W_LongObject(space, *args_from_long(res)) - -def xor__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a ^ b - return W_LongObject(space, *args_from_long(res)) - -def or__Long_Long(space, w_long1, w_long2): #YYYYYY - a = w_long1.longval() - b = w_long2.longval() - res = a | b - return W_LongObject(space, *args_from_long(res)) - -def oct__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(oct(x)) - -def hex__Long(space, w_long1): #YYYYYY - x = w_long1.longval() - return space.wrap(hex(x)) - -def getnewargs__Long(space, w_long1): - return space.newtuple([W_LongObject(space, w_long1.digits, w_long1.sign)]) - - -register_all(vars()) - -# register implementations of ops that recover int op overflows - -# binary ops -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) - return %(opname)s__Long_Long(space, w_long1, w_long2) -""" % {'opname': opname}, '', 'exec') - - getattr(StdObjSpace.MM, opname).register(globals()['%s_ovr__Int_Int' %opname], W_IntObject, W_IntObject, order=1) - -# unary ops -for opname in ['neg', 'abs']: - exec """ -def %(opname)s_ovr__Int(space, w_int1): - w_long1 = delegate_Int2Long(w_int1) - return %(opname)s__Long(space, w_long1) -""" % {'opname': opname} - - getattr(StdObjSpace.MM, opname).register(globals()['%s_ovr__Int' %opname], W_IntObject, order=1) - -# 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) - 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) - 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) -StdObjSpace.MM.pow.register(pow_ovr__Int_Int_Long, W_IntObject, W_IntObject, W_LongObject, order=1) - - -#Helper Functions -def args_from_long(l): #YYYYYY - if l < 0: - sign = -1 - elif l > 0: - sign = 1 - else: - sign = 0 - l = abs(l) - digits = [] - i = 0 - while l: - digits.append(r_uint(l & LONG_MASK)) - l = l >> LONG_BIT - if sign == 0: - digits = [r_uint(0)] - return digits, sign - - -#Add the absolute values of two longs -def _x_add(a, b, space): - size_a = len(a.digits) - size_b = len(b.digits) - if size_a < size_b: - a, b = b, a - size_a, size_b = size_b, size_a - z = W_LongObject(space, [r_uint(0)] * (len(a.digits) + 1), 1) - i = 0 - carry = r_uint(0) - while i < size_b: - ad = a.digits[i] - s = ad + b.digits[i] - res = s + carry - carry = r_uint(res < s) + r_uint(s < ad) - z.digits[i] = res - i += 1 - while i < size_a: - s = a.digits[i] - carry = s + carry - z.digits[i] = carry - carry = r_uint(s > carry) - i += 1 - z.digits[i] = carry - return z - - -#Substract the absolute values of two longs -def _x_sub(a, b, space): - size_a = len(a.digits) - size_b = len(b.digits) - sign = 1 - i = 0 - if size_a < size_b: - sign = -1 - a, b = b, a - size_a, size_b = size_b, size_a - elif size_a == size_b: - i = size_a - 1; - while i > 0 and a.digits[i] == b.digits[i]: - i -= 1 - if (i == -1): - return W_LongObject(space, [r_uint(0)]) - if a.digits[i] < b.digits[i]: - sign = -1 - a, b = b, a - size_a = size_b = i + 1 - z = W_LongObject(space, [r_uint(0)] * len(a.digits), 1) - i = 0 - borrow = r_uint(0) - while i < size_b: - ad = a.digits[i] - s = ad - b.digits[i] - res = s - borrow - z.digits[i] = res - borrow = r_uint(res > s) + r_uint(s > ad) - i += 1 - while i < size_a: - ad = a.digits[i] - res = ad - borrow - borrow = r_uint(res > ad) - z.digits[i] = res - i += 1 - assert borrow == 0 - z.sign = sign - return z - - -#Multiply the absolute values of two longs -def _x_mul(a, b, space): - size_a = len(a.digits) * 2 - size_b = len(b.digits) * 2 - z = W_LongObject(space, [r_uint(0)] * ((size_a + size_b) // 2), 1) - i = 0 - while i < size_a: - carry = r_uint(0) - f = a._getshort(i) - j = 0 - while j < size_b: - carry += z._getshort(i + j) + b._getshort(j) * f - z._setshort(i + j, carry & SHORT_MASK) - carry = carry >> SHORT_BIT - j += 1 - while carry != 0: - assert i + j < size_a + size_b - carry += z._getshort(i + j) - z._setshort(i + j, carry & SHORT_MASK) - carry = carry >> SHORT_BIT - j += 1 - i += 1 - z._normalize() - return z - -def _inplace_divrem1(pout, pin, n): - rem = r_uint(0, space) - assert n > 0 and n <= SHORT_MASK - size = len(pin.digits) * 2 - 1 - while size >= 0: - rem = (rem << SHORT_BIT) + pin._getshort(size) From pedronis at codespeak.net Tue Jul 19 19:39:39 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 19:39:39 +0200 (CEST) Subject: [pypy-svn] r14789 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050719173939.6E8E227B57@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 19:39:24 2005 New Revision: 14789 Added: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py - copied unchanged from r14785, pypy/dist/pypy/objspace/std/longobject.py Log: longobject from trunk. From pedronis at codespeak.net Tue Jul 19 19:46:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 19:46:34 +0200 (CEST) Subject: [pypy-svn] r14790 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050719174634.0D52527B5D@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 19:46:21 2005 New Revision: 14790 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Log: disable CHECK_DIGITS for annotation/translation Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Tue Jul 19 19:46:21 2005 @@ -63,7 +63,7 @@ # False == no checking at all # True == check 0 <= value <= MASK -CHECK_DIGITS = True +CHECK_DIGITS = False if CHECK_DIGITS: class DigitArray(list): From pedronis at codespeak.net Tue Jul 19 19:56:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 19:56:08 +0200 (CEST) Subject: [pypy-svn] r14791 - pypy/dist/pypy/annotation Message-ID: <20050719175608.4954927B5D@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 19:55:58 2005 New Revision: 14791 Modified: pypy/dist/pypy/annotation/builtin.py Log: oops, fix frexp annotation Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 19 19:55:58 2005 @@ -226,6 +226,9 @@ def math_floor(x): return SomeFloat() +def math_frexp(x): + return SomeTuple((SomeFloat(), SomeInteger())) + def math_any(*args): return SomeFloat() @@ -291,7 +294,7 @@ BUILTIN_ANALYZERS[math.floor] = math_floor BUILTIN_ANALYZERS[math.exp] = math_any BUILTIN_ANALYZERS[math.ldexp] = math_any -BUILTIN_ANALYZERS[math.frexp] = math_any +BUILTIN_ANALYZERS[math.frexp] = math_frexp BUILTIN_ANALYZERS[sys.getrefcount] = count BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf import unicodedata From pedronis at codespeak.net Tue Jul 19 21:56:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 21:56:34 +0200 (CEST) Subject: [pypy-svn] r14793 - in pypy/dist/pypy/rpython: . test Message-ID: <20050719195634.C692027B4B@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 21:56:28 2005 New Revision: 14793 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rslice.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rtyper.py Log: avoid obscure repr keys clashes, with basic test Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Tue Jul 19 21:56:28 2005 @@ -11,7 +11,7 @@ def rtyper_makerepr(self, rtyper): return bool_repr def rtyper_makekey(self): - return None + return self.__class__, bool_repr = BoolRepr() Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 19 21:56:28 2005 @@ -26,10 +26,10 @@ def rtyper_makekey(self): if self.s_self is None: # built-in function case - return getattr(self, 'const', None) + return self.__class__, getattr(self, 'const', None) else: # built-in method case - return (self.methodname, self.s_self.rtyper_makekey()) + return (self.__class__, self.methodname, self.s_self.rtyper_makekey()) class BuiltinFunctionRepr(Repr): Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 19 21:56:28 2005 @@ -341,7 +341,7 @@ def rtyper_makerepr(self, rtyper): return getinstancerepr(rtyper, self.classdef) def rtyper_makekey(self): - return self.classdef + return self.__class__, self.classdef class InstanceRepr(Repr): Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Tue Jul 19 21:56:28 2005 @@ -50,7 +50,7 @@ raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) def rtyper_makekey(self): - return (self.dictdef.dictkey, self.dictdef.dictvalue) + return (self.__class__, self.dictdef.dictkey, self.dictdef.dictvalue) class StrDictRepr(rmodel.Repr): Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Tue Jul 19 21:56:28 2005 @@ -15,7 +15,7 @@ def rtyper_makerepr(self, rtyper): return float_repr def rtyper_makekey(self): - return None + return self.__class__, float_repr = FloatRepr() Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Tue Jul 19 21:56:28 2005 @@ -18,7 +18,7 @@ else: return signed_repr def rtyper_makekey(self): - return self.unsigned + return self.__class__, self.unsigned signed_repr = IntegerRepr() unsigned_repr = IntegerRepr() Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Tue Jul 19 21:56:28 2005 @@ -40,7 +40,7 @@ listitem) def rtyper_makekey(self): - return self.listdef.listitem + return self.__class__, self.listdef.listitem class ListRepr(Repr): Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 19 21:56:28 2005 @@ -115,13 +115,13 @@ r_container = rtyper.getrepr(self.s_container) return r_container.make_iterator_repr() def rtyper_makekey(self): - return self.s_container.rtyper_makekey() + return self.__class__, self.s_container.rtyper_makekey() class __extend__(annmodel.SomeImpossibleValue): def rtyper_makerepr(self, rtyper): return impossible_repr def rtyper_makekey(self): - return None + return self.__class__, # ____ generic binary operations _____________________________ Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Tue Jul 19 21:56:28 2005 @@ -16,11 +16,11 @@ return pyobj_repr def rtyper_makekey(self): if self.is_constant(): - return "const" + return self.__class__, "const" if self.knowntype is type: - return "type" + return self.__class__, "type" else: - return "pyobj" + return self.__class__, "pyobj" class PyObjRepr(Repr): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 19 21:56:28 2005 @@ -88,7 +88,7 @@ def rtyper_makekey(self): lst = self.prebuiltinstances.items() lst.sort() - return tuple(lst) + return tuple([self.__class__]+lst) builtin_descriptor_type = ( type(len), # type 'builtin_function_or_method' Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Tue Jul 19 21:56:28 2005 @@ -15,7 +15,7 @@ ## if self.is_constant() and not self.const: ## return None ## else: - return self.ll_ptrtype + return self.__class__, self.ll_ptrtype class PtrRepr(Repr): Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Tue Jul 19 21:56:28 2005 @@ -39,7 +39,8 @@ else: return startstop_slice_repr def rtyper_makekey(self): - return (self.start.rtyper_makekey(), + return (self.__class__, + self.start.rtyper_makekey(), self.stop.rtyper_makekey(), self.step.rtyper_makekey()) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jul 19 21:56:28 2005 @@ -34,19 +34,19 @@ def rtyper_makerepr(self, rtyper): return string_repr def rtyper_makekey(self): - return None + return self.__class__, class __extend__(annmodel.SomeChar): def rtyper_makerepr(self, rtyper): return char_repr def rtyper_makekey(self): - return None + return self.__class__, class __extend__(annmodel.SomeUnicodeCodePoint): def rtyper_makerepr(self, rtyper): return unichar_repr def rtyper_makekey(self): - return None + return self.__class__, CONST_STR_CACHE = WeakValueDictionary() string_repr = StringRepr() Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Tue Jul 19 21:56:28 2005 @@ -23,7 +23,7 @@ def rtyper_makekey(self): keys = [s_item.rtyper_makekey() for s_item in self.items] - return tuple(keys) + return tuple([self.__class__]+keys) class TupleRepr(Repr): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 19 21:56:28 2005 @@ -78,7 +78,8 @@ def getrepr(self, s_obj): # s_objs are not hashable... try hard to find a unique key anyway - key = s_obj.__class__, s_obj.rtyper_makekey() + key = s_obj.rtyper_makekey() + assert key[0] == s_obj.__class__ try: result = self.reprs[key] except KeyError: Modified: pypy/dist/pypy/rpython/test/test_rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtyper.py (original) +++ pypy/dist/pypy/rpython/test/test_rtyper.py Tue Jul 19 21:56:28 2005 @@ -13,6 +13,15 @@ def teardown_module(mod): py.log._setstate(mod.logstate) +def test_reprkey_dont_clash(): + stup1 = annmodel.SomeTuple((annmodel.SomeFloat(), + annmodel.SomeInteger())) + stup2 = annmodel.SomeTuple((annmodel.SomeString(), + annmodel.SomeInteger())) + key1 = stup1.rtyper_makekey() + key2 = stup2.rtyper_makekey() + assert key1 != key2 + def test_simple(): def dummyfn(x): return x+1 From pedronis at codespeak.net Tue Jul 19 23:32:49 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Jul 2005 23:32:49 +0200 (CEST) Subject: [pypy-svn] r14794 - in pypy/dist/pypy/rpython: . test Message-ID: <20050719213249.B3C1327B4B@code1.codespeak.net> Author: pedronis Date: Tue Jul 19 23:32:48 2005 New Revision: 14794 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: more needed call_args support Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 19 23:32:48 2005 @@ -299,18 +299,33 @@ return self.r_im_self.convert_const(method.im_self) def rtype_simple_call(self, hop): + return self.redispatch_call(hop, call_args=False) + + def rtype_call_args(self, hop): + return self.redispatch_call(hop, call_args=True) + + def redispatch_call(self, hop, call_args): s_function = annmodel.SomePBC({self.function: True}) hop2 = hop.copy() hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') if isinstance(hop2.args_v[0], Constant): hop2.args_v[0] = hop.inputarg(self, 0) + if call_args: + hop2.swap_fst_snd_args() + _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape + adjust_shape(hop2, s_shape) c = Constant(self.function) hop2.v_s_insertfirstarg(c, s_function) # insert 'function' # now hop2 looks like simple_call(function, self, args...) return hop2.dispatch() - +def adjust_shape(hop2, s_shape): + new_shape = (s_shape.const[0]+1,) + s_shape.const[1:] + c_shape = Constant(new_shape) + s_shape = hop2.rtyper.annotator.bookkeeper.immutablevalue(new_shape) + hop2.v_s_insertfirstarg(c_shape, s_shape) # reinsert adjusted shape + # ____________________________________________________________ @@ -531,6 +546,12 @@ return rclass.get_type_repr(self.rtyper).convert_const(cls) def rtype_simple_call(self, hop): + return self.redispatch_call(hop, call_args=False) + + def rtype_call_args(self, hop): + return self.redispatch_call(hop, call_args=True) + + def redispatch_call(self, hop, call_args): if self.lowleveltype != Void: # instantiating a class from multiple possible classes vcls = hop.inputarg(self, arg=0) @@ -556,7 +577,12 @@ s_init = self.rtyper.annotator.bookkeeper.immutablevalue(initfunc) hop2 = hop.copy() hop2.r_s_popfirstarg() # discard the class pointer argument - hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' + if call_args: + _, s_shape = hop2.r_s_popfirstarg() # temporarely remove shape + hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' + adjust_shape(hop2, s_shape) + else: + hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' c = Constant(initfunc) hop2.v_s_insertfirstarg(c, s_init) # add 'initfunc' hop2.s_result = annmodel.SomePBC({None: True}) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 19 23:32:48 2005 @@ -554,6 +554,11 @@ self.args_s.insert(0, s_newfirstarg) self.nb_args += 1 + def swap_fst_snd_args(self): + self.args_v[0], self.args_v[1] = self.args_v[1], self.args_v[0] + self.args_s[0], self.args_s[1] = self.args_s[1], self.args_s[0] + self.args_r[0], self.args_r[1] = self.args_r[1], self.args_r[0] + def has_implicit_exception(self, exc_cls): for link in self.exceptionlinks: if issubclass(exc_cls, link.exitcase): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Tue Jul 19 23:32:48 2005 @@ -94,12 +94,24 @@ return instance.a1 assert interpret(f, [5]) == 5 +def test_class_init_w_kwds(): + def f(a): + instance = MyBaseWithInit(a=a) + return instance.a1 + assert interpret(f, [5]) == 5 + def test_class_init_2(): def f(a, b): instance = MySubclassWithInit(a, b) return instance.a1 * instance.b1 assert interpret(f, [6, 7]) == 42 +def test_class_init_2_w_kwds(): + def f(a, b): + instance = MySubclassWithInit(a, b=b) + return instance.a1 * instance.b1 + assert interpret(f, [6, 7]) == 42 + def test_class_calling_init(): def f(): instance = MySubclassWithInit(1, 2) @@ -142,6 +154,14 @@ res = interpret(f, [6]) assert res == 11 +def test_call_frozen_pbc_simple_w_kwds(): + fr1 = Freezing() + fr1.x = 5 + def f(n): + return fr1.mymethod(y=n) + res = interpret(f, [6]) + assert res == 11 + def test_call_frozen_pbc_multiple(): fr1 = Freezing() fr2 = Freezing() @@ -158,6 +178,22 @@ res = interpret(f, [-1]) assert res == 5 +def test_call_frozen_pbc_multiple_w_kwds(): + fr1 = Freezing() + fr2 = Freezing() + fr1.x = 5 + fr2.x = 6 + def f(n): + if n > 0: + fr = fr1 + else: + fr = fr2 + return fr.mymethod(y=n) + res = interpret(f, [1]) + assert res == 6 + res = interpret(f, [-1]) + assert res == 5 + def test_is_among_frozen(): fr1 = Freezing() fr2 = Freezing() @@ -310,6 +346,18 @@ res = interpret(fn, []) assert res == 0 +def test_rpbc_bound_method_static_call_w_kwds(): + class R: + def meth(self, x): + return x + r = R() + m = r.meth + def fn(): + return m(x=3) + res = interpret(fn, []) + assert res == 3 + + def test_constant_return_disagreement(): class R: def meth(self): From pedronis at codespeak.net Wed Jul 20 02:34:26 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 02:34:26 +0200 (CEST) Subject: [pypy-svn] r14795 - in pypy/dist/pypy: rpython rpython/test translator Message-ID: <20050720003426.8770427B60@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 02:34:24 2005 New Revision: 14795 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/translator/transform.py Log: fixing support for the combination of method call on variable instances and specialisation Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 20 02:34:24 2005 @@ -486,6 +486,20 @@ # (as shown for example in test_rclass/test_method_both_A_and_B) return llops.convertvar(v_inst, r_inst, self.r_im_self) + def rtype_hardwired_simple_call(self, hop): + hop2 = hop.copy() + hop2.swap_fst_snd_args() # bring the hardwired function constant in front + func = hop2.args_v[0].value + s_func = annmodel.SomePBC({func: True}) + hop2.r_s_popfirstarg() # info captured, discard it + + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' + hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + + hop2.v_s_insertfirstarg(Constant(func), s_func) # insert 'function' + # now hop2 looks like simple_call(function, self, args...) + return self.rtyper.translate_op_simple_call(hop2) + def rtype_simple_call(self, hop): r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jul 20 02:34:24 2005 @@ -404,6 +404,12 @@ r_arg2 = hop.args_r[1] return pair(r_arg1, r_arg2).rtype_contains(hop) + def translate_op_hardwired_simple_call(self, hop): + return hop.args_r[0].rtype_hardwired_simple_call(hop) + + def translate_op_hardwired_call_args(self, hop): + return hop.args_r[0].rtype_hardwired_simple_call(hop) + # __________ irregular operations __________ def translate_op_newlist(self, hop): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Jul 20 02:34:24 2005 @@ -721,3 +721,17 @@ assert res == 11 res = interpret(g, [1, 0]) assert res == 7 + +def test_call_special_starargs_method(): + class Star: + def __init__(self, d): + self.d = d + def meth(self, *args): + return self.d + len(args) + + def f(i, j): + s = Star(i) + return s.meth(i, j) + + res = interpret(f, [3, 0]) + assert res == 5 Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Wed Jul 20 02:34:24 2005 @@ -158,7 +158,16 @@ specialized_callb, specialcase = self.bookkeeper.query_spaceop_callable(op) if specialcase or callb != specialized_callb: if not specialcase: - op.args[0] = Constant(specialized_callb.prebuiltinstances.keys()[0]) + specialized_func = Constant(specialized_callb.prebuiltinstances.keys()[0]) + if not isinstance(op.args[0], Constant) and not callb.is_constant(): + # this is a method call on some variable instance: + # we still need the logic for methods up to calling the fixed specialized function, + # we use special call operations 'hardwired_simple_call' and 'hardwired_call_args' + # including the specialized function as 2nd argument to distinguish this case + op.opname = intern('hardwired_'+op.opname) + op.args.insert(1, specialized_func) + else: + op.args[0] = specialized_func else: if op.opname != 'simple_call': assert 0, "not supported: call_args to a specialized function" From tismer at codespeak.net Wed Jul 20 02:54:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 20 Jul 2005 02:54:39 +0200 (CEST) Subject: [pypy-svn] r14796 - in pypy/dist/pypy: rpython translator/goal translator/pickle Message-ID: <20050720005439.80D6327B60@code1.codespeak.net> Author: tismer Date: Wed Jul 20 02:54:37 2005 New Revision: 14796 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/pickle/genpickle.py Log: tried to build pickling support for debugging. translate_pypy now tries to save a file if the option was given, after a TyperError has happened. Unfortunately, the involved structures seem to be too deeply nested. We crash with stack overflow. Further exploration is necessry to find out what to cut. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jul 20 02:54:37 2005 @@ -59,13 +59,10 @@ finally: TLS.nested_hash_level -= 1 - # due to this dynamic hash value, we must forbid - # pickling, until we have an algorithm for that - def __reduce_ex__(self, *args): - raise Exception('%s insts cannot be pickled, yet. __hash__ is not' - ' constant during reconstruction.' % - self.__class__.__name__) - __reduce__ = __reduce_ex__ + # due to this dynamic hash value, we should forbid + # pickling, until we have an algorithm for that. + # but we just provide a tag for external help. + __hash_is_not_constant__ = True def __repr__(self): return '<%s>' % (self,) @@ -746,6 +743,8 @@ class _pyobject(Hashable): + __slots__ = [] # or we get in trouble with pickling + _TYPE = PyObject def _parentstructure(self): Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Wed Jul 20 02:54:37 2005 @@ -75,6 +75,8 @@ from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_print from pypy.translator.pickle.main import load, save +# catch TyperError to allow for post-mortem dump +from pypy.rpython.rmodel import TyperError # XXX this tries to make compiling faster from pypy.translator.tool import buildpyxmodule @@ -492,6 +494,7 @@ cleanup() try: + err = None if load_file: t = loaded_dic['trans'] entry_point = t.entrypoint @@ -509,17 +512,25 @@ print "continuing Analysis as defined by %s, loaded from %s" %( targetspec, load_file) print 'options in effect:', options - analyse(None) + try: + analyse(None) + except TyperError: + err = sys.exc_info() else: targetspec_dic = {} sys.path.insert(0, os.path.dirname(targetspec)) execfile(targetspec+'.py', targetspec_dic) print "Analysing target as defined by %s" % targetspec print 'options in effect:', options - analyse(targetspec_dic['target']) + try: + analyse(targetspec_dic['target']) + except TyperError: + err = sys.exc_info() print '-'*60 if save_file: print 'saving state to %s' % save_file + if err: + print '*** this save is done after errors occured ***' save(t, save_file, trans=t, inputtypes=inputtypes, @@ -527,6 +538,8 @@ targetspec_dic=targetspec_dic, options=options, ) + if err: + raise err[0], err[1], err[2] if options['-no-c']: print 'Not generating C code.' elif options['-c']: Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Wed Jul 20 02:54:37 2005 @@ -31,7 +31,7 @@ import pickle from types import * -import types +import types, weakref class AlreadyCreated(Exception): pass @@ -191,6 +191,9 @@ except AlreadyCreated: name = self.picklenames[id(obj)] return name + except Exception, e: + self.problem = e, obj + raise def nameofargs(self, tup, plain_tuple = False): """ a string with the nameofs, concatenated """ @@ -443,6 +446,13 @@ self.produce('from types import %s as %s' % ( key, name)) return name + elif cls in weakref.__dict__.values(): + for key, value in weakref.__dict__.items(): + if value is cls: + break + self.produce('from weakref import %s as %s' % ( + key, name)) + return name else: expr = self.typename_mapping[cls] self.produce('%s = %s' % (name, expr)) @@ -600,7 +610,7 @@ raise assert not hasattr(instance, '__dict__'), ('wrong assumptions' ' about __slots__ in %s instance without __setstate__,' - ' please update %s' % (cls.__name__, __name__) ) + ' please update %s' % (klass.__name__, __name__) ) restorestate = _get(instance) restorer = _rec restoreargs = klass, @@ -746,6 +756,12 @@ wp, wp.__name__) return self.skipped_function(wp, msg) + def nameof_weakref(self, value): + # no need to name weakrefs. Their contents is what is weakref'ed. + # obtain the ref'ed object by calling + obj = value() + return '%s(%s)' % (self.nameof(type(value)), self.nameof(obj)) + def make_cell(obj): def func(): From pedronis at codespeak.net Wed Jul 20 03:27:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 03:27:44 +0200 (CEST) Subject: [pypy-svn] r14797 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720012744.BA40927B60@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 03:27:42 2005 New Revision: 14797 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: call_args for the combination of variable instance method and specialisation. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jul 20 03:27:42 2005 @@ -487,35 +487,47 @@ return llops.convertvar(v_inst, r_inst, self.r_im_self) def rtype_hardwired_simple_call(self, hop): - hop2 = hop.copy() - hop2.swap_fst_snd_args() # bring the hardwired function constant in front - func = hop2.args_v[0].value - s_func = annmodel.SomePBC({func: True}) - hop2.r_s_popfirstarg() # info captured, discard it + return self.redispatch_call(hop, call_args=False, hardwired=True) - hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' - hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') - - hop2.v_s_insertfirstarg(Constant(func), s_func) # insert 'function' - # now hop2 looks like simple_call(function, self, args...) - return self.rtyper.translate_op_simple_call(hop2) + def rtype_hardwired_call_args(self, hop): + return self.redispatch_call(hop, call_args=True, hardwired=True) def rtype_simple_call(self, hop): - r_class = self.r_im_self.rclass - mangled_name, r_func = r_class.clsfields[self.methodname] - assert isinstance(r_func, FunctionsPBCRepr) - s_func = r_func.s_pbc + return self.redispatch_call(hop, call_args=False) + def rtype_call_args(self, hop): + return self.redispatch_call(hop, call_args=True) + + def redispatch_call(self, hop, call_args, hardwired=False): hop2 = hop.copy() + if hardwired: + hop2.swap_fst_snd_args() # bring the hardwired function constant in front + func = hop2.args_v[0].value + s_func = annmodel.SomePBC({func: True}) + hop2.r_s_popfirstarg() # info captured, discard it + v_func = Constant(func) + else: + r_class = self.r_im_self.rclass + mangled_name, r_func = r_class.clsfields[self.methodname] + assert isinstance(r_func, FunctionsPBCRepr) + s_func = r_func.s_pbc + v_im_self = hop.inputarg(self, arg=0) + v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) + v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') - v_im_self = hop.inputarg(self, arg=0) - v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) - v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) + opname = 'simple_call' + if call_args: + hop2.swap_fst_snd_args() + _, s_shape = hop2.r_s_popfirstarg() + adjust_shape(hop2, s_shape) + opname = 'call_args' + hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' # now hop2 looks like simple_call(function, self, args...) - return hop2.dispatch() + return hop2.dispatch(opname=opname) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jul 20 03:27:42 2005 @@ -408,7 +408,7 @@ return hop.args_r[0].rtype_hardwired_simple_call(hop) def translate_op_hardwired_call_args(self, hop): - return hop.args_r[0].rtype_hardwired_simple_call(hop) + return hop.args_r[0].rtype_hardwired_call_args(hop) # __________ irregular operations __________ @@ -502,10 +502,11 @@ setattr(result, key, value) return result - def dispatch(self): - op = self.spaceop + def dispatch(self, opname=None): + if not opname: + opname = self.spaceop.opname rtyper = self.rtyper - translate_meth = getattr(rtyper, 'translate_op_'+op.opname, + translate_meth = getattr(rtyper, 'translate_op_'+opname, rtyper.missing_operation) return translate_meth(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 Wed Jul 20 03:27:42 2005 @@ -735,3 +735,31 @@ res = interpret(f, [3, 0]) assert res == 5 + +def test_call_star_method(): + class N: + def __init__(self, d): + self.d = d + def meth(self, a, b): + return self.d + a + b + + def f(i, j): + n = N(i) + return n.meth(*(i, j)) + + res = interpret(f, [3, 7]) + assert res == 13 + +def test_call_star_special_starargs_method(): + class N: + def __init__(self, d): + self.d = d + def meth(self, *args): + return self.d + len(args) + + def f(i, j): + n = N(i) + return n.meth(*(i, j)) + + res = interpret(f, [3, 0]) + assert res == 5 From pedronis at codespeak.net Wed Jul 20 04:48:38 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 04:48:38 +0200 (CEST) Subject: [pypy-svn] r14798 - pypy/dist/pypy/translator/goal Message-ID: <20050720024838.6A33927B60@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 04:48:37 2005 New Revision: 14798 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: update Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Wed Jul 20 04:48:37 2005 @@ -8,9 +8,6 @@ * slice(SomeObject, SomeObject, SomeObject) - * we need a call_args similar to simple_call (doing redispatching) - on MethodOfFrozenPBCRepr etc - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC set to a larger one. From ericvrp at codespeak.net Wed Jul 20 11:11:58 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 20 Jul 2005 11:11:58 +0200 (CEST) Subject: [pypy-svn] r14803 - pypy/dist/pypy/tool Message-ID: <20050720091158.67C7127B7D@code1.codespeak.net> Author: ericvrp Date: Wed Jul 20 11:11:57 2005 New Revision: 14803 Modified: pypy/dist/pypy/tool/udir.py Log: Small addition. On symlink capable o.s's add a link (usession-current) referring to the new usession- Modified: pypy/dist/pypy/tool/udir.py ============================================================================== --- pypy/dist/pypy/tool/udir.py (original) +++ pypy/dist/pypy/tool/udir.py Wed Jul 20 11:11:57 2005 @@ -10,3 +10,14 @@ udir = local.make_numbered_dir(prefix='usession-', keep=3) +import os +src = str(udir) +dest = src[:src.rfind('-')] + '-current' +try: + os.unlink(dest) +except: + pass +try: + os.symlink(src, dest) +except: + pass From ac at codespeak.net Wed Jul 20 12:07:03 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 12:07:03 +0200 (CEST) Subject: [pypy-svn] r14804 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720100703.9CACF27B60@code1.codespeak.net> Author: ac Date: Wed Jul 20 12:07:03 2005 New Revision: 14804 Modified: pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_rint.py Log: Implement builtin oct. Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Wed Jul 20 12:07:03 2005 @@ -313,6 +313,11 @@ true = inputconst(Bool, True) return hop.gendirectcall(ll_int2hex, varg, true) + def rtype_oct(_, hop): + varg = hop.inputarg(hop.args_r[0], 0) + true = inputconst(Bool, True) + return hop.gendirectcall(ll_int2oct, varg, true) + CHAR_ARRAY = GcArray(Char) @@ -355,6 +360,38 @@ j += 1 return result +def ll_int2oct(i, addPrefix): + from pypy.rpython.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 + # # _________________________ Conversions _________________________ Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Wed Jul 20 12:07:03 2005 @@ -75,7 +75,20 @@ 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) From ac at codespeak.net Wed Jul 20 12:43:09 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 12:43:09 +0200 (CEST) Subject: [pypy-svn] r14805 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720104309.F218C27B60@code1.codespeak.net> Author: ac Date: Wed Jul 20 12:43:09 2005 New Revision: 14805 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Implement %o formatcode. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jul 20 12:43:09 2005 @@ -264,7 +264,7 @@ if curstr: r.append(curstr) curstr = '' - if f not in 'xdsrf': + if f not in 'xdosrf': raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt)) r.append((f,)) @@ -309,6 +309,10 @@ 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: assert 0 else: 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 Jul 20 12:43:09 2005 @@ -245,17 +245,26 @@ def percentX(i): return "bing %x bang" % (i,) - + res = interpret(percentX, [23]) assert ''.join(res.chars) == 'bing 17 bang' res = interpret(percentX, [-123]) assert ''.join(res.chars) == 'bing -7b bang' - def moreThanOne(s, d, x): - return "string: %s decimal: %d hex: %x" % (s, d, x) + def percentO(i): + return "bing %o bang" % (i,) + + res = interpret(percentO, [23]) + assert ''.join(res.chars) == 'bing 27 bang' + + res = interpret(percentO, [-123]) + assert ''.join(res.chars) == 'bing -173 bang' + + def moreThanOne(s, d, x, o): + return "string: %s decimal: %d hex: %x oct: %o" % (s, d, x, o) - args = 'a', 2, 3 + args = 'a', 2, 3, 4 res = interpret(moreThanOne, list(args)) assert ''.join(res.chars) == moreThanOne(*args) From ale at codespeak.net Wed Jul 20 13:53:59 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 20 Jul 2005 13:53:59 +0200 (CEST) Subject: [pypy-svn] r14807 - in pypy/dist/pypy: module/posix module/posix/test rpython rpython/module Message-ID: <20050720115359.F26C627B82@code1.codespeak.net> Author: ale Date: Wed Jul 20 13:53:56 2005 New Revision: 14807 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py Log: This is an intermeddiate checkin. Mostly it works (I have 6 failures in the standard tests). - changed interp_posix to use unwrap<-spec correctly - added better tests for the functions - added OSError - added ll functions Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Wed Jul 20 13:53:56 2005 @@ -3,6 +3,7 @@ class Module(MixedModule): appleveldefs = { + 'error' : 'app_posix.error' } interpleveldefs = { 'open' : 'interp_posix.open', Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Wed Jul 20 13:53:56 2005 @@ -12,38 +12,38 @@ return space.wrap(fd) -def lseek(space, w_fd, pos, how): +def lseek(space, fd, pos, how): os.lseek(fd,pos,how) -lseek.unwrap_spec = [ObjSpace, W_Root, int, int] +lseek.unwrap_spec = [ObjSpace, int, int, int] -def isatty(space, w_fd): - return os.isatty(fd) -lseek.unwrap_spec = [ObjSpace, W_Root, int, int] - -def read(space, w_fd, buffersize): - return os.read(w_fd,buffersize) -read.unwrap_spec = [ObjSpace, W_Root, int] - -def write(space, w_fd, data): - return os.write( w_fd, data) -write.unwrap_spec = [ObjSpace, W_Root, str] - -def close(space, w_fd): - os.close(w_fd) -close.unwrap_spec = [ObjSpace, W_Root] - -def ftruncate(space, w_fd, length): - os.ftruncate(w_fd, length) -ftruncate.unwrap_spec = [ObjSpace, W_Root, int] - -def fstat(space, w_fd): - return os.fstat(w_fd) -fstat.unwrap_spec = [ObjSpace, W_Root] +def isatty(space, fd): + return os.isatty(w_fd) +lseek.unwrap_spec = [ObjSpace, int] + +def read(space, fd, buffersize): + return os.read(fd,buffersize) +read.unwrap_spec = [ObjSpace, int, int] + +def write(space, fd, data): + return os.write( fd, data) +write.unwrap_spec = [ObjSpace, int, str] + +def close(space, fd): + os.close(fd) +close.unwrap_spec = [ObjSpace, int] + +def ftruncate(space, fd, length): + os.ftruncate(fd, length) +ftruncate.unwrap_spec = [ObjSpace, int, int] + +def fstat(space, fd): + return os.fstat(fd) +fstat.unwrap_spec = [ObjSpace, int] def getcwd(space): return os.getcwd() getcwd.unwrap_spec = [ObjSpace] -def dup(space, w_fd): - return os.dup(w_fd) -dup.unwrap_spec = [ObjSpace, W_Root] \ No newline at end of file +def dup(space, fd): + return os.dup(fd) +dup.unwrap_spec = [ObjSpace, int] \ No newline at end of file Modified: pypy/dist/pypy/module/posix/test/test_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix.py Wed Jul 20 13:53:56 2005 @@ -1,28 +1,102 @@ from pypy.rpython.test.test_llinterp import interpret +from pypy.tool.udir import udir +import os, posix + +def setup_module(module): + testf = udir.join('test.txt') + testfile = testf.open('w') + testfile.write('This is a test') + testfile.close() + module.path = testf.strpath def test_open(): def f(): - import os - ff = os.open('test_posix.py',0,0755) + ff = posix.open(path,posix.O_RDONLY,0777) return ff func = interpret(f,[]) - assert func + assert type(func) == int def test_dup(): - def ff(): - import os - fi = os.open('test_posix.py',0,0755) - g = os.dup(fi) - #fi.close() + def ff(fi): + g = posix.dup(fi) return g - func = interpret(ff,[]) - assert func + fi = os.open(path,os.O_RDONLY,0755) + g = interpret(ff,[fi]) + assert os.fstat(g) == os.fstat(fi) def test_fstat(): - def fo(): - import os - fi = os.open('test_posix.py',0,0755) - g = os.fstat(fi) + def fo(fi): + g = posix.fstat(fi) return g - func = interpret(fo,[],True) - assert func + fi = os.open(path,os.O_RDONLY,0777) + func = interpret(fo,[fi]) + stat = os.fstat(fi) + for i in range(len(stat)): + stat0 = getattr(func, 'item%d' % i) + assert stat0 == stat[i] + +def test_lseek(): + def f(fi,pos): + posix.lseek(fi,pos,0) + fi = os.open(path,os.O_RDONLY,0777) + func = interpret(f,[fi,5]) + res = os.read(fi,2) + assert res =='is' + +def test_isatty(): + def f(fi): + posix.isatty(fi) + fi = os.open(path,os.O_RDONLY,0777) + func = interpret(f,[fi]) + assert not func + os.close(fi) + func = interpret(f,[fi]) + assert not func + +def test_getcwd(): + def f(): + return posix.getcwd() + res = interpret(f,[]) + cwd = os.getcwd() + print res.chars,cwd + assert ''.join([x for x in res.chars]) == cwd + +def test_write(): + def f(fi): + text = 'This is a test' + return posix.write(fi,text) + fi = os.open(path,os.O_WRONLY,0777) + text = 'This is a test' + func = interpret(f,[fi]) + os.close(fi) + fi = os.open(path,os.O_RDONLY,0777) + res = os.read(fi,20) + assert res == text + +def test_read(): + def f(fi,len): + return posix.read(fi,len) + fi = os.open(path,os.O_WRONLY,0777) + text = 'This is a test' + os.write(fi,text) + os.close(fi) + fi = os.open(path,os.O_RDONLY,0777) + res = interpret(f,[fi,20]) + assert ''.join([x for x in res.chars]) == text + +def test_close(): + def f(fi): + return posix.close(fi) + fi = os.open(path,os.O_WRONLY,0777) + text = 'This is a test' + os.write(fi,text) + res = interpret(f,[fi]) + raises( OSError(), os.fstat(fi)) + +def test_ftruncate(): + def f(fi,len): + posix.ftruncate(fi,len) + fi = os.open(path,os.O_RDWR,0777) + func = interpret(f,[fi,6]) + assert os.fstat(fi).st_size == 6 + Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Wed Jul 20 13:53:56 2005 @@ -4,6 +4,7 @@ import os import time import types +from pypy.annotation.model import SomeInteger, SomeTuple class ExtFuncInfo: @@ -49,15 +50,19 @@ # _____________________________________________________________ nonefactory = lambda *args: None +tuplefactory = lambda *args: SomeTuple((SomeInteger(),)*10) # external function declarations -declare(os.open , int , 'll_os/open') -declare(os.read , str , 'll_os/read') -declare(os.write , int , 'll_os/write') -declare(os.close , nonefactory, 'll_os/close') -declare(os.getcwd , str , 'll_os/getcwd') -declare(os.dup , int , 'll_os/dup') -declare(os.fstat , int , 'll_os/fstat') -declare(time.time , float , 'll_time/time') -declare(time.clock, float , 'll_time/clock') -declare(time.sleep, nonefactory, 'll_time/sleep') +declare(os.open , int , 'll_os/open') +declare(os.read , str , 'll_os/read') +declare(os.write , int , 'll_os/write') +declare(os.close , nonefactory, 'll_os/close') +declare(os.getcwd , str , 'll_os/getcwd') +declare(os.dup , int , 'll_os/dup') +declare(os.lseek , int , 'll_os/lseek') +declare(os.isatty , bool , 'll_os/isatty') +declare(os.ftruncate, nonefactory, 'll_os/ftruncate') +declare(os.fstat , tuplefactory, 'll_os/fstat') +declare(time.time , float , 'll_time/time') +declare(time.clock , float , 'll_time/clock') +declare(time.sleep , nonefactory, 'll_time/sleep') 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 Wed Jul 20 13:53:56 2005 @@ -17,7 +17,6 @@ from pypy.rpython.rstr import STR from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc - # utility conversion functions def to_rstr(s): p = malloc(STR, len(s)) @@ -78,13 +77,44 @@ return os.dup(fd) ll_os_dup.suggested_primitive = True +def ll_os_lseek(fd,pos,how): + return intmask(os.lseek(fd,pos,how)) +ll_os_lseek.suggested_primitive = True + +def ll_os_isatty(fd): + return os.isatty(fd) +ll_os_isatty.suggested_primitive = True + +def ll_os_ftruncate(fd,len): + return os.ftruncate(fd,len) +ll_os_ftruncate.suggested_primitive = True + +n = 10 +fieldnames = ['item%d' % i for i in range(n)] +lltypes = [Signed]*n +fields = tuple(zip(fieldnames, lltypes)) +tup = malloc(GcStruct('tuple%d' % n, *fields)) + +from pypy.rpython.rarithmetic import intmask + def ll_os_fstat(fd): + stat = os.fstat(fd) + i = 0 n = len(stat) - fieldnames = ['item%d' % i for i in range(n)] - lltypes = [Signed]*n - fields = tuple(zip(fieldnames, lltypes)) - tup = GcStruct('tuple%d' % n, fields) - #lowleveltype = Ptr(tup) - #p = malloc( tup ) - return tup \ No newline at end of file + tup.item0 = stat[0] + tup.item1 = intmask(stat[1]) + tup.item2 = intmask(stat[2]) + tup.item3 = intmask(stat[3]) + tup.item4 = intmask(stat[4]) + tup.item5 = intmask(stat[5]) + tup.item6 = intmask(stat[6]) + tup.item7 = intmask(stat[7]) + tup.item8 = intmask(stat[8]) + tup.item9 = intmask(stat[9]) +## while i Author: ale Date: Wed Jul 20 13:56:22 2005 New Revision: 14808 Added: pypy/dist/pypy/module/posix/app_posix.py Log: Oops - forgot to check this one in Added: pypy/dist/pypy/module/posix/app_posix.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/posix/app_posix.py Wed Jul 20 13:56:22 2005 @@ -0,0 +1,5 @@ + +class OSError(Exception): + pass + +error = OSError \ No newline at end of file From ac at codespeak.net Wed Jul 20 14:35:05 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 14:35:05 +0200 (CEST) Subject: [pypy-svn] r14813 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720123505.CBF2D27B75@code1.codespeak.net> Author: ac Date: Wed Jul 20 14:35:05 2005 New Revision: 14813 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Implement list multiplication. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Wed Jul 20 14:35:05 2005 @@ -202,6 +202,10 @@ llfn = ll_delitem return hop.gendirectcall(llfn, v_lst, v_index) + def rtype_mul((r_lst, r_int), hop): + v_lst, v_factor = hop.inputargs(r_lst, Signed) + return hop.gendirectcall(ll_mul, v_lst, v_factor) + class __extend__(pairtype(ListRepr, SliceRepr)): def rtype_getitem((r_lst, r_slic), hop): @@ -541,6 +545,23 @@ TEMP = GcArray(Ptr(rstr.STR)) +def ll_mul(l, f): + items = l.items + length = len(items) + if lenght == 0 or f <= 0: + return ll_newlist(typeOf(l), 0) + + resultlen = length * f + new_lst = ll_newlist(typeOf(l), resultlen) + i = 0 + new_items = new_lst.items + j = 0 + while j < resultlen: + while i < length: + new_items[i + j] = items[i] + i += 1 + j += length + return new_lst # ____________________________________________________________ @@ -575,6 +596,8 @@ return v_result def ll_alloc_and_set(LISTPTR, count, item): + if count < 0: + count = 0 l = malloc(LISTPTR.TO) l.items = malloc(LISTPTR.TO.items.TO, count) i = 0 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 Jul 20 14:35:05 2005 @@ -340,3 +340,17 @@ return lst[-1] * lst2[-1] res = interpret(fn, [5]) assert res == 42 + +def test_list_multiply(): + def fn(i): + lst = [i] * i + return len(lst) + for arg in (1, 9, 0, -1, -27): + res = interpret(fn, [arg]) + assert res == fn(arg) + def fn(i): + lst = [i, i + 1] * i + return len(lst) + for arg in (1, 9, 0, -1, -27): + res = interpret(fn, [arg]) + assert res == fn(arg) From ac at codespeak.net Wed Jul 20 14:48:34 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 14:48:34 +0200 (CEST) Subject: [pypy-svn] r14815 - pypy/dist/pypy/rpython Message-ID: <20050720124834.487D727B75@code1.codespeak.net> Author: ac Date: Wed Jul 20 14:48:34 2005 New Revision: 14815 Modified: pypy/dist/pypy/rpython/rstr.py Log: Implement multiplication of int and char. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jul 20 14:48:34 2005 @@ -370,6 +370,12 @@ return hop.gendirectcall(ll_char_mul, v_char, v_int) rtype_inplace_mul = rtype_mul +class __extend__(pairtype(IntegetRepr, CharRepr)): + def rtype_mul(_, hop): + v_int, v_char = hop.inputargs(Signed, char_repr) + return hop.gendirectcall(ll_char_mul, v_char, v_int) + rtype_inplace_mul = rtype_mul + class __extend__(pairtype(CharRepr, CharRepr)): def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') def rtype_ne(_, hop): return _rtype_compare_template(hop, 'ne') From ludal at codespeak.net Wed Jul 20 14:49:42 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Wed, 20 Jul 2005 14:49:42 +0200 (CEST) Subject: [pypy-svn] r14816 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050720124942.7151527B75@code1.codespeak.net> Author: ludal Date: Wed Jul 20 14:49:41 2005 New Revision: 14816 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py Log: comment on naming conventions Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Wed Jul 20 14:49:41 2005 @@ -22,8 +22,29 @@ return True return False -## building functions - +## building functions helpers +## -------------------------- +## +## Naming convention: +## to provide a function handler for a grammar rule name yyy +## you should provide a build_yyy( builder, nb ) function +## where builder is the AstBuilder instance used to build the +## ast tree and nb is the number of items this rule is reducing +## +## Example: +## for example if the rule +## term <- var ( '+' expr )* +## matches +## x + (2*y) + z +## build_term will be called with nb == 2 +## and get_atoms( builder, nb ) should return a list +## of 5 objects : Var TokenObject('+') Expr('2*y') TokenObject('+') Expr('z') +## where Var and Expr are AST subtrees and Token is a not yet +## reduced token +## +## AST_RULES is kept as a dictionnary to be rpython compliant this is the +## main reason why build_* functions are not methods of the AstBuilder class +## def get_atoms( builder, nb ): L = [] i = nb From pedronis at codespeak.net Wed Jul 20 15:35:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 15:35:57 +0200 (CEST) Subject: [pypy-svn] r14817 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720133557.79F8C27B7C@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 15:35:54 2005 New Revision: 14817 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: typo fixes & test Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Wed Jul 20 15:35:54 2005 @@ -548,7 +548,7 @@ def ll_mul(l, f): items = l.items length = len(items) - if lenght == 0 or f <= 0: + if length == 0 or f <= 0: return ll_newlist(typeOf(l), 0) resultlen = length * f Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jul 20 15:35:54 2005 @@ -370,7 +370,7 @@ return hop.gendirectcall(ll_char_mul, v_char, v_int) rtype_inplace_mul = rtype_mul -class __extend__(pairtype(IntegetRepr, CharRepr)): +class __extend__(pairtype(IntegerRepr, CharRepr)): def rtype_mul(_, hop): v_int, v_char = hop.inputargs(Signed, char_repr) return hop.gendirectcall(ll_char_mul, v_char, v_int) 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 Jul 20 15:35:54 2005 @@ -397,3 +397,13 @@ else: res = interpret(fn, [i, j]) assert res == expected + + +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) == "" + From ac at codespeak.net Wed Jul 20 16:57:14 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 16:57:14 +0200 (CEST) Subject: [pypy-svn] r14819 - pypy/dist/pypy/objspace/std Message-ID: <20050720145714.3E27927B7C@code1.codespeak.net> Author: ac Date: Wed Jul 20 16:57:13 2005 New Revision: 14819 Modified: pypy/dist/pypy/objspace/std/intobject.py Log: Fix oct/hex. Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Wed Jul 20 16:57:13 2005 @@ -404,31 +404,10 @@ return space.newfloat(x) def oct__Int(space, w_int1): - x = w_int1.intval - if x < 0: - ## XXX what about this warning? - #if (PyErr_Warn(PyExc_FutureWarning, - # "hex()/oct() of negative int will return " - # "a signed string in Python 2.4 and up") < 0) - # return NULL; - pass - if x == 0: - ret = "0" - else: - ret = "0%lo" % x - return space.wrap(ret) + return space.wrap(oct(w_int1.intval)) def hex__Int(space, w_int1): - x = w_int1.intval - if x < 0: - ## XXX what about this warning? - #if (PyErr_Warn(PyExc_FutureWarning, - # "hex()/oct() of negative int will return " - # "a signed string in Python 2.4 and up") < 0) - # return NULL; - pass - ret = "0x%lx" % x - return space.wrap(ret) + return space.wrap(hex(w_int1.intval)) def getnewargs__Int(space, w_int1): return space.newtuple([W_IntObject(space, w_int1.intval)]) From ac at codespeak.net Wed Jul 20 16:58:49 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 16:58:49 +0200 (CEST) Subject: [pypy-svn] r14820 - pypy/dist/pypy/module/posix/test Message-ID: <20050720145849.8AAA727B7C@code1.codespeak.net> Author: ac Date: Wed Jul 20 16:58:49 2005 New Revision: 14820 Modified: pypy/dist/pypy/module/posix/test/test_posix.py Log: Fix typo. Modified: pypy/dist/pypy/module/posix/test/test_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix.py Wed Jul 20 16:58:49 2005 @@ -91,7 +91,7 @@ text = 'This is a test' os.write(fi,text) res = interpret(f,[fi]) - raises( OSError(), os.fstat(fi)) + raises(OSError, os.fstat, fi) def test_ftruncate(): def f(fi,len): From ac at codespeak.net Wed Jul 20 17:00:01 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Jul 2005 17:00:01 +0200 (CEST) Subject: [pypy-svn] r14821 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050720150001.3E78227B7C@code1.codespeak.net> Author: ac Date: Wed Jul 20 17:00:00 2005 New Revision: 14821 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/intobject.py Log: Merge changes of intobject from trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/intobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/intobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/intobject.py Wed Jul 20 17:00:00 2005 @@ -209,13 +209,8 @@ m = x % y return space.wrap((z,m)) -old_style_div = 1 / 2 == 1 // 2 def div__Int_Int(space, w_int1, w_int2): - # Select the proper div - if old_style_div: - return _floordiv(space, w_int1, w_int2) - else: - return _truediv(space, w_int1, w_int2) + return _floordiv(space, w_int1, w_int2) floordiv__Int_Int = _floordiv truediv__Int_Int = _truediv @@ -409,31 +404,10 @@ return space.newfloat(x) def oct__Int(space, w_int1): - x = w_int1.intval - if x < 0: - ## XXX what about this warning? - #if (PyErr_Warn(PyExc_FutureWarning, - # "hex()/oct() of negative int will return " - # "a signed string in Python 2.4 and up") < 0) - # return NULL; - pass - if x == 0: - ret = "0" - else: - ret = "0%lo" % x - return space.wrap(ret) + return space.wrap(oct(w_int1.intval)) def hex__Int(space, w_int1): - x = w_int1.intval - if x < 0: - ## XXX what about this warning? - #if (PyErr_Warn(PyExc_FutureWarning, - # "hex()/oct() of negative int will return " - # "a signed string in Python 2.4 and up") < 0) - # return NULL; - pass - ret = "0x%lx" % x - return space.wrap(ret) + return space.wrap(hex(w_int1.intval)) def getnewargs__Int(space, w_int1): return space.newtuple([W_IntObject(space, w_int1.intval)]) From ale at codespeak.net Wed Jul 20 17:04:02 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 20 Jul 2005 17:04:02 +0200 (CEST) Subject: [pypy-svn] r14822 - pypy/dist/pypy/module/posix Message-ID: <20050720150402.368E327B7C@code1.codespeak.net> Author: ale Date: Wed Jul 20 17:04:00 2005 New Revision: 14822 Modified: pypy/dist/pypy/module/posix/interp_posix.py Log: Oops - typos Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Wed Jul 20 17:04:00 2005 @@ -1,4 +1,4 @@ -from pypy.interpreter.baseobjspace import ObjSpace,W_Root +from pypy.interpreter.baseobjspace import ObjSpace import os from os import * @@ -18,7 +18,7 @@ def isatty(space, fd): return os.isatty(w_fd) -lseek.unwrap_spec = [ObjSpace, int] +isatty.unwrap_spec = [ObjSpace, int] def read(space, fd, buffersize): return os.read(fd,buffersize) From pedronis at codespeak.net Wed Jul 20 17:41:39 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 17:41:39 +0200 (CEST) Subject: [pypy-svn] r14823 - in pypy/dist/pypy/rpython: . test Message-ID: <20050720154139.EF79727B7C@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 17:41:36 2005 New Revision: 14823 Modified: pypy/dist/pypy/rpython/rslice.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/rpython/test/test_rtyper.py Log: - another char*num test - slice repr key was returning the same key for different repr choices, fix and some testing Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Wed Jul 20 17:41:36 2005 @@ -38,11 +38,16 @@ return startonly_slice_repr else: return startstop_slice_repr + def rtyper_makekey(self): - return (self.__class__, - self.start.rtyper_makekey(), - self.stop.rtyper_makekey(), - self.step.rtyper_makekey()) + if (self.start.is_constant() and self.start.const in (None, 0) and + self.stop.is_constant() and self.stop.const == -1): + kind = "minusone" # [:-1] + elif self.stop.is_constant() and self.stop.const is None: + kind = "startonly" + else: + kind = "startstop" + return self.__class__, kind class SliceRepr(Repr): 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 Jul 20 17:41:36 2005 @@ -407,3 +407,10 @@ 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) == "" Modified: pypy/dist/pypy/rpython/test/test_rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtyper.py (original) +++ pypy/dist/pypy/rpython/test/test_rtyper.py Wed Jul 20 17:41:36 2005 @@ -13,7 +13,7 @@ def teardown_module(mod): py.log._setstate(mod.logstate) -def test_reprkey_dont_clash(): +def test_reprkeys_dont_clash(): stup1 = annmodel.SomeTuple((annmodel.SomeFloat(), annmodel.SomeInteger())) stup2 = annmodel.SomeTuple((annmodel.SomeString(), @@ -22,6 +22,35 @@ key2 = stup2.rtyper_makekey() assert key1 != key2 +def test_slice_reprkeys(): + one = annmodel.SomeInteger(nonneg=True) + one.const = 1 + three = annmodel.SomeInteger(nonneg=True) + three.const = 3 + minusone = annmodel.SomeInteger() + minusone.const = -1 + none = annmodel.SomePBC({None: True}) + + startonly = annmodel.SomeSlice(one, none, none) + startonly2 = annmodel.SomeSlice(one, none, one) + startonly3 = annmodel.SomeSlice(three, none, one) + + startstop = annmodel.SomeSlice(one, one, none) + startstop2 = annmodel.SomeSlice(one, one, one) + startstop3 = annmodel.SomeSlice(one, three, none) + + minusone_slice = annmodel.SomeSlice(none, minusone, none) + minusone_slice2 = annmodel.SomeSlice(none, minusone, one) + + assert startonly.rtyper_makekey() == startonly2.rtyper_makekey() == startonly3.rtyper_makekey() + assert startstop.rtyper_makekey() == startstop2.rtyper_makekey() == startstop3.rtyper_makekey() + assert minusone_slice.rtyper_makekey() == minusone_slice2.rtyper_makekey() + + assert startonly.rtyper_makekey() != startstop.rtyper_makekey() + assert startonly.rtyper_makekey() != minusone_slice.rtyper_makekey() + assert minusone_slice.rtyper_makekey() != startstop.rtyper_makekey() + + def test_simple(): def dummyfn(x): return x+1 From pedronis at codespeak.net Wed Jul 20 17:47:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 20 Jul 2005 17:47:44 +0200 (CEST) Subject: [pypy-svn] r14824 - pypy/dist/pypy/module/unicodedata Message-ID: <20050720154744.77DBA27B7C@code1.codespeak.net> Author: pedronis Date: Wed Jul 20 17:47:42 2005 New Revision: 14824 Modified: pypy/dist/pypy/module/unicodedata/function.py Log: a default is always required for dict.get Modified: pypy/dist/pypy/module/unicodedata/function.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/function.py (original) +++ pypy/dist/pypy/module/unicodedata/function.py Wed Jul 20 17:47:42 2005 @@ -150,7 +150,7 @@ result[j + 2] = T j += 3 continue - decomp = decomposition.get(ch) + decomp = decomposition.get(ch, []) if decomp: decomplen = len(decomp) if j + decomplen > resultlen: From hpk at codespeak.net Wed Jul 20 19:48:37 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 20 Jul 2005 19:48:37 +0200 (CEST) Subject: [pypy-svn] r14828 - pypy/extradoc/sprintinfo Message-ID: <20050720174837.BC34527B84@code1.codespeak.net> Author: hpk Date: Wed Jul 20 19:48:35 2005 New Revision: 14828 Added: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt (contents, props changed) Log: added some information about the hildesheim2 sprint i am currently organizing. Added: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Wed Jul 20 19:48:35 2005 @@ -0,0 +1,46 @@ +Hildesheim2 PyPy sprint +====================================================== + +The next internal PyPy sprint is scheduled 25th-31st July 2005 +at Trillke-Gut, Hildesheim, Germany. Its focus will be +intensely working on getting a self-contained PyPy version. + +Currently scheduled to come: + + Armin Rigo 25th-31st (?) + Samuele Pedroni 24th-1st + Christian Tismer 25th-31st (?) + Carl Friedrich Bolz 25th-31st (not there on 27th) + Holger Krekel 24th-31st + +Anyone, who is somewhat experienced with PyPy already, +is invited to come. For new people it will make more +sense to attend the next big public sprint in Heidelberg +(also Germany) end of August. + +Location & Accomodation +------------------------ + +The sprint will be held in the merlinux offices (or in a larger +room if more people decide to come). + +Holger tries to organize private accomodation for all participants. +However, attendees should be prepared to share a room with +another participant. Also the rooms will be located in a +living group (german WG). If you want something more separate +or private, ask holger to look for a hotel closeby. + +Getting there +----------------- + +Take a train to "Hildesheim Hauptbahnhof" (there are ICE's from +Berlin and the south of germany, or trains from Hannover, use +http://www.bahn.de to plan). Then take the bus number 3 +direction "Hildesheimer Wald" and get out at "Waldquelle". +The full address is: + + Trillke-Gut + Steinbergstr. 42 + 31139 Hildesheim + Tel. +49 5121 47247 + From hpk at codespeak.net Wed Jul 20 19:58:07 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 20 Jul 2005 19:58:07 +0200 (CEST) Subject: [pypy-svn] r14829 - pypy/extradoc/sprintinfo Message-ID: <20050720175807.4320C27B7C@code1.codespeak.net> Author: hpk Date: Wed Jul 20 19:58:05 2005 New Revision: 14829 Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Log: some ReST fixes Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Wed Jul 20 19:58:05 2005 @@ -5,7 +5,7 @@ at Trillke-Gut, Hildesheim, Germany. Its focus will be intensely working on getting a self-contained PyPy version. -Currently scheduled to come: +Currently scheduled to come:: Armin Rigo 25th-31st (?) Samuele Pedroni 24th-1st @@ -37,10 +37,9 @@ Berlin and the south of germany, or trains from Hannover, use http://www.bahn.de to plan). Then take the bus number 3 direction "Hildesheimer Wald" and get out at "Waldquelle". -The full address is: +The full address is:: Trillke-Gut Steinbergstr. 42 31139 Hildesheim - Tel. +49 5121 47247 From cfbolz at codespeak.net Wed Jul 20 20:33:40 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Jul 2005 20:33:40 +0200 (CEST) Subject: [pypy-svn] r14830 - pypy/extradoc/sprintinfo Message-ID: <20050720183340.04CC527B74@code1.codespeak.net> Author: cfbolz Date: Wed Jul 20 20:33:39 2005 New Revision: 14830 Added: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Log: added draft for Heidelberg sprint announcement. Added: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Wed Jul 20 20:33:39 2005 @@ -0,0 +1,62 @@ +PyPy Sprint in Heidelberg 22nd - 29th August 2005 +================================================== + +The next PyPy sprint is scheduled for end of August in +Heidelberg, Germany. Its main focus is to translate the whole +PyPy interpreter to a low level language. To learn more +about the new PyPy Python-in-Python implementation look here: + + http://codespeak.net/pypy + + +Goals and topics of the sprint +------------------------------ + +XXX The focus will probably be translation issues, +possibly including garbage collection and threading (?). + +Location & Accomodation +------------------------ + +The sprint will be held in a conference room of the Institute of Physics, +University of Heidelberg. We have WLAN connection there and small kitchen +to make tea and coffee. `See here`_ how to get there from the Heidelberg +main station. + +There is a huge number of hotels_ in Heidelberg, all of which are +unfortunately rather expensive. It should be no problem to reach the sprint +venue from anywhere in Heidelberg. As an alternative you could also take a +`hotel in Mannheim`_ which you can reach in 15 min from Heidelberg with the +train. If there is enough interest Carl could try to rent a room in a living +group (WG). + +.. _`See here`: http://www.physi.uni-heidelberg.de/physi/front/anfahrt.en.php +.. _hotels: http://www.cvb-heidelberg.de/index_eng.html +.. _`hotel in Mannheim`: www.hotel.de/mannheim + +Exact times +----------- + +The Pypy sprint is held Monday 22nd August - Monday 29th August 2005. +Hours will be from 09:00 until people have had enough. It's a good +idea to arrive a day before the sprint starts. + + +Network, Food +------------- + +The Heidelberg Altstadt can be reached in approximately 10 min from the sprint +venue. There you will find all kinds of restaurants and fast food places. + +You need a wireless network card to access the network. + + +Registration etc.pp. +-------------------- + +Please subscribe to the `PyPy sprint mailing list`_, introduce +yourself and post a note that you want to come. Feel free +to ask any questions there! + +.. _`PyPy sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint + From cfbolz at codespeak.net Wed Jul 20 20:37:33 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Jul 2005 20:37:33 +0200 (CEST) Subject: [pypy-svn] r14831 - pypy/extradoc/sprintinfo Message-ID: <20050720183733.2900527B86@code1.codespeak.net> Author: cfbolz Date: Wed Jul 20 20:37:32 2005 New Revision: 14831 Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Log: fix link Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Heidelberg-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Wed Jul 20 20:37:32 2005 @@ -32,7 +32,7 @@ .. _`See here`: http://www.physi.uni-heidelberg.de/physi/front/anfahrt.en.php .. _hotels: http://www.cvb-heidelberg.de/index_eng.html -.. _`hotel in Mannheim`: www.hotel.de/mannheim +.. _`hotel in Mannheim`: http://www.hotel.de/mannheim Exact times ----------- From cfbolz at codespeak.net Wed Jul 20 20:40:00 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Jul 2005 20:40:00 +0200 (CEST) Subject: [pypy-svn] r14832 - pypy/extradoc/sprintinfo Message-ID: <20050720184000.29A6527B88@code1.codespeak.net> Author: cfbolz Date: Wed Jul 20 20:39:59 2005 New Revision: 14832 Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Log: found even better page. Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Heidelberg-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Wed Jul 20 20:39:59 2005 @@ -32,7 +32,7 @@ .. _`See here`: http://www.physi.uni-heidelberg.de/physi/front/anfahrt.en.php .. _hotels: http://www.cvb-heidelberg.de/index_eng.html -.. _`hotel in Mannheim`: http://www.hotel.de/mannheim +.. _`hotel in Mannheim`: http://www.hotels.de/en/mannheim.htm Exact times ----------- From ericvrp at codespeak.net Thu Jul 21 00:35:21 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 00:35:21 +0200 (CEST) Subject: [pypy-svn] r14836 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050720223521.47C0927B88@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 00:35:20 2005 New Revision: 14836 Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: simplified tests because PBC work now last test fails still (probably) because rpython/module/ll_os.py/ll_os_read raises an exception. (errormessage: AttributeError: 'FuncNode' object has no attribute 'write_exceptblock') Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Thu Jul 21 00:35:20 2005 @@ -1,6 +1,7 @@ from __future__ import division import sys +import os import py from pypy.tool.udir import udir @@ -10,7 +11,6 @@ py.log.setconsumer("genllvm database prepare", None) def test_external_function_ll_os_dup(): - import os def fn(): return os.dup(0) f = compile_function(fn, []) @@ -43,71 +43,51 @@ assert duration >= delay_time - 0.5 assert duration <= delay_time + 0.5 -class TestOSLevelFunctions: - def setup_method(self, method): - path = udir.join("e") - self.path = path - self.pathints = map(ord, path) - +path = str(udir.join("e")) + def test_os_file_ops_open_close(): - # the test is overly complicated because - # we don't have prebuilt string constants yet - import os - def openclose(a,b,c,d,e,f): - s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) + def openclose(): + fd = os.open(path, os.O_CREAT|os.O_RDWR, 0777) os.close(fd) return fd - path = '/tmp/b' if os.path.exists(path): os.unlink(path) - f = compile_function(openclose, [int] * len(path)) - result = f(*map(ord, path)) + f = compile_function(openclose, []) + result = f() assert os.path.exists(path) def test_os_file_ops_open_write_close(): - # the test is overly complicated because - # we don't have prebuilt string constants yet - import os - def openwriteclose(a,b,c,d,e,f): - s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) - byteswritten = os.write(fd, s) + def openwriteclose(): + fd = os.open(path, os.O_CREAT|os.O_RDWR, 0777) + byteswritten = os.write(fd, path) os.close(fd) return byteswritten - path = '/tmp/b' if os.path.exists(path): os.unlink(path) - f = compile_function(openwriteclose, [int] * len(path)) - result = f(*map(ord, path)) + f = compile_function(openwriteclose, []) + result = f() assert os.path.exists(path) assert open(path).read() == path -def Xtest_os_file_ops_open_write_read_close(): - # the test is overly complicated because - # we don't have prebuilt string constants yet - import os - def openwriteclose_openreadclose(a,b,c,d,e,f): - s = chr(a) + chr(b) + chr(c) + chr(d) + chr(e) + chr(f) - - fd = os.open(s, os.O_CREAT|os.O_RDWR, 0777) - byteswritten = os.write(fd, s+s+s) +def test_os_file_ops_open_write_read_close(): + def openwriteclose_openreadclose(): + fd = os.open(path, os.O_CREAT|os.O_RDWR, 0777) + byteswritten = os.write(fd, path+path+path) os.close(fd) - fd = os.open(s, os.O_RDWR, 0777) + fd = os.open(path, os.O_RDWR, 0777) maxread = 1000 r = os.read(fd, maxread) os.close(fd) return len(r) - path = '/tmp/b' if os.path.exists(path): os.unlink(path) - f = compile_function(openwriteclose_openreadclose, [int] * len(path)) - result = f(*map(ord, path)) + f = compile_function(openwriteclose_openreadclose, []) + result = f() assert os.path.exists(path) assert open(path).read() == path * 3 assert result is len(path) * 3 From ericvrp at codespeak.net Thu Jul 21 00:42:23 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 00:42:23 +0200 (CEST) Subject: [pypy-svn] r14837 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050720224223.EF9C027B8C@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 00:42:22 2005 New Revision: 14837 Added: pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/opwriter.py Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py Log: - moved parts of funcnode.py into extfuncnode.py and opwriter.py - simplified extfuncnode.py by not special-casing functions that have a one-to-one c-equivalent - moved (optimization) code for tracking which externl functions are actually used from LLVMNode to external node. - simplified external function node detection in database.py - added ll_os_dup and ll_os_close to extfunction.py because they are no longer special-case - use the new suggested_primitive methology Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Thu Jul 21 00:42:22 2005 @@ -1,5 +1,6 @@ from pypy.translator.llvm2.log import log -from pypy.translator.llvm2.funcnode import ExternalFuncNode, FuncNode, FuncTypeNode +from pypy.translator.llvm2.funcnode import FuncNode, FuncTypeNode +from pypy.translator.llvm2.extfuncnode import ExternalFuncNode from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode @@ -75,8 +76,7 @@ def create_constant_node(self, type_, value): node = None if isinstance(type_, lltype.FuncType): - if value._callable and (not hasattr(value, "graph") or value.graph is None - or getattr(value._callable, "suggested_primitive", False)): + if getattr(value._callable, "suggested_primitive", False): node = ExternalFuncNode(self, value) else: node = FuncNode(self, value) Added: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Thu Jul 21 00:42:22 2005 @@ -0,0 +1,37 @@ +import py +from pypy.objspace.flow.model import Block, Constant, Variable, Link +from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.rpython import lltype +from pypy.translator.backendoptimization import remove_same_as +from pypy.translator.unsimplify import remove_double_links +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode +from pypy.translator.llvm2.atomic import is_atomic +from pypy.translator.llvm2.log import log +from pypy.rpython.extfunctable import table as extfunctable +log = log.extfuncnode + +class ExternalFuncNode(LLVMNode): + + used_external_functions = {} + + def __init__(self, db, value): + self.db = db + self.value = value + self.ref = "%" + value._callable.__name__ + + def setup(self): + self._issetup = True + + def getdecl(self): + T = self.value._TYPE + args = [self.db.repr_arg_type(a) for a in T.ARGS] + decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), + self.ref, + ", ".join(args)) + return decl + + def writedecl(self, codewriter): + codewriter.declare(self.getdecl()) + + def writeimpl(self, codewriter): + self.used_external_functions[self.ref] = True Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Thu Jul 21 00:42:22 2005 @@ -5,6 +5,8 @@ declare int %time(int*) ;void* actually declare int %clock() declare void %sleep(int) +declare int %dup(int) +declare void %close(int) declare int %open(sbyte*, int, int) declare int %write(int, sbyte*, int) declare int %read(int, sbyte*, int) @@ -67,22 +69,6 @@ """) -extfunctions["%new.st.var.rpy_string.0.helper"] = ((), """ -%st.rpy_string.0 * %new.st.var.rpy_string.0.helper(int %len) { - %size = getelementptr %st.rpy_string.0* null, int 0, uint 1, uint 1, int %len - %usize = cast sbyte* %size to uint - %malloc.Size.5 = getelementptr sbyte* null, uint %usize - %malloc.SizeU.5 = cast sbyte* %malloc.Size.5 to uint - %malloc.Ptr.5 = call sbyte* %gc_malloc(uint %malloc.SizeU.5) - %ptr = cast sbyte* %malloc.Ptr.5 to sbyte* - %result = cast sbyte* %ptr to %st.rpy_string.0* - %arraylength = getelementptr %st.rpy_string.0* %result, int 0, uint 1, uint 0 - store int %len, int* %arraylength - ret %st.rpy_string.0* %result -} - -""") - extfunctions["%ll_time_time"] = ((), """ double %ll_time_time() { %v0 = call int %time(int* null) @@ -96,7 +82,7 @@ double %ll_time_clock() { %v0 = call int %clock() %v1 = cast int %v0 to double - ; XXX how to get at the proper division constant per platform? + ; XXX how to get at the proper division (or any other) constant per platform? %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC accrdoing to single unix spec ret double %v2 } @@ -112,6 +98,22 @@ """) +extfunctions["%ll_os_dup"] = ((), """ +int %ll_os_dup(int %fd) { + %ret = call int %dup(int %fd) + ret int %ret +} + +""") + +extfunctions["%ll_os_close"] = ((), """ +void %ll_os_close(int %fd) { + call void %close(int %fd) + ret void +} + +""") + extfunctions["%ll_os_open"] = (("%cast",), """ int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) { %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) @@ -132,21 +134,16 @@ """) -extfunctions["%ll_os_read"] = (("%new.st.var.rpy_string.0.helper",), """ -%st.rpy_string.0* %ll_os_read(int %fd, int %buffersize) { - ;This is a bit simplistic! It really allocated a large enough buffer to hold all the data in. - %str = call %st.rpy_string.0* %new.st.var.rpy_string.0.helper(int %buffersize) +extfunctions["%ll_read_into"] = ((), """ +int %ll_read_into(int %fd, %st.rpy_string.0* %structstring) { + %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr - ;load the actual data - %destptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 1 + %destptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 %dest = cast [0 x sbyte]* %destptr to sbyte* - %bytesread = call int %read(int %fd, sbyte* %dest, int %buffersize) - - ;set str.length to number of bytes read - %reallengthptr = getelementptr %st.rpy_string.0* %str, int 0, uint 1, uint 0 - store int %bytesread, int* %reallengthptr - ret %st.rpy_string.0* %str + %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength) + ret int %bytesread } """) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 21 00:42:22 2005 @@ -5,13 +5,13 @@ from pypy.translator.backendoptimization import remove_same_as from pypy.translator.unsimplify import remove_double_links from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode +from pypy.translator.llvm2.opwriter import OpWriter from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log from pypy.rpython.extfunctable import table as extfunctable nextnum = py.std.itertools.count().next log = log.funcnode - class FuncTypeNode(LLVMNode): def __init__(self, db, type_): self.db = db @@ -67,15 +67,6 @@ codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): - - # XXX Code checks for when the rpython extfunctable has set the annotable - # flag to True????? - _callable = self.value._callable - for func, extfuncinfo in extfunctable.iteritems(): # precompute a dict? - if _callable is extfuncinfo.ll_function: - log('skipped output of external function %s' % self.value._name) - return - assert self._issetup graph = self.graph log.writeimpl(graph.name) @@ -155,305 +146,3 @@ codewriter.ret(inputargtype, inputarg) else: codewriter.ret_void() - - -class ExternalFuncNode(LLVMNode): - - fnmapping = { #functions that have one-to-one C equivalents - "%ll_os_dup": "%dup", - "%ll_os_close": "%close", - } - - def __init__(self, db, value): - self.db = db - self.value = value - self.ref = "%" + value._callable.__name__ - - def setup(self): - self._issetup = True - - def getdecl(self): - T = self.value._TYPE - args = [self.db.repr_arg_type(a) for a in T.ARGS] - decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), - self.ref, - ", ".join(args)) - return decl - - def getcdecl(self): - #XXX Mapping - T = self.value._TYPE - args = [self.db.repr_arg_type(a) for a in T.ARGS] - decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), - self.fnmapping[self.ref], - ", ".join(args)) - return decl - - # ______________________________________________________________________ - # main entry points from genllvm - def writedecl(self, codewriter): - codewriter.declare(self.getdecl()) - - if self.ref in self.fnmapping: - codewriter.declare(self.getcdecl()) - - def writeimpl(self, codewriter): - if self.ref not in self.fnmapping: - self.used_external_functions[self.ref] = True - return - - T = self.value._TYPE - args = ["%s %%a%s" % (self.db.repr_arg_type(a), c) - for c, a in enumerate(T.ARGS)] - - decl = "%s %s(%s)" % (self.db.repr_arg_type(T.RESULT), - self.ref, - ", ".join(args)) - - codewriter.openfunc(decl) - - # go thru and map argsXXX - argrefs = ["%%a%s" % c for c in range(len(T.ARGS))] - argtypes = [self.db.repr_arg_type(a) for a in T.ARGS] - - # get return type (mapped perhaps) - resulttype = self.db.repr_arg_type(T.RESULT) - - # get function name - fnname = self.fnmapping[self.ref] - - # call - if resulttype != "void": - # map resulttype ??? XXX - codewriter.call("%res", resulttype, fnname, argrefs, argtypes) - codewriter.ret(resulttype, "%res") - else: - codewriter.call_void(fnname, argrefs, argtypes) - codewriter.ret_void() - - codewriter.closefunc() - -class OpWriter(object): - binary_operations = {'int_mul': 'mul', - 'int_add': 'add', - 'int_sub': 'sub', - 'int_floordiv': 'div', - 'int_mod': 'rem', - 'int_lt': 'setlt', - 'int_le': 'setle', - 'int_eq': 'seteq', - 'int_ne': 'setne', - 'int_ge': 'setge', - 'int_gt': 'setgt', - - 'uint_mul': 'mul', - 'uint_add': 'add', - 'uint_sub': 'sub', - 'uint_floordiv': 'div', - 'uint_mod': 'rem', - 'uint_lt': 'setlt', - 'uint_le': 'setle', - 'uint_eq': 'seteq', - 'uint_ne': 'setne', - 'uint_ge': 'setge', - 'uint_gt': 'setgt', - - 'char_lt': 'setlt', - 'char_le': 'setle', - 'char_eq': 'seteq', - 'char_ne': 'setne', - 'char_ge': 'setge', - 'char_gt': 'setgt', - - 'float_mul': 'mul', - 'float_add': 'add', - 'float_sub': 'sub', - 'float_truediv': 'div', - 'float_mod': 'rem', - 'float_lt': 'setlt', - 'float_le': 'setle', - 'float_eq': 'seteq', - 'float_ne': 'setne', - 'float_ge': 'setge', - 'float_gt': 'setgt', - } - - def __init__(self, db, codewriter): - self.db = db - self.codewriter = codewriter - - def write_operation(self, op): - if op.opname in self.binary_operations: - self.binaryop(op) - else: - meth = getattr(self, op.opname, None) - assert meth is not None, "operation %r not found" %(op.opname,) - meth(op) - - def int_neg(self, op): - self.codewriter.binaryop("sub", - self.db.repr_arg(op.result), - self.db.repr_arg_type(op.args[0]), - "0", - self.db.repr_arg(op.args[0]), - ) - - def bool_not(self, op): - self.codewriter.binaryop("xor", - self.db.repr_arg(op.result), - self.db.repr_arg_type(op.args[0]), - self.db.repr_arg(op.args[0]), - "true") - - - - def binaryop(self, op): - name = self.binary_operations[op.opname] - assert len(op.args) == 2 - self.codewriter.binaryop(name, - self.db.repr_arg(op.result), - self.db.repr_arg_type(op.args[0]), - self.db.repr_arg(op.args[0]), - self.db.repr_arg(op.args[1])) - - def cast_primitive(self, op): #works for all primitives - assert len(op.args) == 1 - targetvar = self.db.repr_arg(op.result) - targettype = self.db.repr_arg_type(op.result) - fromvar = self.db.repr_arg(op.args[0]) - fromtype = self.db.repr_arg_type(op.args[0]) - self.codewriter.cast(targetvar, fromtype, fromvar, targettype) - - cast_pointer = cast_primitive - cast_bool_to_int = cast_primitive - cast_bool_to_uint = uint_is_true = cast_primitive - cast_int_to_char = cast_char_to_int = cast_primitive - cast_int_to_uint = cast_primitive - - def int_is_true(self, op): - self.codewriter.binaryop("setne", - self.db.repr_arg(op.result), - self.db.repr_arg_type(op.args[0]), - self.db.repr_arg(op.args[0]), - "0") - - uint_is_true = int_is_true - - def float_is_true(self, op): - self.codewriter.binaryop("setne", - self.db.repr_arg(op.result), - self.db.repr_arg_type(op.args[0]), - self.db.repr_arg(op.args[0]), - "0.0") - - def direct_call(self, op): - assert len(op.args) >= 1 - targetvar = self.db.repr_arg(op.result) - returntype = self.db.repr_arg_type(op.result) - functionref = self.db.repr_arg(op.args[0]) - argrefs = self.db.repr_arg_multi(op.args[1:]) - argtypes = self.db.repr_arg_type_multi(op.args[1:]) - if returntype != "void": - self.codewriter.call(targetvar, returntype, functionref, argrefs, - argtypes) - else: - self.codewriter.call_void(functionref, argrefs, argtypes) - - def malloc(self, op): - targetvar = self.db.repr_arg(op.result) - arg = op.args[0] - assert (isinstance(arg, Constant) and - isinstance(arg.value, lltype.Struct)) - #XXX unclean - node = self.db.obj2node[arg.value] - type_ = node.ref - self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) - - def malloc_varsize(self, op): - targetvar = self.db.repr_arg(op.result) - arg_type = op.args[0] - assert (isinstance(arg_type, Constant) and - isinstance(arg_type.value, (lltype.Array, lltype.Struct))) - #XXX unclean - struct_type = self.db.obj2node[arg_type.value].ref - struct_cons = self.db.obj2node[arg_type.value].constructor_ref - argrefs = self.db.repr_arg_multi(op.args[1:]) - argtypes = self.db.repr_arg_type_multi(op.args[1:]) - self.codewriter.call(targetvar, struct_type + "*", struct_cons, - argrefs, argtypes) - - def getfield(self, op): - tmpvar = self.db.repr_tmpvar() - struct, structtype = self.db.repr_argwithtype(op.args[0]) - fieldnames = list(op.args[0].concretetype.TO._names) - index = fieldnames.index(op.args[1].value) - targetvar = self.db.repr_arg(op.result) - targettype = self.db.repr_arg_type(op.result) - if targettype != "void": - self.codewriter.getelementptr(tmpvar, structtype, struct, - ("uint", index)) - self.codewriter.load(targetvar, targettype, tmpvar) - else: - self.codewriter.comment("***Skipping operation getfield()***", - indent=True) - - def getsubstruct(self, op): - struct, structtype = self.db.repr_argwithtype(op.args[0]) - fieldnames = list(op.args[0].concretetype.TO._names) - index = fieldnames.index(op.args[1].value) - targetvar = self.db.repr_arg(op.result) - targettype = self.db.repr_arg_type(op.result) - assert targettype != "void" - self.codewriter.getelementptr(targetvar, structtype, - struct, ("uint", index)) - - def setfield(self, op): - tmpvar = self.db.repr_tmpvar() - struct, structtype = self.db.repr_argwithtype(op.args[0]) - fieldnames = list(op.args[0].concretetype.TO._names) - index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, structtype, struct, - ("uint", index)) - valuevar, valuetype = self.db.repr_argwithtype(op.args[2]) - assert valuetype != "void" - self.codewriter.store(valuetype, valuevar, tmpvar) - - def getarrayitem(self, op): - array, arraytype = self.db.repr_argwithtype(op.args[0]) - index = self.db.repr_arg(op.args[1]) - indextype = self.db.repr_arg_type(op.args[1]) - tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, arraytype, array, - ("uint", 1), (indextype, index)) - targetvar = self.db.repr_arg(op.result) - targettype = self.db.repr_arg_type(op.result) - self.codewriter.load(targetvar, targettype, tmpvar) - - def getarraysubstruct(self, op): - array, arraytype = self.db.repr_argwithtype(op.args[0]) - index = self.db.repr_arg(op.args[1]) - indextype = self.db.repr_arg_type(op.args[1]) - targetvar = self.db.repr_arg(op.result) - self.codewriter.getelementptr(targetvar, arraytype, array, - ("uint", 1), (indextype, index)) - - def setarrayitem(self, op): - array, arraytype = self.db.repr_argwithtype(op.args[0]) - index = self.db.repr_arg(op.args[1]) - indextype = self.db.repr_arg_type(op.args[1]) - - tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, arraytype, array, - ("uint", 1), (indextype, index)) - - valuevar = self.db.repr_arg(op.args[2]) - valuetype = self.db.repr_arg_type(op.args[2]) - self.codewriter.store(valuetype, valuevar, tmpvar) - - def getarraysize(self, op): - array, arraytype = self.db.repr_argwithtype(op.args[0]) - tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0)) - targetvar = self.db.repr_arg(op.result) - targettype = self.db.repr_arg_type(op.result) - self.codewriter.load(targetvar, targettype, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Thu Jul 21 00:42:22 2005 @@ -11,7 +11,7 @@ from pypy.rpython import lltype from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter -from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.extfuncnode import ExternalFuncNode from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.extfunction import extdeclarations, \ @@ -31,7 +31,7 @@ remove_void(translator) #rename_extfunc_calls(translator) translator.checkgraphs() - LLVMNode.used_external_functions = {} + ExternalFuncNode.used_external_functions = {} def compile(self, func=None): if func is None: @@ -77,7 +77,7 @@ typ_decl.writeimpl(codewriter) depdone = {} - for funcname,value in LLVMNode.used_external_functions.iteritems(): + for funcname,value in ExternalFuncNode.used_external_functions.iteritems(): deps = dependencies(funcname,[]) deps.reverse() for dep in deps: Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Thu Jul 21 00:42:22 2005 @@ -1,7 +1,4 @@ class LLVMNode(object): - - used_external_functions = {} - def ref(): def _get_ref(self): return self._ref Added: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Thu Jul 21 00:42:22 2005 @@ -0,0 +1,236 @@ +import py +from pypy.objspace.flow.model import Block, Constant, Variable, Link +from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.rpython import lltype +from pypy.translator.backendoptimization import remove_same_as +from pypy.translator.unsimplify import remove_double_links +from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode +from pypy.translator.llvm2.atomic import is_atomic +from pypy.translator.llvm2.log import log +from pypy.rpython.extfunctable import table as extfunctable +log = log.opwriter + +class OpWriter(object): + binary_operations = {'int_mul': 'mul', + 'int_add': 'add', + 'int_sub': 'sub', + 'int_floordiv': 'div', + 'int_mod': 'rem', + 'int_lt': 'setlt', + 'int_le': 'setle', + 'int_eq': 'seteq', + 'int_ne': 'setne', + 'int_ge': 'setge', + 'int_gt': 'setgt', + + 'uint_mul': 'mul', + 'uint_add': 'add', + 'uint_sub': 'sub', + 'uint_floordiv': 'div', + 'uint_mod': 'rem', + 'uint_lt': 'setlt', + 'uint_le': 'setle', + 'uint_eq': 'seteq', + 'uint_ne': 'setne', + 'uint_ge': 'setge', + 'uint_gt': 'setgt', + + 'char_lt': 'setlt', + 'char_le': 'setle', + 'char_eq': 'seteq', + 'char_ne': 'setne', + 'char_ge': 'setge', + 'char_gt': 'setgt', + + 'float_mul': 'mul', + 'float_add': 'add', + 'float_sub': 'sub', + 'float_truediv': 'div', + 'float_mod': 'rem', + 'float_lt': 'setlt', + 'float_le': 'setle', + 'float_eq': 'seteq', + 'float_ne': 'setne', + 'float_ge': 'setge', + 'float_gt': 'setgt', + } + + def __init__(self, db, codewriter): + self.db = db + self.codewriter = codewriter + + def write_operation(self, op): + if op.opname in self.binary_operations: + self.binaryop(op) + else: + meth = getattr(self, op.opname, None) + assert meth is not None, "operation %r not found" %(op.opname,) + meth(op) + + def int_neg(self, op): + self.codewriter.binaryop("sub", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + "0", + self.db.repr_arg(op.args[0]), + ) + + def bool_not(self, op): + self.codewriter.binaryop("xor", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "true") + + + + def binaryop(self, op): + name = self.binary_operations[op.opname] + assert len(op.args) == 2 + self.codewriter.binaryop(name, + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + self.db.repr_arg(op.args[1])) + + def cast_primitive(self, op): #works for all primitives + assert len(op.args) == 1 + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + fromvar = self.db.repr_arg(op.args[0]) + fromtype = self.db.repr_arg_type(op.args[0]) + self.codewriter.cast(targetvar, fromtype, fromvar, targettype) + + cast_pointer = cast_primitive + cast_bool_to_int = cast_primitive + cast_bool_to_uint = uint_is_true = cast_primitive + cast_int_to_char = cast_char_to_int = cast_primitive + cast_int_to_uint = cast_primitive + + def int_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0") + + uint_is_true = int_is_true + + def float_is_true(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "0.0") + + def direct_call(self, op): + assert len(op.args) >= 1 + targetvar = self.db.repr_arg(op.result) + returntype = self.db.repr_arg_type(op.result) + functionref = self.db.repr_arg(op.args[0]) + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) + if returntype != "void": + self.codewriter.call(targetvar, returntype, functionref, argrefs, + argtypes) + else: + self.codewriter.call_void(functionref, argrefs, argtypes) + + def malloc(self, op): + targetvar = self.db.repr_arg(op.result) + arg = op.args[0] + assert (isinstance(arg, Constant) and + isinstance(arg.value, lltype.Struct)) + #XXX unclean + node = self.db.obj2node[arg.value] + type_ = node.ref + self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) + + def malloc_varsize(self, op): + targetvar = self.db.repr_arg(op.result) + arg_type = op.args[0] + assert (isinstance(arg_type, Constant) and + isinstance(arg_type.value, (lltype.Array, lltype.Struct))) + #XXX unclean + struct_type = self.db.obj2node[arg_type.value].ref + struct_cons = self.db.obj2node[arg_type.value].constructor_ref + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) + self.codewriter.call(targetvar, struct_type + "*", struct_cons, + argrefs, argtypes) + + def getfield(self, op): + tmpvar = self.db.repr_tmpvar() + struct, structtype = self.db.repr_argwithtype(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + if targettype != "void": + self.codewriter.getelementptr(tmpvar, structtype, struct, + ("uint", index)) + self.codewriter.load(targetvar, targettype, tmpvar) + else: + self.codewriter.comment("***Skipping operation getfield()***", + indent=True) + + def getsubstruct(self, op): + struct, structtype = self.db.repr_argwithtype(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + assert targettype != "void" + self.codewriter.getelementptr(targetvar, structtype, + struct, ("uint", index)) + + def setfield(self, op): + tmpvar = self.db.repr_tmpvar() + struct, structtype = self.db.repr_argwithtype(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + self.codewriter.getelementptr(tmpvar, structtype, struct, + ("uint", index)) + valuevar, valuetype = self.db.repr_argwithtype(op.args[2]) + assert valuetype != "void" + self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarrayitem(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + self.codewriter.load(targetvar, targettype, tmpvar) + + def getarraysubstruct(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + targetvar = self.db.repr_arg(op.result) + self.codewriter.getelementptr(targetvar, arraytype, array, + ("uint", 1), (indextype, index)) + + def setarrayitem(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) + index = self.db.repr_arg(op.args[1]) + indextype = self.db.repr_arg_type(op.args[1]) + + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) + + valuevar = self.db.repr_arg(op.args[2]) + valuetype = self.db.repr_arg_type(op.args[2]) + self.codewriter.store(valuetype, valuevar, tmpvar) + + def getarraysize(self, op): + array, arraytype = self.db.repr_argwithtype(op.args[0]) + tmpvar = self.db.repr_tmpvar() + self.codewriter.getelementptr(tmpvar, arraytype, array, ("uint", 0)) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + self.codewriter.load(targetvar, targettype, tmpvar) From pedronis at codespeak.net Thu Jul 21 01:13:33 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 01:13:33 +0200 (CEST) Subject: [pypy-svn] r14838 - pypy/dist/pypy/translator/goal Message-ID: <20050720231333.3060F27B86@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 01:13:32 2005 New Revision: 14838 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: link to issue98 about problems with annotating parser code Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 21 01:13:32 2005 @@ -13,7 +13,8 @@ * how to implement the three overrides of translator/ann_override.py ? - * the pypy trunk is still not annotable. + * the pypy trunk is still not annotable: + - see issue92 about parser typing problems How to work in parallel: There is an environment variable to be set with your personal random seed. From pedronis at codespeak.net Thu Jul 21 02:04:48 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 02:04:48 +0200 (CEST) Subject: [pypy-svn] r14839 - in pypy/dist/pypy: annotation objspace/std rpython rpython/test Message-ID: <20050721000448.2425727B85@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 02:04:45 2005 New Revision: 14839 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/rpython/rarithmetic.py pypy/dist/pypy/rpython/test/test_rarithmetic.py Log: ovfcheck(int()) is not supported. Implemented alternative. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu Jul 21 02:04:45 2005 @@ -229,6 +229,9 @@ def math_frexp(x): return SomeTuple((SomeFloat(), SomeInteger())) +def math_modf(x): + return SomeTuple((SomeFloat(), SomeFloat())) + def math_any(*args): return SomeFloat() @@ -295,6 +298,7 @@ BUILTIN_ANALYZERS[math.exp] = math_any BUILTIN_ANALYZERS[math.ldexp] = math_any BUILTIN_ANALYZERS[math.frexp] = math_frexp +BUILTIN_ANALYZERS[math.modf] = math_modf BUILTIN_ANALYZERS[sys.getrefcount] = count BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf import unicodedata Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Thu Jul 21 02:04:45 2005 @@ -2,7 +2,7 @@ Pure Python implementation of string utilities. """ -from pypy.rpython.rarithmetic import r_uint, ovfcheck +from pypy.rpython.rarithmetic import r_uint, ovfcheck, ovfcheck_float_to_int # XXX factor more functions out of stringobject.py. # This module is independent from PyPy. @@ -345,7 +345,7 @@ except (ParseStringOverflowError, OverflowError): fe = string_to_float(exponent) + dexp try: - e = ovfcheck(int(fe)) + e = ovfcheck_float_to_int(fe) except OverflowError: # 4) check the exponent for overflow and truncate to +-400. if exponent[0] == '-': Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Thu Jul 21 02:04:45 2005 @@ -24,6 +24,7 @@ """ +import math class r_int(int): """ fake integer implementation in order to make sure that @@ -190,6 +191,16 @@ def ovfcheck_lshift(a, b): return _local_ovfcheck(int(long(a) << b)) +FL_MAXINT = float(LONG_TEST-1) +FL_MININT = float(-LONG_TEST) + +def ovfcheck_float_to_int(x): + _, intp = math.modf(x) + if FL_MININT <= intp <= FL_MAXINT: + return int(intp) + raise OverflowError + + def _widen(self, other, value): """ if one argument is int or long, the other type wins. 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 Thu Jul 21 02:04:45 2005 @@ -235,3 +235,31 @@ pass else: assert False + +def test_ovfcheck_float_to_int(): + assert ovfcheck_float_to_int(1.0) == 1 + assert ovfcheck_float_to_int(0.0) == 0 + assert ovfcheck_float_to_int(13.0) == 13 + assert ovfcheck_float_to_int(-1.0) == -1 + assert ovfcheck_float_to_int(-13.0) == -13 + assert ovfcheck_float_to_int(float(sys.maxint-1)) == sys.maxint-1 + assert ovfcheck_float_to_int(float(sys.maxint)) == sys.maxint + assert ovfcheck_float_to_int(float(-sys.maxint)) == -sys.maxint + assert ovfcheck_float_to_int(float(-sys.maxint-1)) == -sys.maxint-1 + + try: + ovfcheck_float_to_int(float(-sys.maxint-1)-1) + except OverflowError: + pass + else: + assert False + + try: + ovfcheck_float_to_int(float(sys.maxint)+1) + except OverflowError: + pass + else: + assert False + + + From pedronis at codespeak.net Thu Jul 21 02:08:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 02:08:01 +0200 (CEST) Subject: [pypy-svn] r14840 - in pypy/dist/pypy: interpreter interpreter/pyparser translator Message-ID: <20050721000801.0762627B85@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 02:07:59 2005 New Revision: 14840 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/translator/ann_override.py Log: issue98: chatting stop-gap solution so that annotating the trunk at least terminates. To try that out set CHECK_DIGITS in longobject to False, then in translator/goal translate_pypy.py -no-t -no-c -no-o -no-snapshot will annotate the trunk Annotation terminates but there are quite a lof of SomeObject in interpreter/pyparser and module/recparser related code. Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Thu Jul 21 02:07:59 2005 @@ -178,21 +178,30 @@ the whole source after having only added a new '\n') """ def compile(self, source, filename, mode, flags): + assert isinstance(source, str) # xxx__builtin__.compile is cheating in the unicode case + # we need to do something about that + # CPython encode unicode for compilation into utf-8 + # and use a special internal flag to control behavior! + from pyparser.error import ParseError - from pyparser.pythonutil import pypy_parse + from pyparser.pythonutil import internal_pypy_parse flags |= __future__.generators.compiler_flag # always on (2.2 compat) # XXX use 'flags' space = self.space try: - tuples = pypy_parse(source, mode, True, flags) + parse_result = internal_pypy_parse(source, mode, True, flags) except ParseError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, filename)) - c = self.compile_tuples(tuples, filename, mode) - from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) + w_code = self.compile_parse_result(parse_result, filename, mode) + return w_code + + def compile_parse_result(self, parse_result, filename, mode): + """NOT_RPYTHON""" + from pyparser.pythonutil import parse_result_to_nested_tuples + # the result of this conversion has no useful type in RPython + tuples = parse_result_to_nested_tuples(parse_result, True) - def compile_tuples(self, tuples, filename, mode): # __________ # XXX this uses the non-annotatable stablecompiler at interp-level from pypy.interpreter import stablecompiler @@ -224,8 +233,9 @@ except TypeError,e: raise OperationError(space.w_TypeError,space.wrap(str(e))) # __________ end of XXX above - return c - compile_tuples._annspecialcase_ = 'override:cpy_stablecompiler' + from pypy.interpreter.pycode import PyCode + return space.wrap(PyCode(space)._from_code(c)) + compile_parse_result._annspecialcase_ = 'override:cpy_stablecompiler' class PyPyCompiler(CPythonCompiler): Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Thu Jul 21 02:07:59 2005 @@ -50,8 +50,26 @@ pyf.close() return pypy_parse(source, 'exec', lineno) +def internal_pypy_parse(source, mode='exec', lineno=False, flags=0): + builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) + target_rule = TARGET_DICT[mode] + PYTHON_PARSER.parse_source(source, target_rule, builder, flags) + stack_element = builder.stack[-1] + return (builder.source_encoding, stack_element) + +def parse_result_to_nested_tuples(parse_result, lineno=False): + """NOT_RPYTHON""" + source_encoding, stack_element = parse_result + nested_tuples = stack_element.as_tuple(lineno) + if source_encoding is not None: + return (symbol.encoding_decl, nested_tuples, source_encoding) + else: + return nested_tuples + def pypy_parse(source, mode='exec', lineno=False, flags=0): - """parse using PyPy's parser module and return + """ + NOT_RPYTHON ! + parse using PyPy's parser module and return a tuple of three elements : - The encoding declaration symbol or None if there were no encoding statement @@ -61,17 +79,10 @@ - The encoding string or None if there were no encoding statement nested tuples """ - builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - target_rule = TARGET_DICT[mode] - PYTHON_PARSER.parse_source(source, target_rule, builder, flags) - stack_element = builder.stack[-1] + source_encoding, stack_element = internal_pypy_parse(source, mode, lineno=lineno, flags=lineno) # convert the stack element into nested tuples (caution, the annotator # can't follow this call) - nested_tuples = stack_element.as_tuple(lineno) - if builder.source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, builder.source_encoding) - else: - return nested_tuples + return parse_result_to_nested_tuples((source_encoding, stack_element), lineno=lineno) ## convenience functions for computing AST objects using recparser def ast_from_input(input, mode, transformer): @@ -95,20 +106,12 @@ annotateme() is basically the same code that pypy_parse(), but with the following differences : - - directly take a list of strings rather than a filename in input - in order to avoid using file() (which is faked for now) - + - returns a tuplebuilder.StackElement instead of the *real* nested tuples (StackElement is only a wrapper class around these tuples) """ - builder = TupleBuilder(PYTHON_PARSER.rules, lineno=False) - PYTHON_PARSER.parse_source(source, 'file_input', builder) - nested_tuples = builder.stack[-1] - if builder.source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, builder.source_encoding) - else: - return (None, nested_tuples, None) + return internal_pypy_parse(source, 'exec') if __name__ == "__main__": Modified: pypy/dist/pypy/translator/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/ann_override.py (original) +++ pypy/dist/pypy/translator/ann_override.py Thu Jul 21 02:07:59 2005 @@ -22,3 +22,8 @@ from pypy.interpreter import pycode clsdef = getbookkeeper().getclassdef(pycode.PyCode) return annmodel.SomeInstance(clsdef) + + def override__cpy_stablecompiler(pol, self, parse_result, filename, mode): + from pypy.interpreter import pycode + clsdef = getbookkeeper().getclassdef(pycode.PyCode) + return annmodel.SomeInstance(clsdef) From ale at codespeak.net Thu Jul 21 03:12:23 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 21 Jul 2005 03:12:23 +0200 (CEST) Subject: [pypy-svn] r14841 - in pypy/dist/pypy: module/posix module/posix/test rpython rpython/module Message-ID: <20050721011223.400E527B7A@code1.codespeak.net> Author: ale Date: Thu Jul 21 03:12:19 2005 New Revision: 14841 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py Log: It seems that the only remaining thing to do is exceptionhandling Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Thu Jul 21 03:12:19 2005 @@ -3,8 +3,9 @@ class Module(MixedModule): appleveldefs = { - 'error' : 'app_posix.error' + 'error' : 'app_posix.error', } + interpleveldefs = { 'open' : 'interp_posix.open', 'lseek' : 'interp_posix.lseek', @@ -14,6 +15,8 @@ 'close' : 'interp_posix.close', 'ftruncate' : 'interp_posix.ftruncate', 'fstat' : 'interp_posix.fstat', + 'stat' : 'interp_posix.stat', 'dup' : 'interp_posix.dup', '__doc__' : "space.wrap('Posix module')", + '__name__' : "space.wrap('The builtin posix module')", } Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Thu Jul 21 03:12:19 2005 @@ -40,6 +40,10 @@ return os.fstat(fd) fstat.unwrap_spec = [ObjSpace, int] +def stat(space, path): + return os.stat(path) +stat.unwrap_spec = [ObjSpace, str] + def getcwd(space): return os.getcwd() getcwd.unwrap_spec = [ObjSpace] Modified: pypy/dist/pypy/module/posix/test/test_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix.py Thu Jul 21 03:12:19 2005 @@ -91,7 +91,7 @@ text = 'This is a test' os.write(fi,text) res = interpret(f,[fi]) - raises(OSError, os.fstat, fi) + raises( OSError, os.fstat, fi) def test_ftruncate(): def f(fi,len): Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 21 03:12:19 2005 @@ -3,8 +3,9 @@ """ import os import time +import math import types -from pypy.annotation.model import SomeInteger, SomeTuple +from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat class ExtFuncInfo: @@ -51,6 +52,7 @@ nonefactory = lambda *args: None tuplefactory = lambda *args: SomeTuple((SomeInteger(),)*10) +frexpfactory = lambda *args: SomeTuple((SomeFloat(),SomeInteger())) # external function declarations declare(os.open , int , 'll_os/open') @@ -63,6 +65,11 @@ declare(os.isatty , bool , 'll_os/isatty') declare(os.ftruncate, nonefactory, 'll_os/ftruncate') declare(os.fstat , tuplefactory, 'll_os/fstat') +declare(os.stat , tuplefactory, 'll_os/stat') declare(time.time , float , 'll_time/time') declare(time.clock , float , 'll_time/clock') declare(time.sleep , nonefactory, 'll_time/sleep') +declare(math.log10 , float , 'll_math/log10') +declare(math.ceil , float , 'll_math/ceil') +declare(math.frexp , frexpfactory, 'll_math/frexp') +declare(math.atan2 , float , 'll_math/atan2') 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 Thu Jul 21 03:12:19 2005 @@ -97,12 +97,9 @@ from pypy.rpython.rarithmetic import intmask -def ll_os_fstat(fd): - - stat = os.fstat(fd) - i = 0 - n = len(stat) - tup.item0 = stat[0] +def stat_to_rtuple(stat): + #n = len(stat) + tup.item0 = intmask(stat[0]) tup.item1 = intmask(stat[1]) tup.item2 = intmask(stat[2]) tup.item3 = intmask(stat[3]) @@ -112,9 +109,15 @@ tup.item7 = intmask(stat[7]) tup.item8 = intmask(stat[8]) tup.item9 = intmask(stat[9]) -## while i Author: ale Date: Thu Jul 21 03:59:11 2005 New Revision: 14844 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: Remember to convert to rstr 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 Thu Jul 21 03:59:11 2005 @@ -117,7 +117,7 @@ ll_os_fstat.suggested_primitive = True def ll_os_stat(path): - stat = os.fstat(path) + stat = os.stat(from_rstr(path)) stat_to_tuple(stat) return tup ll_os_stat.suggested_primitive = True \ No newline at end of file From pedronis at codespeak.net Thu Jul 21 04:01:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 04:01:34 +0200 (CEST) Subject: [pypy-svn] r14845 - pypy/dist/pypy/rpython Message-ID: <20050721020134.4B3F427B7A@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 04:01:32 2005 New Revision: 14845 Modified: pypy/dist/pypy/rpython/extfunctable.py Log: disable these for now, ll_math is missing, breaking lots of test! Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 21 04:01:32 2005 @@ -69,7 +69,7 @@ declare(time.time , float , 'll_time/time') declare(time.clock , float , 'll_time/clock') declare(time.sleep , nonefactory, 'll_time/sleep') -declare(math.log10 , float , 'll_math/log10') -declare(math.ceil , float , 'll_math/ceil') -declare(math.frexp , frexpfactory, 'll_math/frexp') -declare(math.atan2 , float , 'll_math/atan2') +#declare(math.log10 , float , 'll_math/log10') +#declare(math.ceil , float , 'll_math/ceil') +#declare(math.frexp , frexpfactory, 'll_math/frexp') +#declare(math.atan2 , float , 'll_math/atan2') From ludal at codespeak.net Thu Jul 21 12:37:33 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 12:37:33 +0200 (CEST) Subject: [pypy-svn] r14848 - in pypy/dist/pypy/interpreter: pyparser pyparser/test stablecompiler Message-ID: <20050721103733.5AE2627B6D@code1.codespeak.net> Author: ludal Date: Thu Jul 21 12:37:26 2005 New Revision: 14848 Added: pypy/dist/pypy/interpreter/pyparser/pysymbol.py pypy/dist/pypy/interpreter/pyparser/pytoken.py Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/ebnflexer.py pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/interpreter/pyparser/pytokenize.py pypy/dist/pypy/interpreter/pyparser/syntaxtree.py pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: - introduced interpreter.pyparser.pysymbol and interpreter.pyparser.pytoken which are pypy versions of the symbol and token modules of CPython - reworked all the parser so that we represent rules and tokens with their integer value instead of strings all tests passed but it might still break some things.. Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Thu Jul 21 12:37:26 2005 @@ -2,6 +2,8 @@ from grammar import BaseGrammarBuilder from pypy.interpreter.astcompiler import ast, consts +import pypy.interpreter.pyparser.pysymbol as sym +import pypy.interpreter.pyparser.pytoken as tok ## these tests should be methods of the ast objects @@ -66,15 +68,15 @@ L = get_atoms( builder, nb ) top = L[0] if isinstance(top, TokenObject): - if top.name == "(": + if top.name == tok.LPAR: builder. ast.Tuple(L[1:-1], top.line) - elif top.name == "[": + elif top.name == tok.LSQB: builder.push( ast.List( L[1:-1], top.line) ) - elif top.name == "{": + elif top.name == tok.LBRACE: builder.push( ast.Dict( L[1:-1], top.line) ) - elif top.name == "NAME": + elif top.name == tok.NAME: builder.push( ast.Name(top.value) ) - elif top.name == "NUMBER": + elif top.name == tok.NUMBER: builder.push( ast.Const(eval(top.value)) ) else: raise ValueError, "unexpected tokens (%d): %s" % (nb,[ str(i) for i in L] ) @@ -94,11 +96,11 @@ if len(L) == 1: builder.push( L[0] ) elif len(L) == 2 and isinstance(L[0],TokenObject): - if L[0].name == "+": + if L[0].name == tok.PLUS: builder.push( ast.UnaryAdd( L[1] ) ) - if L[0].name == "-": + if L[0].name == tok.MINUS: builder.push( ast.UnarySub( L[1] ) ) - if L[0].name == "~": + if L[0].name == tok.TILDE: builder.push( ast.Invert( L[1] ) ) def build_term( builder, nb ): @@ -108,13 +110,13 @@ for i in range(2,l,2): right = L[i] op = L[i-1].name - if op == "*": + if op == tok.STAR: left = ast.Mul( [ left, right ] ) - elif op == "/": + elif op == tok.SLASH: left = ast.Div( [ left, right ] ) - elif op == "%": + elif op == tok.PERCENT: left = ast.Mod( [ left, right ] ) - elif op == "//": + elif op == tok.DOUBLESLASH: left = ast.FloorDiv( [ left, right ] ) else: raise ValueError, "unexpected token: %s" % L[i-1] @@ -127,9 +129,9 @@ for i in range(2,l,2): right = L[i] op = L[i-1].name - if op == "+": + if op == tok.PLUS: left = ast.Add( [ left, right ] ) - elif op == "-": + elif op == tok.MINUS: left = ast.Sub( [ left, right ] ) else: raise ValueError, "unexpected token: %s : %s" % L[i-1] @@ -142,9 +144,9 @@ for i in range(2,l,2): right = L[i] op = L[i-1].name - if op == "<<": + if op == tok.LEFTSHIFT: left = ast.LeftShift( [ left, right ] ) - elif op == ">>": + elif op == tok.RIGHTSHIFT: left = ast.RightShift( [ left, right ] ) else: raise ValueError, "unexpected token: %s : %s" % L[i-1] @@ -204,7 +206,7 @@ builder.push( ast.Discard( L[0] ) ) return op = L[1] - if op.name == '=': + if op.name == tok.EQUAL: nodes = [] for i in range(0,l-2,2): lvalue = to_lvalue( L[i], consts.OP_ASSIGN ) @@ -246,23 +248,23 @@ ASTRULES = { # "single_input" : build_single_input, - "atom" : build_atom, - "power" : build_power, - "factor" : build_factor, - "term" : build_term, - "arith_expr" : build_arith_expr, - "shift_expr" : build_shift_expr, - "and_expr" : build_and_expr, - "xor_expr" : build_xor_expr, - "expr" : build_expr, - "comparison" : build_comparison, - "and_test" : build_and_test, - "test" : build_test, - "testlist" : build_testlist, - "expr_stmt" : build_expr_stmt, - "small_stmt" : return_one, - "simple_stmt" : build_simple_stmt, - "single_input" : build_single_input, + sym.atom : build_atom, + sym.power : build_power, + sym.factor : build_factor, + sym.term : build_term, + sym.arith_expr : build_arith_expr, + sym.shift_expr : build_shift_expr, + sym.and_expr : build_and_expr, + sym.xor_expr : build_xor_expr, + sym.expr : build_expr, + sym.comparison : build_comparison, + sym.and_test : build_and_test, + sym.test : build_test, + sym.testlist : build_testlist, + sym.expr_stmt : build_expr_stmt, + sym.small_stmt : return_one, + sym.simple_stmt : build_simple_stmt, + sym.single_input : build_single_input, } class RuleObject(ast.Node): @@ -312,26 +314,26 @@ def alternative( self, rule, source ): # Do nothing, keep rule on top of the stack if rule.is_root(): - print "ALT:",rule.name - F = ASTRULES.get(rule.name) + print "ALT:", sym.sym_name[rule.codename], rule.codename + F = ASTRULES.get(rule.codename) if F: F( self, 1 ) else: - self.push_rule( rule.name, 1, source ) + self.push_rule( rule.codename, 1, source ) return True def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - print "SEQ:", rule.name - F = ASTRULES.get(rule.name) + print "SEQ:", sym.sym_name[rule.codename], rule.codename + F = ASTRULES.get(rule.codename) if F: F( self, elts_number ) else: - self.push_rule( rule.name, elts_number, source ) + self.push_rule( rule.codename, elts_number, source ) return True def token(self, name, value, source): - print "TOK:", name, value + print "TOK:", tok.tok_name[name], name, value self.push_tok( name, value, source ) return True Modified: pypy/dist/pypy/interpreter/pyparser/ebnflexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnflexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnflexer.py Thu Jul 21 12:37:26 2005 @@ -22,11 +22,12 @@ SYMBOL: a rule symbol usually appeary right of a SYMDEF tokens: '[', ']', '(' ,')', '*', '+', '|' """ - def __init__(self, inpstring ): + def __init__(self, inpstring, tokenmap ): TokenSource.__init__(self) self.input = inpstring self.pos = 0 self._peeked = None + self.tokmap = tokenmap def context(self): """returns an opaque context object, used to backtrack @@ -52,6 +53,7 @@ # means backtracking more than one token # will re-tokenize the stream (but this is the # grammar lexer so we don't care really!) + T = self.tokmap if self._peeked is not None: peeked = self._peeked self._peeked = None @@ -64,28 +66,28 @@ pos = m.end() if pos==len(inp): self.pos = pos - return Token("EOF", None) + return Token(T["EOF"], None) m = g_skip.match(inp, pos) m = g_symdef.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return Token('SYMDEF',tk[:-1]) + return Token(T['SYMDEF'],tk[:-1]) m = g_tok.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return Token(tk,tk) + return Token(T[tk],tk) m = g_string.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return Token('STRING',tk[1:-1]) + return Token(T['STRING'],tk[1:-1]) m = g_symbol.match(inp,pos) if m: tk = m.group(0) self.pos = m.end() - return Token('SYMBOL',tk) + return Token(T['SYMBOL'],tk) raise ValueError("Unknown token at pos=%d context='%s'" % (pos,inp[pos:pos+20]) ) Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Thu Jul 21 12:37:26 2005 @@ -2,6 +2,8 @@ from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ KleenStar, GrammarElement, build_first_sets, EmptyToken from ebnflexer import GrammarSource +import pytoken +import pysymbol import re py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) @@ -32,7 +34,7 @@ class NameToken(Token): """A token that is not a keyword""" def __init__(self, keywords=None ): - Token.__init__(self, "NAME") + Token.__init__(self, pytoken.NAME) self.keywords = keywords def match(self, source, builder, level=0): @@ -48,10 +50,10 @@ """ ctx = source.context() tk = source.next() - if tk.name==self.name: + if tk.codename==self.codename: if tk.value not in self.keywords: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name, tk.value ) + ret = builder.token( tk.codename, tk.value, source ) + return self.debug_return( ret, tk.codename, tk.value ) source.restore( ctx ) return 0 @@ -62,7 +64,7 @@ raise RuntimeError("Unexpected token type %r" % other) if other is EmptyToken: return False - if other.name != self.name: + if other.codename != self.codename: return False if other.value in self.keywords: return False @@ -76,20 +78,40 @@ self.terminals = {} self.current_rule = None self.current_subrule = 0 - self.tokens = {} + self.keywords = [] self.items = [] self.terminals['NAME'] = NameToken() - def new_name(self): + def new_symbol(self): rule_name = ":%s_%s" % (self.current_rule, self.current_subrule) self.current_subrule += 1 - return rule_name + symval = pysymbol.add_anon_symbol( rule_name ) + return symval def new_item(self, itm): self.items.append(itm) return itm - - def visit_grammar(self, node): + + def visit_syntaxnode( self, node ): + """NOT RPYTHON, used only at bootstrap time anyway""" + name = sym_map[node.name] + visit_meth = getattr(self, "handle_%s" % name, None) + if visit_meth: + return visit_meth(node) + else: + print "Unknown handler for %s" %name + # helper function for nodes that have only one subnode: + if len(node.nodes) == 1: + return node.nodes[0].visit(visitor) + raise RuntimeError("Unknown Visitor for %r" % name) + + def visit_tokennode( self, node ): + return self.visit_syntaxnode( node ) + + def visit_tempsyntaxnode( self, node ): + return self.visit_syntaxnode( node ) + + def handle_grammar(self, node): for rule in node.nodes: rule.visit(self) # the rules are registered already @@ -97,33 +119,33 @@ # terminal symbols from non terminals for r in self.items: for i,a in enumerate(r.args): - if a.name in self.rules: + if a.codename in self.rules: assert isinstance(a,Token) - r.args[i] = self.rules[a.name] - if a.name in self.terminals: - del self.terminals[a.name] + r.args[i] = self.rules[a.codename] + if a.codename in self.terminals: + del self.terminals[a.codename] # XXX .keywords also contains punctuations - self.terminals['NAME'].keywords = self.tokens.keys() + self.terminals['NAME'].keywords = self.keywords - def visit_rule(self, node): + def handle_rule(self, node): symdef = node.nodes[0].value self.current_rule = symdef self.current_subrule = 0 alt = node.nodes[1] rule = alt.visit(self) if not isinstance(rule, Token): - rule.name = symdef - self.rules[symdef] = rule + rule.codename = pysymbol.add_symbol( symdef ) + self.rules[rule.codename] = rule - def visit_alternative(self, node): + def handle_alternative(self, node): items = [node.nodes[0].visit(self)] items += node.nodes[1].visit(self) - if len(items) == 1 and items[0].name.startswith(':'): + if len(items) == 1 and not items[0].is_root(): return items[0] - alt = Alternative(self.new_name(), items) + alt = Alternative(self.new_symbol(), items) return self.new_item(alt) - def visit_sequence( self, node ): + def handle_sequence( self, node ): """ """ items = [] for n in node.nodes: @@ -131,56 +153,64 @@ if len(items)==1: return items[0] elif len(items)>1: - return self.new_item( Sequence( self.new_name(), items) ) + return self.new_item( Sequence( self.new_symbol(), items) ) raise SyntaxError("Found empty sequence") - def visit_sequence_cont( self, node ): + def handle_sequence_cont( self, node ): """Returns a list of sequences (possibly empty)""" return [n.visit(self) for n in node.nodes] - def visit_seq_cont_list(self, node): + def handle_seq_cont_list(self, node): return node.nodes[1].visit(self) - def visit_symbol(self, node): + def handle_symbol(self, node): star_opt = node.nodes[1] sym = node.nodes[0].value terminal = self.terminals.get( sym ) if not terminal: - terminal = Token( sym ) - self.terminals[sym] = terminal + tokencode = pytoken.tok_values.get( sym ) + if tokencode is None: + tokencode = pysymbol.add_symbol( sym ) + terminal = Token( tokencode ) + else: + terminal = Token( tokencode ) + self.terminals[sym] = terminal return self.repeat( star_opt, terminal ) - def visit_option( self, node ): + def handle_option( self, node ): rule = node.nodes[1].visit(self) - return self.new_item( KleenStar( self.new_name(), 0, 1, rule ) ) + return self.new_item( KleenStar( self.new_symbol(), 0, 1, rule ) ) - def visit_group( self, node ): + def handle_group( self, node ): rule = node.nodes[1].visit(self) return self.repeat( node.nodes[3], rule ) - def visit_STRING( self, node ): + def handle_STRING( self, node ): value = node.value - tok = self.tokens.get(value) - if not tok: - if py_punct.match( value ): - tok = Token( value ) - elif py_name.match( value ): - tok = Token('NAME', value) - else: + tokencode = pytoken.tok_punct.get( value ) + if tokencode is None: + if not py_name.match( value ): raise SyntaxError("Unknown STRING value ('%s')" % value ) - self.tokens[value] = tok + # assume a keyword + tok = Token( pytoken.NAME, value ) + if value not in self.keywords: + self.keywords.append( value ) + else: + # punctuation + tok = Token( tokencode ) return tok - def visit_sequence_alt( self, node ): + def handle_sequence_alt( self, node ): res = node.nodes[0].visit(self) assert isinstance( res, GrammarElement ) return res def repeat( self, star_opt, myrule ): + assert isinstance( myrule, GrammarElement ) if star_opt.nodes: - rule_name = self.new_name() + rule_name = self.new_symbol() tok = star_opt.nodes[0].nodes[0] if tok.value == '+': item = KleenStar(rule_name, _min=1, rule=myrule) @@ -195,6 +225,22 @@ rules = None +sym_map = {} +sym_rmap = {} +sym_count = 0 + +def g_add_symbol( name ): + global sym_count + if name in sym_rmap: + return sym_rmap[name] + val = sym_count + sym_count += 1 + sym_map[val] = name + sym_rmap[name] = val + return val + +g_add_symbol( 'EOF' ) + def grammar_grammar(): """Builds the grammar for the grammar file @@ -209,36 +255,37 @@ option: '[' alternative ']' group: '(' alternative ')' star? """ - global rules + global rules, sym_map + S = g_add_symbol # star: '*' | '+' - star = Alternative( "star", [Token('*'), Token('+')] ) - star_opt = KleenStar ( "star_opt", 0, 1, rule=star ) + star = Alternative( S("star"), [Token(S('*')), Token(S('+'))] ) + star_opt = KleenStar ( S("star_opt"), 0, 1, rule=star ) # rule: SYMBOL ':' alternative - symbol = Sequence( "symbol", [Token('SYMBOL'), star_opt] ) - symboldef = Token( "SYMDEF" ) - alternative = Sequence( "alternative", []) - rule = Sequence( "rule", [symboldef, alternative] ) + symbol = Sequence( S("symbol"), [Token(S('SYMBOL')), star_opt] ) + symboldef = Token( S("SYMDEF") ) + alternative = Sequence( S("alternative"), []) + rule = Sequence( S("rule"), [symboldef, alternative] ) # grammar: rule+ - grammar = KleenStar( "grammar", _min=1, rule=rule ) + grammar = KleenStar( S("grammar"), _min=1, rule=rule ) # alternative: sequence ( '|' sequence )* - sequence = KleenStar( "sequence", 1 ) - seq_cont_list = Sequence( "seq_cont_list", [Token('|'), sequence] ) - sequence_cont = KleenStar( "sequence_cont",0, rule=seq_cont_list ) + sequence = KleenStar( S("sequence"), 1 ) + seq_cont_list = Sequence( S("seq_cont_list"), [Token(S('|')), sequence] ) + sequence_cont = KleenStar( S("sequence_cont"),0, rule=seq_cont_list ) alternative.args = [ sequence, sequence_cont ] # option: '[' alternative ']' - option = Sequence( "option", [Token('['), alternative, Token(']')] ) + option = Sequence( S("option"), [Token(S('[')), alternative, Token(S(']'))] ) # group: '(' alternative ')' - group = Sequence( "group", [Token('('), alternative, Token(')'), star_opt] ) + group = Sequence( S("group"), [Token(S('(')), alternative, Token(S(')')), star_opt] ) # sequence: (SYMBOL | STRING | option | group )+ - string = Token('STRING') - alt = Alternative( "sequence_alt", [symbol, string, option, group] ) + string = Token(S('STRING')) + alt = Alternative( S("sequence_alt"), [symbol, string, option, group] ) sequence.args = [ alt ] @@ -253,7 +300,7 @@ stream : file-like object representing the grammar to parse """ - source = GrammarSource(stream.read()) + source = GrammarSource(stream.read(), sym_rmap) rule = grammar_grammar() builder = BaseGrammarBuilder() result = rule.match(source, builder) Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 21 12:37:26 2005 @@ -11,6 +11,13 @@ DEBUG = 0 USE_LOOKAHEAD = True +def get_symbol( codename, symbols ): + """Helper function to build a token name""" + if codename in symbols: + return symbols[codename] + else: + return "["+str(codename)+"]" + #### Abstract interface for a lexer/tokenizer class TokenSource(object): """Abstract base class for a source tokenizer""" @@ -74,16 +81,22 @@ from syntaxtree import SyntaxNode, TempSyntaxNode, TokenNode - +# +# we use the term root for a grammar rule to specify rules that are given a name +# by the grammar +# a rule like S -> A B* is mapped as Sequence( SCODE, KleenStar(-3, B)) +# so S is a root and the subrule describing B* is not. +# SCODE is the numerical value for rule "S" class BaseGrammarBuilder(object): """Base/default class for a builder""" - def __init__(self, rules=None, debug=0): + def __init__(self, rules=None, debug=0, symbols={} ): # a dictionary of grammar rules for debug/reference self.rules = rules or {} # This attribute is here for convenience self.source_encoding = None self.debug = debug self.stack = [] + self.symbols = symbols # mapping from codename to symbols def context(self): """Returns the state of the builder to be restored later""" @@ -98,7 +111,7 @@ # Do nothing, keep rule on top of the stack if rule.is_root(): elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.name, source, elems) + self.stack[-1] = SyntaxNode(rule.codename, source, elems) if self.debug: self.stack[-1].dumpstr() return True @@ -114,11 +127,11 @@ node_type = TempSyntaxNode # replace N elements with 1 element regrouping them if elts_number >= 1: - elem = node_type(rule.name, source, items) + elem = node_type(rule.codename, source, items) del self.stack[-elts_number:] self.stack.append(elem) elif elts_number == 0: - self.stack.append(node_type(rule.name, source, [])) + self.stack.append(node_type(rule.codename, source, [])) if self.debug: self.stack[-1].dumpstr() return True @@ -135,11 +148,14 @@ ###################################################################### class GrammarElement(object): """Base parser class""" - def __init__(self, name): + + symbols = {} # dirty trick to provide a symbols mapping while printing (and not putting it in every object) + + def __init__(self, codename): # the rule name - self.name = name + #assert type(codename)==int + self.codename = codename # integer mapping to either a token value or rule symbol value self.args = [] - self._is_root = False self.first_set = [] self.first_set_complete = False # self._processing = False @@ -148,9 +164,10 @@ def is_root(self): """This is a root node of the grammar, that is one that will be included in the syntax tree""" - if self.name != ":" and self.name.startswith(":"): - return False - return True + # code attributed to root grammar rules are >=0 + if self.codename >=0: + return True + return False def match(self, source, builder, level=0): @@ -177,13 +194,13 @@ if EmptyToken in self.first_set: ret = builder.sequence(self, source, 0 ) if self._trace: - self._debug_display(token, level, 'eee') - return self.debug_return( ret, 0 ) + self._debug_display(token, level, 'eee', builder.symbols) + return self.debug_return( ret, builder.symbols, 0 ) if self._trace: - self._debug_display(token, level, 'rrr') + self._debug_display(token, level, 'rrr', builder.symbols) return 0 elif self._trace: - self._debug_display(token, level, '>>>') + self._debug_display(token, level, '>>>', builder.symbols) res = self._match(source, builder, level) if self._trace: @@ -192,14 +209,14 @@ prefix = '+++' else: prefix = '---' - self._debug_display(token, level, prefix) + self._debug_display(token, level, prefix, builder.symbols) print ' '*level, prefix, " TEXT ='%s'" % ( source.get_source_text(pos1,pos2)) if res: print "*" * 50 return res - def _debug_display(self, token, level, prefix): + def _debug_display(self, token, level, prefix, symbols): """prints context debug informations""" prefix = '%s%s' % (' ' * level, prefix) print prefix, " RULE =", self @@ -229,24 +246,24 @@ pass def __str__(self): - return self.display(0) + return self.display(0, GrammarElement.symbols ) def __repr__(self): - return self.display(0) + return self.display(0, GrammarElement.symbols ) - def display(self, level): + def display(self, level=0, symbols={}): """Helper function used to represent the grammar. mostly used for debugging the grammar itself""" return "GrammarElement" - def debug_return(self, ret, *args ): + def debug_return(self, ret, symbols, *args ): # FIXME: use a wrapper of match() methods instead of debug_return() # to prevent additional indirection if ret and DEBUG > 0: sargs = ",".join( [ str(i) for i in args ] ) print "matched %s (%s): %s" % (self.__class__.__name__, - sargs, self.display() ) + sargs, self.display(0, symbols=symbols) ) return ret @@ -284,12 +301,12 @@ for i in self.args: assert isinstance( i, GrammarElement ) - def _match(self, source, builder, level=0): + def _match(self, source, builder, level=0 ): """If any of the rules in self.args matches returns the object built from the first rules that matches """ if DEBUG > 1: - print "try alt:", self.display() + print "try alt:", self.display(level, builder.symbols ) tok = source.peek() # Here we stop at the first match we should # try instead to get the longest alternative @@ -303,17 +320,18 @@ m = rule.match(source, builder, level+1) if m: ret = builder.alternative( self, source ) - return self.debug_return( ret ) + return self.debug_return( ret, builder.symbols ) return 0 - def display(self, level=0): + def display(self, level=0, symbols={}): + name = get_symbol( self.codename, symbols ) if level == 0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name + name = name + " -> " + elif self.is_root(): + return name else: name = "" - items = [ a.display(1) for a in self.args ] + items = [ a.display(1,symbols) for a in self.args ] return name+"(" + "|".join( items ) + ")" def calc_first_set(self): @@ -370,7 +388,7 @@ def _match(self, source, builder, level=0): """matches all of the symbols in order""" if DEBUG > 1: - print "try seq:", self.display() + print "try seq:", self.display(level, builder.symbols ) ctx = source.context() bctx = builder.context() for rule in self.args: @@ -382,13 +400,14 @@ builder.restore(bctx) return 0 ret = builder.sequence(self, source, len(self.args)) - return self.debug_return( ret ) + return self.debug_return( ret, builder.symbols ) - def display(self, level=0): + def display(self, level=0, symbols={}): + name = get_symbol( self.codename, symbols ) if level == 0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name + name = name + " -> " + elif self.is_root(): + return name else: name = "" items = [a.display(1) for a in self.args] @@ -454,17 +473,18 @@ builder.restore(bctx) return 0 ret = builder.sequence(self, source, rules) - return self.debug_return( ret, rules ) + return self.debug_return( ret, builder.symbols, rules ) rules += 1 if self.max>0 and rules == self.max: ret = builder.sequence(self, source, rules) - return self.debug_return( ret, rules ) + return self.debug_return( ret, builder.symbols, rules ) - def display(self, level=0): + def display(self, level=0, symbols={}): + name = get_symbol( self.codename, symbols ) if level==0: - name = self.name + " -> " - elif not self.name.startswith(":"): - return self.name + name = name + " -> " + elif self.is_root(): + return name else: name = "" star = "{%d,%d}" % (self.min,self.max) @@ -494,8 +514,8 @@ class Token(GrammarElement): """Represents a Token in a grammar rule (a lexer token)""" - def __init__( self, name, value = None): - GrammarElement.__init__( self, name ) + def __init__( self, codename, value = None): + GrammarElement.__init__( self, codename ) self.value = value self.first_set = [self] # self.first_set = {self: 1} @@ -513,23 +533,24 @@ """ ctx = source.context() tk = source.next() - if tk.name == self.name: + if tk.codename == self.codename: if self.value is None: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name ) + ret = builder.token( tk.codename, tk.value, source ) + return self.debug_return( ret, builder.symbols, tk.codename ) elif self.value == tk.value: - ret = builder.token( tk.name, tk.value, source ) - return self.debug_return( ret, tk.name, tk.value ) + ret = builder.token( tk.codename, tk.value, source ) + return self.debug_return( ret, builder.symbols, tk.codename, tk.value ) if DEBUG > 1: print "tried tok:", self.display() source.restore( ctx ) return 0 - def display(self, level=0): + def display(self, level=0, symbols={}): + name = get_symbol( self.codename, symbols ) if self.value is None: - return "<%s>" % self.name + return "<%s>" % name else: - return "<%s>=='%s'" % (self.name, self.value) + return "<%s>=='%s'" % (name, self.value) def match_token(self, other): @@ -544,12 +565,12 @@ raise RuntimeError("Unexpected token type %r" % other) if other is EmptyToken: return False - res = other.name == self.name and self.value in (None, other.value) + res = other.codename == self.codename and self.value in (None, other.value) #print "matching", self, other, res return res def __eq__(self, other): - return self.name == other.name and self.value == other.value + return self.codename == other.codename and self.value == other.value @@ -558,4 +579,5 @@ """ pass -EmptyToken = Token(None) +from pypy.interpreter.pyparser.pytoken import NULLTOKEN +EmptyToken = Token(NULLTOKEN, None) Added: pypy/dist/pypy/interpreter/pyparser/pysymbol.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/pysymbol.py Thu Jul 21 12:37:26 2005 @@ -0,0 +1,48 @@ +# replacement for the CPython symbol module +from pytoken import N_TOKENS + +# try to avoid numeric values conflict with tokens +# it's important for CPython, but I'm not so sure it's still +# important here +SYMBOL_START = N_TOKENS+30 +del N_TOKENS + +_count = SYMBOL_START +_anoncount = -10 + +sym_name = {} +sym_values = {} + +def add_symbol( sym ): + global _count + assert type(sym)==str + if not sym_values.has_key( sym ): + val = _count + sym_values[sym] = val + sym_name[val] = sym + globals()[sym] = val + _count += 1 + return val + return sym_values[ sym ] + +def add_anon_symbol( sym ): + global _anoncount + assert type(sym)==str + if not sym_values.has_key( sym ): + val = _anoncount + sym_values[sym] = val + sym_name[val] = sym + _anoncount -= 1 + return val + return sym_values[ sym ] + + +def update_symbols( parser ): + """Update the symbol module according to rules + in PythonParser instance : parser""" + for rule in parser.rules: + add_symbol( rule ) + +# There is no symbol in this module until the grammar is loaded +# once loaded the grammar parser will fill the mappings with the +# grammar symbols Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Thu Jul 21 12:37:26 2005 @@ -7,6 +7,9 @@ from pypy.interpreter.pyparser.grammar import TokenSource, Token from pypy.interpreter.pyparser.error import ParseError +import pytoken +from pytoken import NEWLINE + # Don't import string for that ... NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' NUMCHARS = '0123456789' @@ -64,14 +67,11 @@ return encoding ################################################################################ -import token as tokenmod +from pypy.interpreter.pyparser import pytoken from pytokenize import tabsize, whiteSpaceDFA, triple_quoted, endDFAs, \ single_quoted, pseudoDFA import automata -# adopt pytokenize notations / values -tokenmod.COMMENT = tokenmod.N_TOKENS -tokenmod.NL = tokenmod.N_TOKENS + 1 class TokenError(ParseError): """Raised for lexer errors, e.g. when EOF is found prematurely""" @@ -128,7 +128,7 @@ endmatch = endDFA.recognize(line) if -1 != endmatch: pos = end = endmatch - tok = token_from_values(tokenmod.STRING, contstr + line[:end]) + tok = Token(pytoken.STRING, contstr + line[:end]) token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((STRING, contstr + line[:end], @@ -136,7 +136,7 @@ contstr, needcont = '', 0 contline = None elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': - tok = token_from_values(tokenmod.ERRORTOKEN, contstr + line) + tok = Token(pytoken.ERRORTOKEN, contstr + line) token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((ERRORTOKEN, contstr + line, @@ -162,14 +162,14 @@ if line[pos] in '#\r\n': # skip comments or blank lines if line[pos] == '#': - tok = token_from_values(tokenmod.COMMENT, line[pos:]) + tok = Token(pytoken.COMMENT, line[pos:]) last_comment = line[pos:] if lnum <= 2 and encoding is None: encoding = match_encoding_declaration(last_comment) if encoding is not None: encoding = _normalize_encoding(encoding) else: - tok = token_from_values(tokenmod.NL, line[pos:]) + tok = Token(pytoken.NL, line[pos:]) last_comment = '' # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line, lnum, pos)) @@ -177,12 +177,12 @@ if column > indents[-1]: # count indents or dedents indents.append(column) - tok = token_from_values(tokenmod.INDENT, line[:pos]) + tok = Token(pytoken.INDENT, line[:pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' while column < indents[-1]: indents = indents[:-1] - tok = token_from_values(tokenmod.DEDENT, '') + tok = Token(pytoken.DEDENT, '') token_list.append((tok, line, lnum, pos)) last_comment = '' else: # continued statement @@ -209,22 +209,22 @@ token, initial = line[start:end], line[start] if initial in numchars or \ (initial == '.' and token != '.'): # ordinary number - tok = token_from_values(tokenmod.NUMBER, token) + tok = Token(pytoken.NUMBER, token) token_list.append((tok, line, lnum, pos)) last_comment = '' elif initial in '\r\n': if parenlev > 0: - tok = token_from_values(tokenmod.NL, token) + tok = Token(pytoken.NL, token) last_comment = '' # XXX Skip NL else: - tok = token_from_values(tokenmod.NEWLINE, token) + tok = Token(pytoken.NEWLINE, token) # XXX YUCK ! tok.value = last_comment token_list.append((tok, line, lnum, pos)) last_comment = '' elif initial == '#': - tok = token_from_values(tokenmod.COMMENT, token) + tok = Token(pytoken.COMMENT, token) last_comment = token if lnum <= 2 and encoding is None: encoding = match_encoding_declaration(last_comment) @@ -238,7 +238,7 @@ if -1 != endmatch: # all on one line pos = endmatch token = line[start:pos] - tok = token_from_values(tokenmod.STRING, token) + tok = Token(pytoken.STRING, token) token_list.append((tok, line, lnum, pos)) last_comment = '' else: @@ -255,12 +255,12 @@ contline = line break else: # ordinary string - tok = token_from_values(tokenmod.STRING, token) + tok = Token(pytoken.STRING, token) token_list.append((tok, line, lnum, pos)) last_comment = '' # token_list.append((STRING, token, spos, epos, line)) elif initial in namechars: # ordinary name - tok = token_from_values(tokenmod.NAME, token) + tok = Token(pytoken.NAME, token) token_list.append((tok, line, lnum, pos)) last_comment = '' elif initial == '\\': # continued stmt @@ -270,26 +270,29 @@ parenlev = parenlev + 1 elif initial in ')]}': parenlev = parenlev - 1 - tok = token_from_values(tokenmod.OP, token) + if token in pytoken.tok_punct: + tok = Token(pytoken.tok_punct[token]) + else: + tok = Token(pytoken.OP, token) token_list.append((tok, line, lnum, pos)) last_comment = '' else: - tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) + tok = Token(pytoken.ERRORTOKEN, line[pos]) token_list.append((tok, line, lnum, pos)) last_comment = '' pos = pos + 1 lnum -= 1 if not (flags & PyCF_DONT_IMPLY_DEDENT): - if token_list and token_list[-1][0].name != 'NEWLINE': - token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + if token_list and token_list[-1][0].codename != pytoken.NEWLINE: + token_list.append((Token(pytoken.NEWLINE, ''), '\n', lnum, 0)) for indent in indents[1:]: # pop remaining indent levels - tok = token_from_values(tokenmod.DEDENT, '') + tok = Token(pytoken.DEDENT, '') token_list.append((tok, line, lnum, pos)) - if token_list and token_list[-1][0].name != 'NEWLINE': - token_list.append((Token('NEWLINE', ''), '\n', lnum, 0)) + if token_list and token_list[-1][0].codename != pytoken.NEWLINE: + token_list.append((Token(pytoken.NEWLINE, ''), '\n', lnum, 0)) - tok = token_from_values(tokenmod.ENDMARKER, '',) + tok = Token(pytoken.ENDMARKER, '',) token_list.append((tok, line, lnum, pos)) return token_list, encoding @@ -362,18 +365,8 @@ return (self._current_line, self._lineno) # return 'line %s : %s' % ('XXX', self._current_line) -NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT] -NAMED_LIST = [tokenmod.OP] - -def token_from_values(tok_type, tok_string): - """Compatibility layer between both parsers""" - if tok_type in NONE_LIST: - return Token(tokenmod.tok_name[tok_type], None) - if tok_type in NAMED_LIST: - return Token(tok_string, None) - if tok_type == tokenmod.NEWLINE: - return Token('NEWLINE', '') # XXX pending comment ? - return Token(tokenmod.tok_name[tok_type], tok_string) +NONE_LIST = [pytoken.ENDMARKER, pytoken.INDENT, pytoken.DEDENT] +NAMED_LIST = [pytoken.OP] Source = PythonSource Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Thu Jul 21 12:37:26 2005 @@ -8,13 +8,13 @@ from pypy.interpreter.error import OperationError, debug_print from pypy.interpreter.pyparser.error import ParseError from pypy.tool.option import Options - from pythonlexer import Source +import pysymbol import ebnfparse import sys import os import grammar -import symbol + from codeop import PyCF_DONT_IMPLY_DEDENT class PythonParser(object): @@ -37,7 +37,8 @@ return self.parse_lines(lines, goal, builder, flags) def parse_lines(self, lines, goal, builder=None, flags=0): - target = self.rules[goal] + goalnumber = pysymbol.sym_values[goal] + target = self.rules[goalnumber] src = Source(lines, flags) if builder is None: @@ -71,44 +72,18 @@ grammar.DEBUG = 0 gram = ebnfparse.parse_grammar( file(fname) ) grammar.DEBUG = level - return PythonParser(gram) + parser = PythonParser( gram ) + return parser debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) -_symbols = symbol.sym_name.keys() -_symbols.sort() - -def add_symbol( sym ): - if not hasattr(symbol, sym): - nextval = _symbols[-1] + 1 - setattr(symbol, sym, nextval) - _symbols.append(nextval) - symbol.sym_name[nextval] = sym - return nextval - return 0 -def reload_grammar( version ): +def reload_grammar(version): """helper function to test with pypy different grammars""" global PYTHON_GRAMMAR, PYTHON_PARSER, PYPY_VERSION PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( version ) debug_print( "Reloading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) - for rule in PYTHON_PARSER.rules: - add_symbol( rule ) - - -for rule in PYTHON_PARSER.rules: - add_symbol( rule ) - - -SYMBOLS = {} -# copies the numerical mapping between symbol name and symbol value -# into SYMBOLS -for k, v in symbol.sym_name.items(): - SYMBOLS[v] = k -SYMBOLS['UNKNOWN'] = -1 - - def parse_file_input(pyf, gram, builder=None): """Parse a python file""" Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Thu Jul 21 12:37:26 2005 @@ -1,11 +1,11 @@ __all__ = ["python_parse", "pypy_parse"] import parser -import symbol import pythonparse from tuplebuilder import TupleBuilder from pypy.interpreter.pyparser.error import ParseError +from pypy.interpreter.pyparser import pysymbol PYTHON_PARSER = pythonparse.PYTHON_PARSER TARGET_DICT = { @@ -62,7 +62,7 @@ source_encoding, stack_element = parse_result nested_tuples = stack_element.as_tuple(lineno) if source_encoding is not None: - return (symbol.encoding_decl, nested_tuples, source_encoding) + return (pysymbol.encoding_decl, nested_tuples, source_encoding) else: return nested_tuples Added: pypy/dist/pypy/interpreter/pyparser/pytoken.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/pytoken.py Thu Jul 21 12:37:26 2005 @@ -0,0 +1,88 @@ +# A replacement for the token module +# +# adds a new map token_values to avoid doing getattr on the module +# from PyPy RPython + +import token + +N_TOKENS = token.N_TOKENS + +tok_name = {} +tok_values = {} + +def add_token(name, value=None): + global N_TOKENS + if value is None: + value = N_TOKENS + N_TOKENS += 1 + _g = globals() + _g[name] = value + tok_name[value] = name + tok_values[name] = value + +# This is used to replace None +add_token( 'NULLTOKEN', -1 ) + +for value, name in token.tok_name.items(): + add_token( name, value ) + +# Make sure '@' is in the token list +if "AT" not in tok_values: + add_token( "AT" ) + +add_token( "COMMENT" ) +add_token( "NL" ) + +# a reverse mapping from internal tokens def to more pythonic tokens +tok_punct = { + "&" : AMPER, + "&=" : AMPEREQUAL, + "`" : BACKQUOTE, + "^" : CIRCUMFLEX, + "^=" : CIRCUMFLEXEQUAL, + ":" : COLON, + "," : COMMA, + "." : DOT, + "//" : DOUBLESLASH, + "//=" : DOUBLESLASHEQUAL, + "**" : DOUBLESTAR, + "**=" : DOUBLESTAREQUAL, + "==" : EQEQUAL, + "=" : EQUAL, + ">" : GREATER, + ">=" : GREATEREQUAL, + "{" : LBRACE, + "}" : RBRACE, + "<<" : LEFTSHIFT, + "<<=" : LEFTSHIFTEQUAL, + "<" : LESS, + "<=" : LESSEQUAL, + "(" : LPAR, + "[" : LSQB, + "-=" : MINEQUAL, + "-" : MINUS, + "!=" : NOTEQUAL, + "<>" : NOTEQUAL, + "%" : PERCENT, + "%=" : PERCENTEQUAL, + "+" : PLUS, + "+=" : PLUSEQUAL, + ")" : RBRACE, + ">>" : RIGHTSHIFT, + ">>=" : RIGHTSHIFTEQUAL, + ")" : RPAR, + "]" : RSQB, + ";" : SEMI, + "/" : SLASH, + "/=" : SLASHEQUAL, + "*" : STAR, + "*=" : STAREQUAL, + "~" : TILDE, + "|" : VBAR, + "|=" : VBAREQUAL, + "@": AT, + } +tok_rpunct = {} +for string, value in tok_punct.items(): + tok_rpunct[value] = string + Modified: pypy/dist/pypy/interpreter/pyparser/pytokenize.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pytokenize.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pytokenize.py Thu Jul 21 12:37:26 2005 @@ -20,21 +20,7 @@ from __future__ import generators from pypy.interpreter.pyparser import automata -# ______________________________________________________________________ -# COPIED: -import token -__all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", - "generate_tokens", "NL"] -del x -N_TOKENS = token.N_TOKENS -tok_name = token.tok_name -del token - -COMMENT = N_TOKENS -tok_name[COMMENT] = 'COMMENT' -NL = N_TOKENS + 1 -tok_name[NL] = 'NL' -N_TOKENS += 2 +__all__ = [ "tokenize", "generate_tokens", ] # ______________________________________________________________________ # Automatically generated DFA's (with one or two hand tweeks): Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Thu Jul 21 12:37:26 2005 @@ -1,74 +1,6 @@ """SyntaxTree class definition""" -import symbol -import token - -# XXX hack: make sure '@' is in the token list -if not hasattr(token, 'AT'): - token.AT = token.N_TOKENS + 2 # see pythonlexer.py for why '+2' - token.tok_name[token.AT] = 'AT' - -TOKEN_MAP = { - "STRING" : token.STRING, - "NUMBER" : token.NUMBER, - "NAME" : token.NAME, - "NEWLINE" : token.NEWLINE, - "DEDENT" : token.DEDENT, - "ENDMARKER" : token.ENDMARKER, - "INDENT" : token.INDENT, - "NEWLINE" : token.NEWLINE, - "NT_OFFSET" : token.NT_OFFSET, - "N_TOKENS" : token.N_TOKENS, - "OP" : token.OP, - "?ERRORTOKEN" : token.ERRORTOKEN, - "&" : token.AMPER, - "&=" : token.AMPEREQUAL, - "`" : token.BACKQUOTE, - "^" : token.CIRCUMFLEX, - "^=" : token.CIRCUMFLEXEQUAL, - ":" : token.COLON, - "," : token.COMMA, - "." : token.DOT, - "//" : token.DOUBLESLASH, - "//=" : token.DOUBLESLASHEQUAL, - "**" : token.DOUBLESTAR, - "**=" : token.DOUBLESTAREQUAL, - "==" : token.EQEQUAL, - "=" : token.EQUAL, - ">" : token.GREATER, - ">=" : token.GREATEREQUAL, - "{" : token.LBRACE, - "}" : token.RBRACE, - "<<" : token.LEFTSHIFT, - "<<=" : token.LEFTSHIFTEQUAL, - "<" : token.LESS, - "<=" : token.LESSEQUAL, - "(" : token.LPAR, - "[" : token.LSQB, - "-=" : token.MINEQUAL, - "-" : token.MINUS, - "!=" : token.NOTEQUAL, - "<>" : token.NOTEQUAL, - "%" : token.PERCENT, - "%=" : token.PERCENTEQUAL, - "+" : token.PLUS, - "+=" : token.PLUSEQUAL, - ")" : token.RBRACE, - ">>" : token.RIGHTSHIFT, - ">>=" : token.RIGHTSHIFTEQUAL, - ")" : token.RPAR, - "]" : token.RSQB, - ";" : token.SEMI, - "/" : token.SLASH, - "/=" : token.SLASHEQUAL, - "*" : token.STAR, - "*=" : token.STAREQUAL, - "~" : token.TILDE, - "|" : token.VBAR, - "|=" : token.VBAREQUAL, - "@": token.AT, - } -NT_OFFSET = token.NT_OFFSET - +from pypy.interpreter.pyparser.pysymbol import sym_values +from pypy.interpreter.pyparser.pytoken import tok_values class SyntaxNode(object): @@ -103,17 +35,10 @@ return "" % (self.name, id(self)) def __str__(self): - return "(%s)" % self.name + return "(%s)" % self.name def visit(self, visitor): - """NOT RPYTHON, used only at bootstrap time anyway""" - visit_meth = getattr(visitor, "visit_%s" % self.name, None) - if visit_meth: - return visit_meth(self) - # helper function for nodes that have only one subnode: - if len(self.nodes) == 1: - return self.nodes[0].visit(visitor) - raise RuntimeError("Unknown Visitor for %r" % self.name) + return visitor.visit_syntaxnode(self) def expand(self): """expand the syntax node to its content, @@ -123,7 +48,7 @@ def totuple(self, lineno=False ): """returns a tuple representation of the syntax tree""" - symvalue = SYMBOLS.get( self.name, (0, self.name) ) + symvalue = sym_values.get( self.name, (0, self.name) ) l = [ symvalue ] l += [node.totuple(lineno) for node in self.nodes] return tuple(l) @@ -135,6 +60,9 @@ """expand the syntax node to its content""" return self.nodes + def visit(self, visitor): + return visitor.visit_tempsyntaxnode(self) + class TokenNode(SyntaxNode): """A token node""" def __init__(self, name, source, value): @@ -155,9 +83,12 @@ else: return "<%s!>" % (self.name,) + def visit(self, visitor): + return visitor.visit_tokennode(self) + def totuple(self, lineno=False): """returns a tuple representation of the syntax tree""" - num = TOKEN_MAP.get(self.name, -1) + num = tok_values.get(self.name, -1) if num == -1: print "Unknown", self.name, self.value if self.value is not None: Modified: pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py Thu Jul 21 12:37:26 2005 @@ -4,33 +4,38 @@ class TestLookAheadBasics: def setup_method(self, method): - self.tok1 = Token('t1', 'foo') - self.tok2 = Token('t2', 'bar') - self.tok3 = Token('t3', 'foobar') + self.count = 0 + self.tok1 = Token(self.nextid(), 'foo') + self.tok2 = Token(self.nextid(), 'bar') + self.tok3 = Token(self.nextid(), 'foobar') self.tokens = [self.tok1, self.tok2, self.tok3] build_first_sets(self.tokens) + def nextid(self): + self.count+=1 + return self.count + def test_basic_token(self): assert self.tok1.first_set == [self.tok1] def test_basic_alternative(self): - alt = Alternative('alt', self.tokens) + alt = Alternative(self.nextid(), self.tokens) build_first_sets([alt]) assert alt.first_set == self.tokens def test_basic_sequence(self): - seq = Sequence('seq', self.tokens) + seq = Sequence(self.nextid(), self.tokens) build_first_sets([seq]) assert seq.first_set == [self.tokens[0]] def test_basic_kleenstar(self): tok1, tok2, tok3 = self.tokens - kstar = KleenStar('kstar', 1, 3, tok1) + kstar = KleenStar(self.nextid(), 1, 3, tok1) build_first_sets([kstar]) assert kstar.first_set == [tok1] - kstar = KleenStar('kstar', 0, 3, tok1) + kstar = KleenStar(self.nextid(), 0, 3, tok1) build_first_sets([kstar]) assert kstar.first_set == [tok1, EmptyToken] @@ -40,9 +45,9 @@ ==> S.first_set = [tok1, tok2, EmptyToken] """ tok1, tok2, tok3 = self.tokens - k1 = KleenStar('k1', 0, 2, tok1) - k2 = KleenStar('k1', 0, 2, tok2) - seq = Sequence('seq', [k1, k2]) + k1 = KleenStar(self.nextid(), 0, 2, tok1) + k2 = KleenStar(self.nextid(), 0, 2, tok2) + seq = Sequence(self.nextid(), [k1, k2]) build_first_sets([k1, k2, seq]) assert seq.first_set == [tok1, tok2, EmptyToken] @@ -52,33 +57,41 @@ ==> S.first_set = [tok1, tok2] """ tok1, tok2, tok3 = self.tokens - k1 = KleenStar('k1', 0, 2, tok1) - k2 = KleenStar('k1', 1, 2, tok2) - seq = Sequence('seq', [k1, k2]) + k1 = KleenStar(self.nextid(), 0, 2, tok1) + k2 = KleenStar(self.nextid(), 1, 2, tok2) + seq = Sequence(self.nextid(), [k1, k2]) build_first_sets([k1, k2, seq]) assert seq.first_set == [tok1, tok2] def test_token_comparison(): - assert Token('t1', 'foo') == Token('t1', 'foo') - assert Token('t1', 'foo') != Token('t2', 'foo') - assert Token('t2', 'foo') != Token('t1', None) + assert Token(1, 'foo') == Token(1, 'foo') + assert Token(1, 'foo') != Token(2, 'foo') + assert Token(2, 'foo') != Token(2, None) + +LOW = 1 +CAP = 2 +R_A = 3 +R_B = 4 +R_C = 5 +R_k1 = 6 +R_k2 = 7 class TestLookAhead: def setup_method(self, method): - self.LOW = Token('LOW', 'low') - self.CAP = Token('CAP' ,'cap') - self.A = Alternative('A', []) - k1 = KleenStar('k1', 0, rule=self.LOW) - k2 = KleenStar('k2', 0, rule=self.CAP) - self.B = Sequence('B', [k1, self.A]) - self.C = Sequence('C', [k2, self.A]) + self.LOW = Token(LOW, 'low') + self.CAP = Token(CAP ,'cap') + self.A = Alternative(R_A, []) + k1 = KleenStar(R_k1, 0, rule=self.LOW) + k2 = KleenStar(R_k2, 0, rule=self.CAP) + self.B = Sequence(R_B, [k1, self.A]) + self.C = Sequence(R_C, [k2, self.A]) self.A.args = [self.B, self.C] build_first_sets([self.A, self.B, self.C, self.LOW, self.CAP, k1, k2]) def test_S_first_set(self): - for s in [Token('LOW', 'low'), EmptyToken, Token('CAP', 'cap')]: + for s in [Token(LOW, 'low'), EmptyToken, Token(CAP, 'cap')]: assert s in self.A.first_set assert s in self.B.first_set assert s in self.C.first_set Modified: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Thu Jul 21 12:37:26 2005 @@ -1,15 +1,19 @@ from pypy.interpreter.pyparser.pythonlexer import Source, TokenError, \ match_encoding_declaration -from pypy.interpreter.pyparser.grammar import Token +from pypy.interpreter.pyparser.grammar import Token, GrammarElement +from pypy.interpreter.pyparser.pytoken import EQUAL, ENDMARKER, LSQB, MINUS, NAME, NEWLINE, NULLTOKEN, NUMBER, RSQB, STRING + +from pypy.interpreter.pyparser.pytoken import tok_name, tok_punct +GrammarElement.symbols = tok_name + def parse_source(source): """returns list of parsed tokens""" lexer = Source(source.splitlines(True)) tokens = [] - last_token = Token(None, None) - while last_token.name != 'ENDMARKER': + last_token = Token(NULLTOKEN, None) + while last_token.codename != ENDMARKER: last_token = lexer.next() - # tokens.append((last_token, value)) tokens.append(last_token) return tokens @@ -45,26 +49,26 @@ s = """['a' ]""" tokens = parse_source(s) - assert tokens == [Token('[', None), Token('STRING', "'a'"), - Token(']', None), Token('NEWLINE', ''), - Token('ENDMARKER', None)] + assert tokens == [Token(LSQB, None), Token(STRING, "'a'"), + Token(RSQB, None), Token(NEWLINE, ''), + Token(ENDMARKER, '')] def test_numbers(): """make sure all kind of numbers are correctly parsed""" for number in NUMBERS: - assert parse_source(number)[0] == Token('NUMBER', number) + assert parse_source(number)[0] == Token(NUMBER, number) neg = '-%s' % number - assert parse_source(neg)[:2] == [Token('-', None), - Token('NUMBER', number)] + assert parse_source(neg)[:2] == [Token(MINUS, None), + Token(NUMBER, number)] for number in BAD_NUMBERS: - assert parse_source(number)[0] != Token('NUMBER', number) + assert parse_source(number)[0] != Token(NUMBER, number) def test_hex_number(): """basic pasrse""" tokens = parse_source("a = 0x12L") - assert tokens == [Token('NAME', 'a'), Token('=', None), - Token('NUMBER', '0x12L'), Token('NEWLINE', ''), - Token('ENDMARKER', None)] + assert tokens == [Token(NAME, 'a'), Token(EQUAL, None), + Token(NUMBER, '0x12L'), Token(NEWLINE, ''), + Token(ENDMARKER, '')] def test_punct(): """make sure each punctuation is correctly parsed""" @@ -73,7 +77,7 @@ tokens = parse_source(pstr) except TokenError, error: tokens = [tok for tok, _, _, _ in error.token_stack] - assert tokens[0].name == pstr + assert tokens[0].codename == tok_punct[pstr] def test_encoding_declarations_match(): Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Thu Jul 21 12:37:26 2005 @@ -1,7 +1,6 @@ from grammar import BaseGrammarBuilder -from syntaxtree import TOKEN_MAP # , NT_OFFSET -from pythonparse import SYMBOLS +from pytoken import tok_name, tok_rpunct, NEWLINE, INDENT, DEDENT, ENDMARKER class StackElement: """wraps TupleBuilder's tuples""" @@ -18,7 +17,7 @@ return self.nodes[0][:-1] class NonTerminal(StackElement): - def __init__(self, num, nodes, rulename=None): + def __init__(self, num, nodes): """rulename should always be None with regular Python grammar""" self.nodes = nodes self.num = num @@ -32,7 +31,7 @@ """generate a nested tuples from a list of stack elements""" expanded = [] for element in stack_elements: - if isinstance(element, NonTerminal) and element.num == -2: + if isinstance(element, NonTerminal) and element.num<0: expanded.extend(element.nodes) else: expanded.append(element) @@ -46,38 +45,19 @@ # This attribute is here for convenience self.source_encoding = None self.lineno = lineno - self._unknown = -10 + self.tuplestack = [] - def _add_rule(self, rulename): - SYMBOLS[rulename] = self._unknown - self._unknown -= 1 - def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): nodes = expand_nodes( [self.stack[-1]] ) - if rule.name in SYMBOLS: - self.stack[-1] = NonTerminal(SYMBOLS[rule.name], nodes) - else: - # Using regular CPython's Grammar should not lead here - # XXX find how self._unknown is meant to be used - self.stack[-1] = NonTerminal(self._unknown, nodes, rule.name) - self._add_rule(rule.name) + self.stack[-1] = NonTerminal( rule.codename, nodes ) return True def sequence(self, rule, source, elts_number): """ """ - if rule.is_root(): - if rule.name in SYMBOLS: - num = SYMBOLS[rule.name] - node = [num] - else: - num = self._unknown - node = [num] - self._add_rule(rule.name) - else: - num = -2 - node = [num] + num = rule.codename + node = [rule.codename] if elts_number > 0: sequence_elements = self.stack[-elts_number:] nodes = expand_nodes( sequence_elements ) @@ -86,13 +66,12 @@ self.stack.append( NonTerminal(num, []) ) return True - def token(self, name, value, source): - num = TOKEN_MAP.get(name, -1) + def token(self, codename, value, source): lineno = source.current_lineno() if value is None: - if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): - value = name + if codename not in ( NEWLINE, INDENT, DEDENT, ENDMARKER ): + value = tok_rpunct.get(codename, "unknown op") else: value = '' - self.stack.append( Terminal(num, value, lineno) ) + self.stack.append( Terminal(codename, value, lineno) ) return True Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Thu Jul 21 12:37:26 2005 @@ -29,8 +29,8 @@ import pypy.interpreter.pyparser.pythonparse from pypy.interpreter.stablecompiler.ast import * import parser -import symbol -import token +import pypy.interpreter.pyparser.pysymbol as symbol +import pypy.interpreter.pyparser.pytoken as token import sys class WalkerError(StandardError): From ericvrp at codespeak.net Thu Jul 21 13:55:13 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 13:55:13 +0200 (CEST) Subject: [pypy-svn] r14853 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050721115513.B4F6327B3E@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 13:55:13 2005 New Revision: 14853 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: Make os.write..os.read external functions work by added raise (LLVM unwind). note: exception handling next. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Thu Jul 21 13:55:13 2005 @@ -72,6 +72,9 @@ def ret_void(self): self.indent("ret void") + def unwind(self): + self.indent("unwind") + def phi(self, targetvar, type_, refs, blocknames): assert targetvar.startswith('%') assert refs and len(refs) == len(blocknames), "phi node requires blocks" Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 21 13:55:13 2005 @@ -146,3 +146,6 @@ codewriter.ret(inputargtype, inputarg) else: codewriter.ret_void() + + def write_exceptblock(self, codewriter, block): + codewriter.unwind() From hpk at codespeak.net Thu Jul 21 14:00:56 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 21 Jul 2005 14:00:56 +0200 (CEST) Subject: [pypy-svn] r14854 - pypy/extradoc/minute Message-ID: <20050721120056.35E0627B6A@code1.codespeak.net> Author: hpk Date: Thu Jul 21 14:00:55 2005 New Revision: 14854 Added: pypy/extradoc/minute/pypy-sync-07-21-2005.txt Log: added minutes of today's pypy-sync meeting Added: pypy/extradoc/minute/pypy-sync-07-21-2005.txt ============================================================================== --- (empty file) +++ pypy/extradoc/minute/pypy-sync-07-21-2005.txt Thu Jul 21 14:00:55 2005 @@ -0,0 +1,228 @@ +============================================= +pypy-sync developer meeting 21st July 2005 +============================================= + +Attendees: Anders Chrigstroem, Samuele Pedroni, Adrien Di Mascio, + Ludovic Aubrien, Carl-Friedrich Bolz, Holger Krekel (minutes), + Richard Emslie (partly) + +with pre-sent info: Anders Lehmann +missing/without info: Christian Tismer, Armin Rigo (still holiday?) + +Regular Topics +==================== + +- roll call. holger opens the meeting. + +- activity reports (3 prepared lines of info). + All Attendees submitted activity reports (see `IRC-Log`_ + at the end and 'LAST/NEXT/BLOCKERS' entries in particular) + +- resolve conflicts/blockers + No direct conflicts were discovered. Main "blocker" appears to + be vacations. + +Topics of the week +=================== + +Heidelberg Sprint Planning Status +------------------------------------- + +Carl reports that the sprint room is fixed for the duration +from 22nd to 29th of August at the university of Heidelberg. +He also started a `Heidelberg sprint announcement`_. The +Hildesheim crew should finalize it next week and send it out. +There is a bit of a problem with network connectivity because +the "Rechenzentrum" mandates VPN-clients. Carl will check into +that but would enjoy help! + +Accomodation wise there is the possibility to rent a room +from a flat in Heidelberg. That would cost around 300 Euros. +Richard is interested in that. Others are thinking about it. +Everbody interested should send Carl a mail, he might even +be able to get two rooms like this. (Hotels are usually +quite expensive in Heidelberg). + +.. _`Heidelberg sprint announcement`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/Heidelberg-sprint.html + +compliance tests failures after 2.4.1 merge: how/when to tackle? +---------------------------------------------------------------------- + +Holger notices that after the 2.4.1 merge only roughly 50% of the +compliance `tests are passing`_. Samuele thinks that fixing them +requires a lot of work, approximately one week. The attendees +decide that the Hildesheim Sprint crew should decide about a +strategy of how to tackle this problem. Mails will be sent +to pypy-dev and pypy-funding (because it touches important +EU issues). + +.. _`tests are passing`: http://codespeak.net/~hpk/pypy-testresult/ + +0.6.2 release: status / when do we think to actually do it? Do we still? +---------------------------------------------------------------------------- + +We have interpreter documentation and the parser situation is improving +(running the parser on top of 2.3 yet providing 2.4 semantics). +The main blocker for the release is the compliance test situation. +Therefore further discussion/decisions are postponed until we +have a strategy regarding the compliance tests (see previous topic). + +re-assigning tasks (related to NEXT activities) +----------------------------------------------------- + +Holger notes that the hildesheim sprint crew might interfere +with the Parser (ludal) and os-level implementations (aleale). +The hildesheim sprint crew should be left free to work on +the issues as it sees fit. For people outside the sprint +it is recommended to work in short-commit cycles to avoid +conflicts and to follow the commits from the sprint. +The sprint group will try to provide info on pypy-dev or +on IRC. + +Closing +------------------ + +Holger closes the meeting in time at 13:30pm. + +.. _`IRC-log`: + +Here is the full IRC log:: + + **** BEGIN LOGGING AT Thu Jul 21 12:19:28 2005 + Jul 21 13:02:38 ok, we'll start anyway, although there appear some people to be missing + Jul 21 13:02:59 --> arre (~ac at 1-1-5-33a.gfa.gbg.bostream.se) has joined #pypy-sync + Jul 21 13:03:18 ok + Jul 21 13:03:35 everbody ready to start? + Jul 21 13:03:43 yes + Jul 21 13:03:48 I am. + Jul 21 13:03:59 yes + Jul 21 13:04:06 I am + Jul 21 13:04:16 here is the agenda (posted already yetserday to pypy-funding): + Jul 21 13:04:20 - roll call. holger opens the meeting. + Jul 21 13:04:20 - activity reports (3 prepared lines of info). + Jul 21 13:04:20 - resolve conflicts/blockers + Jul 21 13:04:20 - Heidelberg Sprint Planning Status + Jul 21 13:04:20 - compliance tests failures after 2.4.1 merge: how/when to tackle? + Jul 21 13:04:20 - 0.6.2 release: status / when do we think to actually do it? Do we still? + Jul 21 13:04:20 - re-assigning tasks (related to NEXT activities) + Jul 21 13:04:46 activity reports: i suggest the following order: hpk,aleale,ludal,adim,pedronis,arre,cfbolz, + Jul 21 13:05:05 LAST: interpreter documentation, organizing hildesheim sprint, codespeak migration planning, mentoring so + Jul 21 13:05:05 me os-level commits, fixing py test bugs + Jul 21 13:05:05 NEXT: Hildesheim-Sprint orga + hacking, EU issues + Jul 21 13:05:05 BLOCKERS: too many things going on + Jul 21 13:05:16 --- You are now known as aleale + Jul 21 13:05:23 LAST: working on posix (for pypy), started on math + Jul 21 13:05:23 NEXT: finish posix, and math ? (will try the lib-python tests) + Jul 21 13:05:23 BLOCKERS: need to understand exceptions better (interpreter level, annotation of, etc), a wedding, an immanent move to Germany + Jul 21 13:05:28 --- You are now known as hpk + Jul 21 13:05:31 last week : parser work, pysymbol and pytoken, switching to using integers for rule names instead of strings + Jul 21 13:05:31 next week : vacation + eventually resolving annotation problems + astbuilder to make annotation work further + Jul 21 13:05:31 blocker : vacation ;) + Jul 21 13:05:42 LAST: parser's annotation / astbuilder + Jul 21 13:05:42 NEXT: teach a course + Jul 21 13:05:42 blockers: no real one + Jul 21 13:05:57 Last: bug fixing in annotator and rtyper, progress rtyping PyPy adding rtyper features, implemented hook to control rtyping order, integrated suggestion to continue rtyping even after errors + Jul 21 13:05:59 Next: sprint (we are down to 57 rtyping problems with the translation snapshot) + Jul 21 13:06:00 Issues: tried to annotate the trunk, now annotation finishes but quite some involved SomeObject problems related to parser code + Jul 21 13:06:47 arre, cfbolz next + Jul 21 13:07:15 Last week: annotation/rtyper work and learning more about their internals. + Jul 21 13:07:26 Next week: Vacation until Heidelberg. + Jul 21 13:07:35 Blockers: None at the moment. + Jul 21 13:07:39 LAST: finalized sprint room, trying to get cheap accomodation, looking for the cheapest publich transport tickets + Jul 21 13:07:39 NEXT: checking network connectivity in the sprint room, Hildesheim sprint + Jul 21 13:07:39 BLOCKERS: not much, still a bit own stuff to do + Jul 21 13:08:03 ok, there appear to be no conflicts + Jul 21 13:08:16 except that the hildesheim sprint could provide conflicts + Jul 21 13:08:24 (e.g. os-level functions or the parser situation) + Jul 21 13:08:34 ludal: before you leave to holiday could you send a mail to pypy-dev about the status? + Jul 21 13:08:43 (or post it to the issue) + Jul 21 13:08:59 this way the hildesheim group knows where it could start to work if it wants to + Jul 21 13:09:23 sure, actually I'm not leaving paris so I'll be available online from time to time and hopefully following developpements of the sprint + Jul 21 13:09:36 ludal: great, ok + Jul 21 13:09:51 next topic: heidelberg status, carl? + Jul 21 13:10:08 the room is secured from 22nd to 29th + Jul 21 13:10:10 ! + Jul 21 13:10:22 have to check network connectivity: it is possible that we need some sort of VPN client to access the network + Jul 21 13:10:38 I'm trying to find student rooms + Jul 21 13:10:52 --> rxe (~rxe at client-82-2-57-5.brnt.adsl.virgin.net) has joined #pypy-sync + Jul 21 13:10:54 if there is enough interest + Jul 21 13:11:08 network connectivity: we should have our own router/machine that makes the VPN transparent if possible + Jul 21 13:11:28 yes, if someone helps me with that + Jul 21 13:11:52 the problem is that the local admins from the rechenzentrum are kind of inflexible + Jul 21 13:12:11 so I would have to do it myself + Jul 21 13:12:22 cfbolz: i see, can you try to make your own laptop work? + Jul 21 13:12:29 yes, of course + Jul 21 13:12:43 i saw you also checked in a sprint announcement + Jul 21 13:12:49 we should finalize this next week and send it out + Jul 21 13:12:54 indeed + Jul 21 13:13:14 cfbolz: is the 200-300 euro room still a concrete thing? + Jul 21 13:13:17 yes + Jul 21 13:13:26 so let's try to decide here + Jul 21 13:13:47 cfbolz has a room in a living group (WG) that costs 200-300 euro and two people could sleep there for the sprint week + Jul 21 13:14:03 I could maybe even get two rooms + Jul 21 13:14:07 not sure yet + Jul 21 13:14:30 is anyone basically interested? (hotels are kind of expensive in heidelberg) + Jul 21 13:14:44 sounds good + Jul 21 13:15:18 another question is how we pay for that + Jul 21 13:15:24 (that means i am interested) + Jul 21 13:15:37 (rxe: if you want to send your activity reports, just paste your three LAST/NEXT/BLOCKERS lines in) + Jul 21 13:15:51 arre, pedronis, ludal: anyone of you interested? + Jul 21 13:16:28 LAST: dummy Opaque type in llvm2 + Jul 21 13:16:28 NEXT: nothing planned + Jul 21 13:16:28 BLOCKERS: nothing planned + Jul 21 13:16:34 cfbolz: i think the people using the room should pay, maybe they can get a receipt? + Jul 21 13:17:10 ok, I can check that + Jul 21 13:17:26 well 300 euros seems reasonable priced for one person + Jul 21 13:17:58 arre, pedronis, ludal: ok, this is lasting too long, write cfbolz a mail if you are interested + Jul 21 13:17:58 you could even stay there longer and visit heidelberg a bit :-) + Jul 21 13:18:31 I guess the hardest HD sprint issues are solved, now that we have the room? + Jul 21 13:18:39 hpk: sure, can't decide now + Jul 21 13:18:59 cfbolz: yes, the sprint is fixed 22nd-29th, announcement next week + Jul 21 13:19:23 next topic: compliance tests failures after 2.4.1 merge: how/when to tackle? + Jul 21 13:19:50 any opinions on this? (i guess you all noticed that we have only ~50% compliance tests passing) + Jul 21 13:20:17 http://codespeak.net/~hpk/pypy-testresult/ for reference + Jul 21 13:20:31 cfbolz: where is nearest airport (sorry - next topic)? + Jul 21 13:20:34 <-- ludal (~ludal at logilab.net2.nerim.net) has left #pypy-sync + Jul 21 13:21:00 rxe: let cfbolz add this info to the announcement + Jul 21 13:21:01 rxe: frankfurt I guess + Jul 21 13:21:01 --> ludal (~ludal at logilab.net2.nerim.net) has joined #pypy-sync + Jul 21 13:21:15 ok - thanksx + Jul 21 13:21:23 * hpk notices 9 minutes left + Jul 21 13:21:46 hpk: fixing the tests is a lot of work + Jul 21 13:22:25 something around a week + Jul 21 13:22:59 i suggest that we task the hildesheim sprint crew to discuss this and come up with a strategy when/how to tackle the problem + Jul 21 13:23:24 yes, I don't think we can decide something now + Jul 21 13:23:28 everbody ok with this? + Jul 21 13:23:31 yep + Jul 21 13:23:34 yes + Jul 21 13:23:52 ok with me + Jul 21 13:23:53 yes + Jul 21 13:24:02 ok + Jul 21 13:24:32 ok, we will send according infos to pypy-dev and possibly pypy-funding (it's a critical EU issue in some ways) + Jul 21 13:24:47 next topic: 0.6.2 release: status / when do we think to actually do it? Do we still? + Jul 21 13:24:59 this is a follow up on the last week's topic + Jul 21 13:25:03 interpreter documentation is now mostly there + Jul 21 13:25:13 the parser is getting there + Jul 21 13:25:27 ludal: does the parser/compiler now run on top of Python 2.3 providing 2.4 semantics? + Jul 21 13:25:48 (my limited manual tests seem to indicate that it does) + Jul 21 13:26:01 mostly, you'll have to point out if you see problems + Jul 21 13:26:30 ok, then the main blocker for a 0.6.2 release is the compliance/test situation + Jul 21 13:27:00 so we should re-discuss it next week (after the hildesheim crew dicussed it) if nobody objects + Jul 21 13:27:05 yes + Jul 21 13:27:16 ok + Jul 21 13:27:42 I don't + Jul 21 13:27:44 ok, then last (somewhat optional) topic: - re-assigning tasks (related to NEXT activities) + Jul 21 13:28:33 like mentioned earlier, i think that the hildesheim crew might interfer with the os-level calls (aleale) and parser (ludal) developments + Jul 21 13:29:15 i think that the hildesheim crew should be allowed to work on whatever it wants and try to signal via IRC or pypy-dev/commits + Jul 21 13:29:16 ok + Jul 21 13:29:44 so it's especially important to have short commit cycles to avoid conflicts + Jul 21 13:30:02 (i.e. don't work for three days before checking something in) + Jul 21 13:30:28 ok, it's 13:30 ... closing time for the meeting + Jul 21 13:30:34 thanks for coming! + Jul 21 13:31:09 see you! + Jul 21 13:31:21 bye + Jul 21 13:31:24 see you! + Jul 21 13:31:27 Bye + Jul 21 13:32:28 <-- rxe (~rxe at client-82-2-57-5.brnt.adsl.virgin.net) has left #pypy-sync + **** ENDING LOGGING AT Thu Jul 21 13:32:33 2005 + From ludal at codespeak.net Thu Jul 21 14:06:36 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 14:06:36 +0200 (CEST) Subject: [pypy-svn] r14855 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050721120636.67DB627B6A@code1.codespeak.net> Author: ludal Date: Thu Jul 21 14:06:34 2005 New Revision: 14855 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Log: provide abstract base class for builders and contexts so that should be easier on the annotator Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 21 14:06:34 2005 @@ -79,6 +79,37 @@ assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r r.reorder_rule() +class AbstractContext(object): + """Abstract base class. derived objects put + some attributes here that users can use to save + restore states""" + pass + +class AbstractBuilder(object): + """Abstract base class for builder objects""" + def __init__(self, rules=None, debug=0, symbols={} ): + # a dictionary of grammar rules for debug/reference + self.rules = rules or {} + # This attribute is here for convenience + self.debug = debug + self.symbols = symbols # mapping from codename to symbols + + def context(self): + """Return an opaque context object""" + pass + + def restore(self, ctx): + """Accept an opaque context object""" + pass + + def alternative(self, rule, source): + return False + + def sequence(self, rule, source, elts_number): + return False + + def token(self, name, value, source): + return False from syntaxtree import SyntaxNode, TempSyntaxNode, TokenNode # @@ -87,24 +118,27 @@ # a rule like S -> A B* is mapped as Sequence( SCODE, KleenStar(-3, B)) # so S is a root and the subrule describing B* is not. # SCODE is the numerical value for rule "S" -class BaseGrammarBuilder(object): + +class BaseGrammarBuilderContext(AbstractContext): + def __init__(self, stackpos ): + self.stackpos = stackpos + +class BaseGrammarBuilder(AbstractBuilder): """Base/default class for a builder""" def __init__(self, rules=None, debug=0, symbols={} ): - # a dictionary of grammar rules for debug/reference - self.rules = rules or {} - # This attribute is here for convenience - self.source_encoding = None - self.debug = debug + AbstractBuilder.__init__(self, rules, debug, symbols ) + # stacks contain different objects depending on the builder class + # to be RPython they should not be defined in the base class self.stack = [] - self.symbols = symbols # mapping from codename to symbols def context(self): """Returns the state of the builder to be restored later""" #print "Save Stack:", self.stack - return len(self.stack) + return BaseGrammarBuilderContext(self.stack) def restore(self, ctx): - del self.stack[ctx:] + assert isinstance(ctx, BaseGrammarBuilderContext) + del self.stack[ctx.stackpos:] #print "Restore Stack:", self.stack def alternative(self, rule, source): @@ -195,7 +229,7 @@ ret = builder.sequence(self, source, 0 ) if self._trace: self._debug_display(token, level, 'eee', builder.symbols) - return self.debug_return( ret, builder.symbols, 0 ) + return ret if self._trace: self._debug_display(token, level, 'rrr', builder.symbols) return 0 @@ -257,13 +291,13 @@ return "GrammarElement" - def debug_return(self, ret, symbols, *args ): + def debug_return(self, ret, symbols, arg="" ): # FIXME: use a wrapper of match() methods instead of debug_return() - # to prevent additional indirection + # to prevent additional indirection even better a derived + # Debugging builder class if ret and DEBUG > 0: - sargs = ",".join( [ str(i) for i in args ] ) print "matched %s (%s): %s" % (self.__class__.__name__, - sargs, self.display(0, symbols=symbols) ) + arg, self.display(0, symbols=symbols) ) return ret @@ -320,7 +354,7 @@ m = rule.match(source, builder, level+1) if m: ret = builder.alternative( self, source ) - return self.debug_return( ret, builder.symbols ) + return ret return 0 def display(self, level=0, symbols={}): @@ -400,7 +434,7 @@ builder.restore(bctx) return 0 ret = builder.sequence(self, source, len(self.args)) - return self.debug_return( ret, builder.symbols ) + return ret def display(self, level=0, symbols={}): name = get_symbol( self.codename, symbols ) @@ -473,11 +507,11 @@ builder.restore(bctx) return 0 ret = builder.sequence(self, source, rules) - return self.debug_return( ret, builder.symbols, rules ) + return ret rules += 1 if self.max>0 and rules == self.max: ret = builder.sequence(self, source, rules) - return self.debug_return( ret, builder.symbols, rules ) + return ret def display(self, level=0, symbols={}): name = get_symbol( self.codename, symbols ) @@ -536,10 +570,10 @@ if tk.codename == self.codename: if self.value is None: ret = builder.token( tk.codename, tk.value, source ) - return self.debug_return( ret, builder.symbols, tk.codename ) + return ret elif self.value == tk.value: ret = builder.token( tk.codename, tk.value, source ) - return self.debug_return( ret, builder.symbols, tk.codename, tk.value ) + return ret if DEBUG > 1: print "tried tok:", self.display() source.restore( ctx ) Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Thu Jul 21 14:06:34 2005 @@ -1,5 +1,5 @@ -from grammar import BaseGrammarBuilder +from grammar import AbstractBuilder, AbstractContext from pytoken import tok_name, tok_rpunct, NEWLINE, INDENT, DEDENT, ENDMARKER class StackElement: @@ -37,16 +37,30 @@ expanded.append(element) return expanded -class TupleBuilder(BaseGrammarBuilder): +class TupleBuilderContext(AbstractContext): + def __init__(self, stackpos ): + self.stackpos = stackpos + +class TupleBuilder(AbstractBuilder): """A builder that directly produce the AST""" def __init__(self, rules=None, debug=0, lineno=True): - BaseGrammarBuilder.__init__(self, rules, debug) + AbstractBuilder.__init__(self, rules, debug) # This attribute is here for convenience self.source_encoding = None self.lineno = lineno - self.tuplestack = [] - + self.stack = [] + + def context(self): + """Returns the state of the builder to be restored later""" + #print "Save Stack:", self.stack + return TupleBuilderContext(self.stack) + + def restore(self, ctx): + assert isinstance(ctx, TupleBuilderContext) + del self.stack[ctx.stackpos:] + #print "Restore Stack:", self.stack + def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): From ludal at codespeak.net Thu Jul 21 14:10:43 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 14:10:43 +0200 (CEST) Subject: [pypy-svn] r14857 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050721121043.E872127B6D@code1.codespeak.net> Author: ludal Date: Thu Jul 21 14:10:42 2005 New Revision: 14857 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Log: oops, forgot to run the tests :( Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 21 14:10:42 2005 @@ -134,7 +134,7 @@ def context(self): """Returns the state of the builder to be restored later""" #print "Save Stack:", self.stack - return BaseGrammarBuilderContext(self.stack) + return BaseGrammarBuilderContext(len(self.stack)) def restore(self, ctx): assert isinstance(ctx, BaseGrammarBuilderContext) Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Thu Jul 21 14:10:42 2005 @@ -54,7 +54,7 @@ def context(self): """Returns the state of the builder to be restored later""" #print "Save Stack:", self.stack - return TupleBuilderContext(self.stack) + return TupleBuilderContext(len(self.stack)) def restore(self, ctx): assert isinstance(ctx, TupleBuilderContext) From ludal at codespeak.net Thu Jul 21 14:15:04 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 14:15:04 +0200 (CEST) Subject: [pypy-svn] r14858 - pypy/extradoc/minute Message-ID: <20050721121504.4DF3927B74@code1.codespeak.net> Author: ludal Date: Thu Jul 21 14:15:02 2005 New Revision: 14858 Modified: pypy/extradoc/minute/pypy-sync-07-14.txt pypy/extradoc/minute/pypy-sync-07-21-2005.txt Log: typo Modified: pypy/extradoc/minute/pypy-sync-07-14.txt ============================================================================== --- pypy/extradoc/minute/pypy-sync-07-14.txt (original) +++ pypy/extradoc/minute/pypy-sync-07-14.txt Thu Jul 21 14:15:02 2005 @@ -3,7 +3,7 @@ ============================================= -Attendees: Samuele, Anders C., Anders L., Adrien Di Mascio, Ludovic Aubrien, +Attendees: Samuele, Anders C., Anders L., Adrien Di Mascio, Ludovic Aubry, Christian Tismer, Carl-Friedrich Bolz, Holger Krekel Excused with Pre-Info: Armin Modified: pypy/extradoc/minute/pypy-sync-07-21-2005.txt ============================================================================== --- pypy/extradoc/minute/pypy-sync-07-21-2005.txt (original) +++ pypy/extradoc/minute/pypy-sync-07-21-2005.txt Thu Jul 21 14:15:02 2005 @@ -3,7 +3,7 @@ ============================================= Attendees: Anders Chrigstroem, Samuele Pedroni, Adrien Di Mascio, - Ludovic Aubrien, Carl-Friedrich Bolz, Holger Krekel (minutes), + Ludovic Aubry, Carl-Friedrich Bolz, Holger Krekel (minutes), Richard Emslie (partly) with pre-sent info: Anders Lehmann From ericvrp at codespeak.net Thu Jul 21 15:29:32 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 15:29:32 +0200 (CEST) Subject: [pypy-svn] r14861 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050721132932.998D227B6A@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 15:29:30 2005 New Revision: 14861 Added: pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py pypy/dist/pypy/translator/llvm2/test/test_seq.py pypy/dist/pypy/translator/llvm2/test/test_snippet.py Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Log: Added llvm(1) tests to see how much functionality llvm2 is still missing. Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Thu Jul 21 15:29:30 2005 @@ -8,8 +8,6 @@ from py import path import py -from pypy.tool.udir import udir -from pypy.translator.pyrex.genpyrex import GenPyrex from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture from pypy.translator.llvm2.genllvm import use_boehm_gc Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Thu Jul 21 15:29:30 2005 @@ -1,7 +1,34 @@ - #function snippets +def simple1(): + return 1 + +def simple2(): + return False +def simple3(i): + c = "Hello, Stars!" + return c[i] + +def simple4(): + return 3 + simple1() + +def simple5(b): + if b: + x = 12 + else: + x = 13 + return x + +def simple6(): + simple4() + return 1 +def ackermann(n, m): + if n == 0: + return m + 1 + if m == 0: + return ackermann(n - 1, 1) + return ackermann(n - 1, ackermann(n, m - 1)) def calling1(m): if m > 1: Added: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Thu Jul 21 15:29:30 2005 @@ -0,0 +1,66 @@ +from __future__ import division +import py + +from pypy.translator.translator import Translator +from pypy.objspace.flow.model import Constant, Variable +from pypy.translator.llvm2.genllvm import compile_function +from pypy.translator.llvm2.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): + 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_method_of_base_class(self): + f = compile_function(llvmsnippet.method_of_base_class, []) + assert f() == 14 + + def test_attribute_from_base_class(self): + f = compile_function(llvmsnippet.attribute_from_base_class, []) + assert f() == 4 + + def test_direct_call_of_virtual_method(self): + f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) + assert f() == 14 + + def test_flow_type(self): + f = compile_function(llvmsnippet.flow_type, []) + assert f() == 16 + + def test_merge_class(self): + f = compile_function(llvmsnippet.merge_classes, [bool]) + assert f(True) == 1 + assert f(False) == 2 + + def test_attribute_instance(self): + f = compile_function(llvmsnippet.attribute_instance, [bool]) + assert f(True) == 1 + assert f(False) == 2 + + def test_global_instance(self): + f = compile_function(llvmsnippet.global_instance, [int]) + assert f(-1) == 41 + for i in range(20): + assert f(i) == 2 * i + + def test_call_degrading_func(self): + f = compile_function(llvmsnippet.call_degrading_func, [bool]) + assert f(True) == -36 + assert f(False) == 14 + + def DONOTtest_circular_classdef(self): + f = compile_function(llvmsnippet.circular_classdef, []) + assert f() == 10 Added: pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Thu Jul 21 15:29:30 2005 @@ -0,0 +1,144 @@ +from __future__ import division +import sys + +import py + +from pypy.translator.translator import Translator +from pypy.objspace.flow.model import Constant, Variable +from pypy.translator.llvm2.genllvm import compile_function +from pypy.translator.llvm2.test import llvmsnippet + +class TestLLVMRepr(object): + def DONTtest_simple1(self): + t = Translator(llvmsnippet.simple1) + a = t.annotate([]) + gen = LLVMGenerator(t) + l_repr = gen.get_repr(t.getflowgraph().startblock.exits[0].args[0]) + assert l_repr.llvmname() == "1" + assert l_repr.typed_name() == "int 1" + + def DONTtest_simple2(self): + t = Translator(llvmsnippet.simple2) + a = t.annotate([]) + gen = LLVMGenerator(t) + print gen + print t.getflowgraph().startblock.exits[0].args[0] + l_repr = gen.get_repr(t.getflowgraph().startblock.exits[0].args[0]) + assert l_repr.llvmname() == "false" + assert l_repr.typed_name() == "bool false" + +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() == 0 + + 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): + f = compile_function(llvmsnippet.ackermann, [int, int]) + for i in range(10): + 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 DONOTtest_call_default_arguments(self): + 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 DONOTtest_call_list_default_argument(self): + f = compile_function(llvmsnippet.call_list_default_argument, [int]) + for i in range(20): + assert f(i) == llvmsnippet.call_list_default_argument(i) + + def DONOTtest_return_none(self): + f = compile_function(llvmsnippet.return_none, []) + assert f() is None + + def test_shift(self): + shl = compile_function(llvmsnippet.shiftleft, [int, int]) + shr = compile_function(llvmsnippet.shiftright, [int, int]) + for i in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + for j in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + assert shl(i, j) == i << j + assert shr(i, j) == i >> j + +class TestFloat(object): + def 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): + f = compile_function(llvmsnippet.string_f2, [int, int]) + assert chr(f(1, 0)) == "a" + + +class TestException(object): + def test_simple_exception(self): + f = compile_function(llvmsnippet.simple_exception, [int]) + for i in range(10): + assert f(i) == 4 + for i in range(10, 20): + assert f(i) == 2 + + def test_two_exception(self): + f = compile_function(llvmsnippet.two_exceptions, [int]) + for i in range(10): + assert f(i) == 4 + for i in range(10, 20): + assert f(i) == 2 + + def test_catch_base_exception(self): + f = compile_function(llvmsnippet.catch_base_exception, [int]) + for i in range(10): + assert f(i) == 4 + for i in range(10, 20): + assert f(i) == 2 + + def DONOT_test_catch_instance(self): + f = compile_function(llvmsnippet.catches, [int]) + assert f(1) == 1 + assert f(2) == 1 + assert f(3) == 12 + py.test.raises(RuntimeError, "f(4)") + assert f(5) == 1 + assert f(6) == 6 + assert f(13) == 13 + +class TestPBC(object): + def test_pbc_function1(self): + f = compile_function(llvmsnippet.pbc_function1, [int]) + assert f(0) == 2 + assert f(1) == 4 + assert f(2) == 6 + assert f(3) == 8 + + def DONOTtest_pbc_function2(self): + 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/llvm2/test/test_seq.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_seq.py Thu Jul 21 15:29:30 2005 @@ -0,0 +1,112 @@ +from __future__ import division +import py + +from pypy.translator.translator import Translator +from pypy.objspace.flow.model import Constant, Variable +from pypy.translator.llvm2.genllvm import compile_function +from pypy.translator.llvm2.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]) + print f(1), f(2), f(3) + 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 test_access_global_array(self): + 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/llvm2/test/test_snippet.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_snippet.py Thu Jul 21 15:29:30 2005 @@ -0,0 +1,96 @@ +from __future__ import division +import py + +from pypy.translator.translator import Translator +from pypy.translator.test import snippet as test +from pypy.objspace.flow.model import Constant, Variable + +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): + py.test.skip("two_plus_two not working yet") + f = compile_function(test.two_plus_two, []) + assert f() == 4 + + def test_sieve_of_eratosthenes(self): + py.test.skip("sieve_of_eratosthenes not working yet") + f = compile_function(test.sieve_of_eratosthenes, []) + assert f() == 1028 + + 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): + 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): + factorial2 = compile_function(test.factorial2, [int]) + assert factorial2(5) == 120 + + def test_factorial(self): + factorial = compile_function(test.factorial, [int]) + assert factorial(5) == 120 + + def test_set_attr(self): + py.test.skip("set_attr not working yet") + set_attr = compile_function(test.set_attr, []) + assert set_attr() == 2 + + def DONOT_test_try_raise_choose(self): + try_raise_choose = compile_function(test.try_raise_choose, [int]) + for i in [-1, 0, 1, 2]: + assert try_raise_choose(i) == i + + def test_merge_setattr(self): + py.test.skip("merge_setattr not working yet") + merge_setattr = compile_function(test.merge_setattr, [bool]) + assert merge_setattr(1) == 1 + + def test_simple_method(self): + py.test.skip("simple_method not working yet") + simple_method = compile_function(test.simple_method, [int]) + assert simple_method(65) == 65 + + def test_with_init(self): + py.test.skip("with_init not working yet") + with_init = compile_function(test.with_init, [int]) + assert with_init(42) == 42 + + def DONOT_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 From ludal at codespeak.net Thu Jul 21 15:42:49 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 15:42:49 +0200 (CEST) Subject: [pypy-svn] r14862 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050721134249.E3C3927B6D@code1.codespeak.net> Author: ludal Date: Thu Jul 21 15:42:48 2005 New Revision: 14862 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py Log: this is probably not RPython so change it Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 21 15:42:48 2005 @@ -155,17 +155,21 @@ items = [] for node in self.stack[-elts_number:]: items += node.expand() - if rule.is_root(): - node_type = SyntaxNode - else: - node_type = TempSyntaxNode + is_root = rule.is_root() # replace N elements with 1 element regrouping them if elts_number >= 1: - elem = node_type(rule.codename, source, items) + if is_root: + elem = SyntaxNode(rule.codename, source, items) + else: + elem = TempSyntaxNode(rule.codename, source, items) del self.stack[-elts_number:] self.stack.append(elem) elif elts_number == 0: - self.stack.append(node_type(rule.codename, source, [])) + if is_root: + self.stack.append(SyntaxNode(rule.codename, source, [])) + else: + self.stack.append(TempSyntaxNode(rule.codename, source, [])) + if self.debug: self.stack[-1].dumpstr() return True Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Thu Jul 21 15:42:48 2005 @@ -41,8 +41,8 @@ target = self.rules[goalnumber] src = Source(lines, flags) - if builder is None: - builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) +# if builder is None: +# builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) result = target.match(src, builder) # XXX find a clean way to process encoding declarations builder.source_encoding = src.encoding From ludal at codespeak.net Thu Jul 21 15:53:11 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 15:53:11 +0200 (CEST) Subject: [pypy-svn] r14863 - in pypy/dist/pypy: interpreter/pyparser module/recparser Message-ID: <20050721135311.CE5CF27B69@code1.codespeak.net> Author: ludal Date: Thu Jul 21 15:53:09 2005 New Revision: 14863 Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/module/recparser/pyparser.py Log: prevent callers of grammar to get AbstractBuilders, builder should always be provided by the caller that use it. correct recparser/pyparse to make sure it does provide it's own builder Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Thu Jul 21 15:53:09 2005 @@ -25,7 +25,7 @@ # Build first sets for each rule (including anonymous ones) grammar.build_first_sets(self.items) - def parse_source(self, textsrc, goal, builder=None, flags=0): + def parse_source(self, textsrc, goal, builder, flags=0): """Parse a python source according to goal""" lines = [line + '\n' for line in textsrc.split('\n')] if textsrc.endswith('\n'): @@ -36,13 +36,11 @@ lines[-1] = last_line[:-1] return self.parse_lines(lines, goal, builder, flags) - def parse_lines(self, lines, goal, builder=None, flags=0): + def parse_lines(self, lines, goal, builder, flags=0): goalnumber = pysymbol.sym_values[goal] target = self.rules[goalnumber] src = Source(lines, flags) -# if builder is None: -# builder = grammar.BaseGrammarBuilder(debug=False, rules=self.rules) result = target.match(src, builder) # XXX find a clean way to process encoding declarations builder.source_encoding = src.encoding @@ -85,14 +83,14 @@ debug_print( "Reloading grammar %s" % PYTHON_GRAMMAR ) PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) -def parse_file_input(pyf, gram, builder=None): +def parse_file_input(pyf, gram, builder ): """Parse a python file""" return gram.parse_source( pyf.read(), "file_input", builder ) -def parse_single_input(textsrc, gram, builder=None): +def parse_single_input(textsrc, gram, builder ): """Parse a python single statement""" return gram.parse_source( textsrc, "single_input", builder ) -def parse_eval_input(textsrc, gram, builder=None): +def parse_eval_input(textsrc, gram, builder): """Parse a python expression""" return gram.parse_source( textsrc, "eval_input", builder ) Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Thu Jul 21 15:53:09 2005 @@ -9,6 +9,7 @@ from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import SyntaxNode from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER, ParseError +from pypy.interpreter.pyparser import grammar __all__ = [ "ASTType", "STType", "suite", "expr" ] @@ -55,18 +56,18 @@ """ return self.node.name == "file_input" - def descr_compile (self, w_filename = ""): + def descr_compile (self, w_filename = ""): """STType.compile() """ # We use the compiler module for that - space = self.space - tup = self.totuple(line_info=1) - w_tup = space.wrap(tup) - w_compileAST = mycompile(space, w_tup, w_filename) + space = self.space + tup = self.totuple(line_info=1) + w_tup = space.wrap(tup) + w_compileAST = mycompile(space, w_tup, w_filename) if self.isexpr(): - return exprcompile(space, w_compileAST) + return exprcompile(space, w_compileAST) else: - return modcompile(space, w_compileAST) + return modcompile(space, w_compileAST) ASTType = STType @@ -99,23 +100,25 @@ ) def parse_python_source(space, source, goal): + builder = grammar.BaseGrammarBuilder(debug=False, rules=PYTHON_PARSER.rules) try: - return PYTHON_PARSER.parse_source(source, goal) + PYTHON_PARSER.parse_source(source, goal, builder ) + return builder.stack[-1] except ParseError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, '')) def suite( space, source ): # make the annotator life easier (don't use str.splitlines()) - builder = parse_python_source( space, source, "file_input" ) - return space.wrap( STType(space, builder.stack[-1]) ) + syntaxtree = parse_python_source( space, source, "file_input" ) + return space.wrap( STType(space, syntaxtree) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): # make the annotator life easier (don't use str.splitlines()) - builder = parse_python_source( space, source, "eval_input" ) - return space.wrap( STType(space, builder.stack[-1]) ) + syntaxtree = parse_python_source( space, source, "eval_input" ) + return space.wrap( STType(space, syntaxtree) ) expr.unwrap_spec = [ObjSpace, str] From ericvrp at codespeak.net Thu Jul 21 17:00:21 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 17:00:21 +0200 (CEST) Subject: [pypy-svn] r14869 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050721150021.4CF3E27B70@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 17:00:20 2005 New Revision: 14869 Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/opwriter.py Log: remove some (circular) imports Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfuncnode.py (original) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Thu Jul 21 17:00:20 2005 @@ -7,7 +7,7 @@ from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -from pypy.rpython.extfunctable import table as extfunctable +#from pypy.rpython.extfunctable import table as extfunctable log = log.extfuncnode class ExternalFuncNode(LLVMNode): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Thu Jul 21 17:00:20 2005 @@ -8,7 +8,6 @@ from pypy.translator.llvm2.opwriter import OpWriter from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -from pypy.rpython.extfunctable import table as extfunctable nextnum = py.std.itertools.count().next log = log.funcnode Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Thu Jul 21 17:00:20 2005 @@ -7,7 +7,7 @@ from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -from pypy.rpython.extfunctable import table as extfunctable +#from pypy.rpython.extfunctable import table as extfunctable log = log.opwriter class OpWriter(object): From mwh at codespeak.net Thu Jul 21 17:21:39 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Jul 2005 17:21:39 +0200 (CEST) Subject: [pypy-svn] r14874 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050721152139.155FD27B70@code1.codespeak.net> Author: mwh Date: Thu Jul 21 17:21:38 2005 New Revision: 14874 Modified: pypy/dist/pypy/objspace/std/test/test_stringformat.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: fix u"%(foo)s"%UserDefinedMapping() in the same way as revision 13045 did for strings. Add a test -- the first for unicode % anything !? -- but py.test has gone insane on me so I haven't run them :( Modified: pypy/dist/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/dist/pypy/objspace/std/test/test_stringformat.py Thu Jul 21 17:21:38 2005 @@ -38,6 +38,11 @@ def __getitem__(self, key): py.test.fail('should not be here') assert '' % MyMapping() == '' + class MyMapping2(object): + def __getitem__(self, key): + return key + assert '%(key)s'%MyMapping2() == 'key' + assert u'%(key)s'%MyMapping2() == u'key' class AppTestStringObject: Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Thu Jul 21 17:21:38 2005 @@ -846,9 +846,17 @@ import _formatting if isinstance(values, tuple): return _formatting.format(format, values, None, do_unicode=True) - if hasattr(values, "keys"): - return _formatting.format(format, (values,), values, do_unicode=True) - return _formatting.format(format, (values,), None, do_unicode=True) + else: + # CPython\'s logic for deciding if ""%values is + # an error (1 value, 0 %-formatters) or not + # (values is of a mapping type) + if (hasattr(values, "__getitem__") + and not isinstance(values, basestring)): + return _formatting.format(format, (values,), values, + do_unicode=True) + else: + return _formatting.format(format, (values,), None, + do_unicode=True) def unicode_encode__Unicode_ANY_ANY(unistr, encoding=None, errors=None): import codecs, sys From ericvrp at codespeak.net Thu Jul 21 17:34:25 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 21 Jul 2005 17:34:25 +0200 (CEST) Subject: [pypy-svn] r14875 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050721153425.BABB527B70@code1.codespeak.net> Author: ericvrp Date: Thu Jul 21 17:34:25 2005 New Revision: 14875 Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py Log: disabled tests that cause a segfault at the moment Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Thu Jul 21 17:34:25 2005 @@ -24,15 +24,15 @@ f = compile_function(llvmsnippet.class_simple2, [int]) assert f(2) == 10 - def test_method_of_base_class(self): + def SEGFAULTtest_method_of_base_class(self): f = compile_function(llvmsnippet.method_of_base_class, []) assert f() == 14 - def test_attribute_from_base_class(self): + def SEGFAULTtest_attribute_from_base_class(self): f = compile_function(llvmsnippet.attribute_from_base_class, []) assert f() == 4 - def test_direct_call_of_virtual_method(self): + def SEGFAULTtest_direct_call_of_virtual_method(self): f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) assert f() == 14 From adim at codespeak.net Thu Jul 21 17:46:12 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Jul 2005 17:46:12 +0200 (CEST) Subject: [pypy-svn] r14877 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050721154612.31BFE27B70@code1.codespeak.net> Author: adim Date: Thu Jul 21 17:46:10 2005 New Revision: 14877 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: - made 1 more test pass ('x = a + (1 * c)') - provides more helpful debug messages Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Thu Jul 21 17:46:10 2005 @@ -52,15 +52,14 @@ i = nb while i>0: obj = builder.pop() - if isinstance(obj,RuleObject): - i+=obj.count + if isinstance(obj, RuleObject): + i += obj.count else: L.append( obj ) i -= 1 L.reverse() return L - def build_single_input( builder, nb ): pass @@ -68,16 +67,21 @@ L = get_atoms( builder, nb ) top = L[0] if isinstance(top, TokenObject): + print "\t reducing atom (%s) (top.name) = %s" % (nb, tok.name) if top.name == tok.LPAR: - builder. ast.Tuple(L[1:-1], top.line) + builder.push( L[1] ) elif top.name == tok.LSQB: - builder.push( ast.List( L[1:-1], top.line) ) + builder.push( ast.List( L[1].nodes, top.line) ) elif top.name == tok.LBRACE: builder.push( ast.Dict( L[1:-1], top.line) ) elif top.name == tok.NAME: builder.push( ast.Name(top.value) ) elif top.name == tok.NUMBER: builder.push( ast.Const(eval(top.value)) ) + elif top.name == tok.STRING: + # need to concatenate strings in L + # builder.push( ast.Const(eval(top.value)) ) + assert False, "TODO (String)" else: raise ValueError, "unexpected tokens (%d): %s" % (nb,[ str(i) for i in L] ) @@ -234,17 +238,32 @@ nodes = [] for n in range(0,l,2): nodes.append(L[n]) - builder.push( ast.Stmt( nodes ) ) + builder.push( ast.Stmt(nodes) ) return def build_single_input( builder, nb ): L = get_atoms( builder, nb ) l = len(L) - if l>=1: - builder.push( ast.Module( None, L[0] ) ) + if l >= 1: + builder.push(ast.Module(None, L[0])) return raise WalkerError("error") +def build_testlist_gexp(builder, nb): + L = get_atoms(builder, nb) + l = len(L) + if l == 1: + builder.push(L[0]) + return + items = [] + if L[1].name == tok.COMMA: + for i in range(0, l, 2): # this is L not 1 + items.append(L[i]) + else: + # genfor + assert False, "TODO" + builder.push( Tuple( items ) ) + return ASTRULES = { # "single_input" : build_single_input, @@ -265,6 +284,7 @@ sym.small_stmt : return_one, sym.simple_stmt : build_simple_stmt, sym.single_input : build_single_input, + sym.testlist_gexp : build_testlist_gexp, } class RuleObject(ast.Node): @@ -276,7 +296,10 @@ self.col = 0 # src.getcol() def __str__(self): - return "" % (self.name,) + return "" % (sym.sym_name[self.name], self.count) + + def __repr__(self): + return "" % (sym.sym_name[self.name], self.count) class TokenObject(ast.Node): """A simple object used to wrap a rule or token""" @@ -288,7 +311,14 @@ self.col = 0 # src.getcol() def __str__(self): - return "" % (self.name, self.value) + return "" % (tok.tok_rpunct.get(self.name, + tok.tok_name.get(self.name,str(self.name))), + self.value) + + def __repr__(self): + return "" % (tok.tok_rpunct.get(self.name, + tok.tok_name.get(self.name,str(self.name))), + self.value) class AstBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" @@ -301,9 +331,10 @@ return self.rule_stack.pop(-1) def push(self, obj): + self.rule_stack.append( obj ) if not isinstance(obj, RuleObject) and not isinstance(obj, TokenObject): print "Pushed:", str(obj), len(self.rule_stack) - self.rule_stack.append( obj ) + # print "\t", self.rule_stack def push_tok(self, name, value, src ): self.push( TokenObject( name, value, src ) ) @@ -314,9 +345,10 @@ def alternative( self, rule, source ): # Do nothing, keep rule on top of the stack if rule.is_root(): - print "ALT:", sym.sym_name[rule.codename], rule.codename + print "ALT:", sym.sym_name[rule.codename], self.rule_stack F = ASTRULES.get(rule.codename) if F: + # print "REDUCING ALTERNATIVE %s" % sym.sym_name[rule.codename] F( self, 1 ) else: self.push_rule( rule.codename, 1, source ) @@ -325,10 +357,13 @@ def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - print "SEQ:", sym.sym_name[rule.codename], rule.codename + print "SEQ:", sym.sym_name[rule.codename] F = ASTRULES.get(rule.codename) if F: + # print "REDUCING SEQUENCE %s" % sym.sym_name[rule.codename] F( self, elts_number ) + else: + self.push_rule( rule.codename, elts_number, source ) else: self.push_rule( rule.codename, elts_number, source ) return True Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Jul 21 17:46:10 2005 @@ -23,9 +23,10 @@ "x = a * (1 + c)", "f = lambda x: x+1", "x, y, z = 1, 2, 3", + "x = 'a' 'b' 'c'", ] -expression_tests = [ 0, 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, ] # = range(len(expressions)) -failed_expression_tests = [ 12, 13, 14 ] +expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # = range(len(expressions)) +failed_expression_tests = [ 13, 14, 15 ] comparisons = [ "a < b", From adim at codespeak.net Thu Jul 21 18:06:06 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Jul 2005 18:06:06 +0200 (CEST) Subject: [pypy-svn] r14878 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050721160606.CF1F627B5E@code1.codespeak.net> Author: adim Date: Thu Jul 21 18:05:03 2005 New Revision: 14878 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: recognize expression like "x = 'a' 'b' 'c'" Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Thu Jul 21 18:05:03 2005 @@ -67,7 +67,7 @@ L = get_atoms( builder, nb ) top = L[0] if isinstance(top, TokenObject): - print "\t reducing atom (%s) (top.name) = %s" % (nb, tok.name) + print "\t reducing atom (%s) (top.name) = %s" % (nb, top.name) if top.name == tok.LPAR: builder.push( L[1] ) elif top.name == tok.LSQB: @@ -80,8 +80,11 @@ builder.push( ast.Const(eval(top.value)) ) elif top.name == tok.STRING: # need to concatenate strings in L - # builder.push( ast.Const(eval(top.value)) ) - assert False, "TODO (String)" + s = '' + for token in L: + s += eval(token.value) + builder.push( ast.Const(s) ) + # assert False, "TODO (String)" else: raise ValueError, "unexpected tokens (%d): %s" % (nb,[ str(i) for i in L] ) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Jul 21 18:05:03 2005 @@ -25,8 +25,8 @@ "x, y, z = 1, 2, 3", "x = 'a' 'b' 'c'", ] -expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # = range(len(expressions)) -failed_expression_tests = [ 13, 14, 15 ] +expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15] # = range(len(expressions)) +failed_expression_tests = [ 13, 14] comparisons = [ "a < b", From adim at codespeak.net Thu Jul 21 18:27:25 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Jul 2005 18:27:25 +0200 (CEST) Subject: [pypy-svn] r14879 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050721162725.2236527B70@code1.codespeak.net> Author: adim Date: Thu Jul 21 18:27:23 2005 New Revision: 14879 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: still make more tests pass TODO: we should directly put methods like 'to_lvalue()' in the ast nodes classes (ast.Tuple, ast.Name, etc.) in order to avoid code like : if isinstance(ast_node, ast.Tuple): ... elif: ... TODO2: replace calls to eval() with appropriate RPYTHON implementations Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Thu Jul 21 18:27:23 2005 @@ -13,6 +13,11 @@ def to_lvalue( ast_node, OP ): if isinstance( ast_node, ast.Name ): return ast.AssName( ast_node.name, OP ) + elif isinstance(ast_node, ast.Tuple): + nodes = [] + for node in ast_node.getChildren(): + nodes.append(ast.AssName(node.name, consts.OP_ASSIGN)) + return ast.AssTuple(nodes) else: assert False, "TODO" @@ -63,6 +68,14 @@ def build_single_input( builder, nb ): pass +def eval_number(value): + """temporary implementation""" + return eval(value) + +def eval_string(value): + """temporary implementation""" + return eval(value) + def build_atom( builder, nb ): L = get_atoms( builder, nb ) top = L[0] @@ -77,12 +90,12 @@ elif top.name == tok.NAME: builder.push( ast.Name(top.value) ) elif top.name == tok.NUMBER: - builder.push( ast.Const(eval(top.value)) ) + builder.push( ast.Const(eval_number(top.value)) ) elif top.name == tok.STRING: # need to concatenate strings in L s = '' for token in L: - s += eval(token.value) + s += eval_string(token.value) builder.push( ast.Const(s) ) # assert False, "TODO (String)" else: Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Jul 21 18:27:23 2005 @@ -25,8 +25,10 @@ "x, y, z = 1, 2, 3", "x = 'a' 'b' 'c'", ] -expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15] # = range(len(expressions)) -failed_expression_tests = [ 13, 14] +expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15] # = range(len(expressions)) +# expression_tests = [14] + +failed_expression_tests = [ 13] comparisons = [ "a < b", From ludal at codespeak.net Thu Jul 21 19:10:58 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 19:10:58 +0200 (CEST) Subject: [pypy-svn] r14883 - in pypy/dist/pypy: interpreter/pyparser module/recparser Message-ID: <20050721171058.79B6F27B74@code1.codespeak.net> Author: ludal Date: Thu Jul 21 19:10:55 2005 New Revision: 14883 Removed: pypy/dist/pypy/module/recparser/astbuilder.py Modified: pypy/dist/pypy/interpreter/pyparser/ebnflexer.py pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/syntaxtree.py pypy/dist/pypy/module/recparser/pyparser.py Log: + try to make recparser module annotate + fix (somewhat) reporting of line numbers Modified: pypy/dist/pypy/interpreter/pyparser/ebnflexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnflexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnflexer.py Thu Jul 21 19:10:55 2005 @@ -26,8 +26,10 @@ TokenSource.__init__(self) self.input = inpstring self.pos = 0 + self.begin = 0 self._peeked = None self.tokmap = tokenmap + self.current_line = 1 def context(self): """returns an opaque context object, used to backtrack @@ -47,6 +49,13 @@ """restore the context provided by context()""" self.pos, self._peeked = ctx + def current_line(self): + end = self.input.find("\n",self.pos) + return self.input[self.begin:self.pos] + + def current_lineno(self): + return self.current_line + def next(self): """returns the next token""" # We only support 1-lookahead which @@ -63,6 +72,7 @@ inp = self.input m = g_skip.match(inp, pos) while m and pos!=m.end(): + self.current_line+=m.group().count("\n") pos = m.end() if pos==len(inp): self.pos = pos @@ -71,6 +81,7 @@ m = g_symdef.match(inp,pos) if m: tk = m.group(0) + self.begin = self.pos self.pos = m.end() return Token(T['SYMDEF'],tk[:-1]) m = g_tok.match(inp,pos) Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Thu Jul 21 19:10:55 2005 @@ -2,6 +2,7 @@ from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ KleenStar, GrammarElement, build_first_sets, EmptyToken from ebnflexer import GrammarSource +from syntaxtree import AbstractSyntaxVisitor import pytoken import pysymbol @@ -71,7 +72,7 @@ return True -class EBNFVisitor(object): +class EBNFVisitor(AbstractSyntaxVisitor): def __init__(self): self.rules = {} Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 21 19:10:55 2005 @@ -40,6 +40,10 @@ return -1 def current_line(self): + """Returns the current line""" + return "" + + def current_lineno(self): """Returns the current line number""" return 0 Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Thu Jul 21 19:10:55 2005 @@ -2,13 +2,22 @@ from pypy.interpreter.pyparser.pysymbol import sym_values from pypy.interpreter.pyparser.pytoken import tok_values +class AbstractSyntaxVisitor(object): + def visit_syntaxnode( self, node ): + pass + + def visit_tempsyntaxnode( self, node ): + pass + + def visit_tokennode( self, node ): + pass class SyntaxNode(object): """A syntax node""" def __init__(self, name, source, args): self.name = name self.nodes = args - self.lineno = source.current_line() + self.lineno = source.current_lineno() def dumptree(self, treenodes, indent): """helper function used to dump the syntax tree""" @@ -38,6 +47,7 @@ return "(%s)" % self.name def visit(self, visitor): + assert isinstance(visitor, AbstractSyntaxVisitor) return visitor.visit_syntaxnode(self) def expand(self): @@ -61,6 +71,7 @@ return self.nodes def visit(self, visitor): + assert isinstance(visitor, AbstractSyntaxVisitor) return visitor.visit_tempsyntaxnode(self) class TokenNode(SyntaxNode): @@ -84,6 +95,7 @@ return "<%s!>" % (self.name,) def visit(self, visitor): + assert isinstance(visitor, AbstractSyntaxVisitor) return visitor.visit_tokennode(self) def totuple(self, lineno=False): Deleted: /pypy/dist/pypy/module/recparser/astbuilder.py ============================================================================== --- /pypy/dist/pypy/module/recparser/astbuilder.py Thu Jul 21 19:10:55 2005 +++ (empty file) @@ -1,48 +0,0 @@ - - -from grammar import BaseGrammarBuilder -from compiler.ast import nodes, TokenNode -from compiler.astfactory import factory_functions, group_factory, syntaxnode_factory - -class AstBuilder(BaseGrammarBuilder): - """A builder that directly produce the AST""" - - def __init__( self, rules=None, debug=0 ): - BaseGrammarBuilder.__init__(self, rules, debug ) - - def top(self, n=1): - toplist = [] - for node in self.stack[-n:]: - toplist += node.expand() - return toplist - - def alternative( self, rule, source ): - # Do nothing, keep rule on top of the stack - if rule.is_root(): - ast_factory = factory_functions.get( rule.name, syntaxnode_factory ) - elems = self.top() - node = ast_factory( rule.name, source, elems ) - self.stack[-1] = node - if self.debug: - self.stack[-1].dumpstr() - return True - - def sequence(self, rule, source, elts_number): - """ """ - items = self.top( elts_number ) - if rule.is_root(): - ast_factory = factory_functions.get( rule.name, syntaxnode_factory ) - else: - ast_factory = group_factory - - node = ast_factory( rule.name, source, items ) - # replace N elements with 1 element regrouping them - if elts_number >= 1: - self.stack[-elts_number:] = node - else: - self.stack.append(node) - return True - - def token(self, name, value, source): - self.stack.append(TokenNode(name, source, value)) - return True Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Thu Jul 21 19:10:55 2005 @@ -3,16 +3,60 @@ from pypy.interpreter.baseobjspace import ObjSpace, Wrappable, W_Root from pypy.interpreter.gateway import interp2app, applevel -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError from pypy.interpreter.typedef import TypeDef from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty -from pypy.interpreter.pycode import PyCode -from pypy.interpreter.pyparser.syntaxtree import SyntaxNode +from pypy.interpreter.pycode import PyCode +from pypy.interpreter.pyparser.syntaxtree import SyntaxNode, AbstractSyntaxVisitor from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER, ParseError -from pypy.interpreter.pyparser import grammar +from pypy.interpreter.pyparser import grammar, pysymbol, pytoken __all__ = [ "ASTType", "STType", "suite", "expr" ] + +class SyntaxToTupleVisitor(AbstractSyntaxVisitor): + def __init__(self, space, line_info): + self.space = space + self.line_info = line_info + self.tuple_stack_w = [] + + def result( self ): + return self.tuple_stack_w[-1] + + def visit_syntaxnode( self, node ): + space = self.space + # visiting in depth first order + for n in node.nodes: + n.visit(self) + n = len(node.nodes) + l = [ space.wrap( node.name ) ] + self.tuple_stack_w[-n:] + del self.tuple_stack_w[-n:] + self.tuple_stack_w.append( space.newtuple( l ) ) + + def visit_tempsyntaxnode( self, node ): + assert False, "Should not come here" + + def visit_tokennode( self, node ): + space = self.space + num = node.name + lineno = node.lineno + if node.value is not None: + val = node.value + else: + if num not in ( pytoken.NEWLINE, pytoken.INDENT, + pytoken.DEDENT, pytoken.ENDMARKER ): + val = pytoken.tok_rpunct[num] + else: + val = node.value or '' + if self.line_info: + self.tuple_stack_w.append( space.newtuple( [space.wrap(num), + space.wrap(val), + space.wrap(lineno)])) + else: + self.tuple_stack_w.append( space.newtuple( [space.wrap(num), + space.wrap(val)])) + + class STType (Wrappable): """Class STType """ @@ -21,73 +65,70 @@ Wrapper for parse tree data returned by parse_python_source. This encapsulate the syntaxnode at the head of the syntax tree """ - self.space = space + self.space = space self.node = syntaxnode - def totuple (self, line_info = False ): + def descr_totuple(self, line_info = True): """STType.totuple() Convert the ST object into a tuple representation. """ - # lineinfo is ignored for now - return self.node.totuple( line_info ) + visitor = SyntaxToTupleVisitor(self.space, line_info ) + self.node.visit( visitor ) + return visitor.result() - def descr_totuple(self, line_info = False): - return self.space.wrap(self.totuple(line_info)) - descr_totuple.unwrap_spec=['self', int] - def tolist (self, line_info = False): + def tolist(self, line_info = True): """STType.tolist() Convert the ST object into a list representation. """ return self.node.tolist( line_info ) - def isexpr (self): + def isexpr(self): """STType.isexpr() Returns true if the root node in the syntax tree is an expr node, false otherwise. """ - return self.node.name == "eval_input" + return self.node.name == pysymbol.eval_input - def issuite (self): + def issuite(self): """STType.issuite() Returns true if the root node in the syntax tree is a suite node, false otherwise. """ - return self.node.name == "file_input" + return self.node.name == pysymbol.file_input - def descr_compile (self, w_filename = ""): + def descr_compile(self, w_filename = ""): """STType.compile() """ # We use the compiler module for that space = self.space - tup = self.totuple(line_info=1) - w_tup = space.wrap(tup) + w_tup = self.descr_totuple(line_info=True) w_compileAST = mycompile(space, w_tup, w_filename) - if self.isexpr(): + if self.isexpr(): return exprcompile(space, w_compileAST) - else: + else: return modcompile(space, w_compileAST) ASTType = STType -app = applevel(""" - def mycompile(tup, filename): - import compiler +app = applevel(""" + def mycompile(tup, filename): + import compiler transformer = compiler.transformer.Transformer() - compileAST = transformer.compile_node(tup) + compileAST = transformer.compile_node(tup) compiler.misc.set_filename(filename, compileAST) - return compileAST + return compileAST - def exprcompile(compileAST): + def exprcompile(compileAST): import compiler gen = compiler.pycodegen.ExpressionCodeGenerator(compileAST) return gen.getCode() - def modcompile(compileAST): + def modcompile(compileAST): import compiler gen = compiler.pycodegen.ModuleCodeGenerator(compileAST) - return gen.getCode() + return gen.getCode() """, filename=__file__) mycompile = app.interphook("mycompile") @@ -111,14 +152,14 @@ def suite( space, source ): # make the annotator life easier (don't use str.splitlines()) syntaxtree = parse_python_source( space, source, "file_input" ) - return space.wrap( STType(space, syntaxtree) ) + return space.wrap( STType(space, syntaxtree) ) suite.unwrap_spec = [ObjSpace, str] def expr( space, source ): # make the annotator life easier (don't use str.splitlines()) syntaxtree = parse_python_source( space, source, "eval_input" ) - return space.wrap( STType(space, syntaxtree) ) + return space.wrap( STType(space, syntaxtree) ) expr.unwrap_spec = [ObjSpace, str] From arigo at codespeak.net Thu Jul 21 19:15:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Jul 2005 19:15:03 +0200 (CEST) Subject: [pypy-svn] r14884 - pypy/extradoc/sprintinfo Message-ID: <20050721171503.21E8A27B74@code1.codespeak.net> Author: arigo Date: Thu Jul 21 19:15:03 2005 New Revision: 14884 Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Log: Updated my sprint dates. Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Thu Jul 21 19:15:03 2005 @@ -7,7 +7,7 @@ Currently scheduled to come:: - Armin Rigo 25th-31st (?) + Armin Rigo 23rd-1st Samuele Pedroni 24th-1st Christian Tismer 25th-31st (?) Carl Friedrich Bolz 25th-31st (not there on 27th) From ludal at codespeak.net Thu Jul 21 19:25:01 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 21 Jul 2005 19:25:01 +0200 (CEST) Subject: [pypy-svn] r14885 - pypy/dist/pypy/module/recparser Message-ID: <20050721172501.69C5D27B75@code1.codespeak.net> Author: ludal Date: Thu Jul 21 19:25:00 2005 New Revision: 14885 Modified: pypy/dist/pypy/module/recparser/pyparser.py Log: one more function that couldn't be annotated Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Thu Jul 21 19:25:00 2005 @@ -20,7 +20,7 @@ self.line_info = line_info self.tuple_stack_w = [] - def result( self ): + def w_result( self ): return self.tuple_stack_w[-1] def visit_syntaxnode( self, node ): @@ -74,7 +74,7 @@ """ visitor = SyntaxToTupleVisitor(self.space, line_info ) self.node.visit( visitor ) - return visitor.result() + return visitor.w_result() descr_totuple.unwrap_spec=['self', int] @@ -165,7 +165,6 @@ def ast2tuple(space, node, line_info=0): """Quick dummy implementation of parser.ast2tuple(tree) function""" - tuples = node.totuple(line_info) - return space.wrap(tuples) + return node.descr_totuple( line_info ) ast2tuple.unwrap_spec = [ObjSpace, STType, int] From rxe at codespeak.net Thu Jul 21 20:21:53 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 21 Jul 2005 20:21:53 +0200 (CEST) Subject: [pypy-svn] r14888 - pypy/extradoc/sprintinfo Message-ID: <20050721182153.E6E8F27B9A@code1.codespeak.net> Author: rxe Date: Thu Jul 21 20:21:52 2005 New Revision: 14888 Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Log: Added my details. Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Thu Jul 21 20:21:52 2005 @@ -12,6 +12,7 @@ Christian Tismer 25th-31st (?) Carl Friedrich Bolz 25th-31st (not there on 27th) Holger Krekel 24th-31st + Richard Emslie 24th-1st Anyone, who is somewhat experienced with PyPy already, is invited to come. For new people it will make more From pedronis at codespeak.net Thu Jul 21 21:07:05 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 21:07:05 +0200 (CEST) Subject: [pypy-svn] r14890 - pypy/dist/pypy/translator/goal Message-ID: <20050721190705.12EA027BA8@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 21:07:05 2005 New Revision: 14890 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: updated with a list of the current problems as produced with -t-insist Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Thu Jul 21 21:07:05 2005 @@ -4,17 +4,292 @@ Let's list and update here the issues that will show up, or have shown up already sometime ago, while running translate_pypy:: - * FlotRepr abs + * how to implement the three overrides of translator/ann_override.py ? - * slice(SomeObject, SomeObject, SomeObject) + * current list of RTyper problems: - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC - set to a larger one. + TyperError-1: (pypy.objspace.std.typeobject:unwrap) + don't know about built-in function + .. block at -1 EH with 2 exits(v701741) + .. v701737 = simple_call((builtin_function_or_method hasattr), v701728, ('fakedcpytype')) - * how to implement the three overrides of translator/ann_override.py ? + TyperError-2: (pypy.objspace.std.listsort:lt) + unimplemented operation: 'lt' on (, ) + .. block at -1 with 1 exits + .. v795189 = lt(a_795178, b_795179) + + TyperError-3: (pypy.module.sys.vm:getrefcount) + don't know about built-in function + .. block at -1 with 1 exits + .. v412138 = simple_call((builtin_function_or_method getrefcount), w_obj_412119) + + TyperError-4: (pypy.objspace.std.listobject:unwrap) + don't know how to convert from to + .. block at -1 with 1 exits + .. v701496 = getattr(v701490, ('append')) + + TyperError-5: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v733701) + .. link from block at -1 to block at -1 + + TyperError-6: (pypy.objspace.std.sliceobject:unwrap) + don't know about built-in function + .. block at -1 with 1 exits + .. v702025 = simple_call((type slice), v701937, v701973, v702012) + + TyperError-7: (pypy.objspace.std.fake:fake__new__) + don't know how to convert from to + .. block at 9 with 1 exits + .. v521562 = getattr(v521553, ('append')) + + TyperError-8: (pypy.objspace.std.fake:fake__new__) + missing PyObjRepr.rtype_method_append + .. block at 44 with 1 exits + .. v521685 = simple_call(_1_521602, v521650) + + TyperError-9: (pypy.objspace.std.objspace:wrap__object) + is not iterable + .. block at 533 with 1 exits + .. v733768 = iter(x_733662) + + TyperError-10: (pypy.objspace.std.objspace:wrap__object) + no list() support for + .. block at 446 with 1 exits + .. v733690 = simple_call((type list), x_733593) + + TyperError-11: (pypy.module.__builtin__.compiling:compile) + call_specialcase: unknown tag override:cpy_compile + .. block at 161 with 1 exits + .. v549464 = call_specialcase(v549422, str__549335, filename_549331, mode_549332, flags_549333) + + TyperError-12: (pypy.module.__builtin__.importing:load_part) + don't know about built-in function + .. block at 201 with 2 exits(v769301) + .. v769270 = simple_call((function isdir), v769233) + + TyperError-13: (pypy.objspace.std.longobject:_FromDouble) + don't know about built-in function + .. block at 245 with 1 exits + .. v677356 = simple_call((builtin_function_or_method ldexp), v677334, (15)) + + TyperError-14: (pypy.objspace.std.objspace:wrap__object) + call_specialcase: unknown tag override:fake_object + .. block at 870 with 1 exits + .. v734154 = call_specialcase((function fake_object), v734137, v734138) + + TyperError-15: (pypy.objspace.std.objspace:wrap__object) + is not iterable + .. block at -1 with 1 exits + .. 'block-entry' + + TyperError-16: (pypy.objspace.std.objspace:wrap__object) + call_specialcase: unknown tag override:wrap_exception_cls + .. block at 811 with 2 exits(v734217) + .. v734191 = call_specialcase(v734159, x_734142) + + TyperError-17: (pypy.objspace.std.longobject:_k_mul) + unimplemented operation: 'setitem' on (, ) + .. block at 546 with 2 exits(v368685) + .. v368346 = setitem(v368281, v368345, v368259) + + TyperError-18: (pypy.objspace.std.longobject:longval) + don't know about built-in function + .. block at 50 with 1 exits + .. v723409 = simple_call((type long), d_723372) + + TyperError-19: (pypy.objspace.std.longobject:_FromDouble) + don't know about built-in function + .. block at 143 with 1 exits + .. v677171 = simple_call((builtin_function_or_method ldexp), frac_676983, v677155) + + TyperError-20: (pypy.objspace.std.tupleobject:unwrap) + don't know how to convert from to + .. block at -1 with 1 exits + .. v702406 = getattr(v702400, ('append')) + + TyperError-21: (pypy.objspace.std.tupleobject:unwrap) + don't know about built-in function + .. block at 66 with 1 exits + .. v702466 = simple_call((type tuple), v702461) + + TyperError-22: (pypy.objspace.std.longobject:_k_mul) + unimplemented operation: 'setitem' on (, ) + .. block at 435 with 2 exits(v368115) + .. v368040 = setitem(v367904, v368039, v367883) + + TyperError-23: (pypy.objspace.std.objspace:unwrap) + unimplemented operation: 'mod' on (, ) + .. block at 63 with 1 exits + .. v586013 = mod(('cannot unwrap: %r'), v586007) + + TyperError-24: (pypy.module.unicodedata.unicodedb:bidirectional) + non-constant tuple index + .. block at -1 EH with 1 exits + .. v703906 = getitem((('\x04\x04\x04\x04\x...00\x00')), v703902) + + TyperError-25: (pypy.objspace.std.unicodeobject:unwrap) + don't know how to convert from to + .. block at -1 with 1 exits + .. v701468 = simple_call((builtin_function_or_method join), v701459) + + TyperError-26: (pypy.module.__builtin__.importing:try_import_mod) + don't know about built-in function + .. block at -1 with 2 exits(v799443) + .. v799427 = simple_call((function exists), f_799397) + + TyperError-27: (pypy.objspace.std.fake:fake__new__) + don't know about built-in function + .. block at 145 with 1 exits + .. v643239 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v643211, v643212) + + TyperError-28: (pypy.objspace.std.fake:fake__new__) + don't know about built-in function + .. block at 145 with 1 exits + .. v521832 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v521804, v521805) + + TyperError-29: (pypy.objspace.std.listobject:unwrap) + no list() support for + .. block at 73 with 1 exits + .. v701590 = simple_call((type list), v701585) + + TyperError-30: (pypy.interpreter.executioncontext:__init__) + cannot create non-StrDicts, got + .. block at -1 with 1 exits + .. v371306 = newdict() + + TyperError-31: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v733237) + .. link from block at -1 to block at -1 + + TyperError-32: (pypy.objspace.std.objspace:wrap__object) + is not iterable + .. block at -1 with 1 exits + .. 'block-entry' + + TyperError-33: (pypy.objspace.std.fake:fake__new__) + missing PyObjRepr.rtype_method_append + .. block at 44 with 1 exits + .. v643092 = simple_call(_1_643009, v643057) + + TyperError-34: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v733214) + .. link from block at -1 to block at -1 + + TyperError-35: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v734039) + .. link from block at -1 to block at -1 + + TyperError-36: (pypy.objspace.std.objspace:wrap__object) + no unichr() support for + .. block at 265 with 1 exits + .. v733599 = simple_call((builtin_function_or_method unichr), v733569) + + TyperError-37: (pypy.objspace.std.longobject:_AsDouble) + don't know about built-in function + .. block at 53 with 1 exits + .. v628723 = simple_call((builtin_function_or_method ldexp), v628707, v628711) + + TyperError-38: (pypy.objspace.std.longobject:_x_divrem) + comparing a signed and an unsigned number + .. block at 709 with 2 exits(v742285) + .. v742180 = eq(v742103, (-1)) + + TyperError-39: (pypy.module.unicodedata.unicodedb:category) + non-constant tuple index + .. block at -1 EH with 1 exits + .. v655549 = getitem((('\x00\x00\x00\x00\x...02\x02')), v655545) + + TyperError-40: (pypy.interpreter.pyframe:setfastscope) + unimplemented operation: 'setitem' on ( * GcStruct object { ... } } } } }>, ) + .. block at 47 with 1 exits + .. v31663 = setitem(v31641, v31662, scope_w_31634) + + TyperError-41: (pypy.objspace.std.objspace:unwrap) + don't know how to convert from to + .. block at -1 EH with 2 exits(v585990) + .. link from block at -1 EH to codeless block + + TyperError-42: (pypy.objspace.std.longobject:_FromDouble) + don't know about built-in function + .. block at 89 with 1 exits + .. v676918 = simple_call((builtin_function_or_method frexp), v676907) + + TyperError-43: (pypy.objspace.std.objspace:wrap__object) + is not iterable + .. block at 466 with 2 exits(last_exception) + .. 'block-entry' + + TyperError-44: (pypy.objspace.std.fake:fake__new__) + don't know how to convert from to + .. block at 9 with 1 exits + .. v642969 = getattr(v642960, ('append')) + + TyperError-45: (pypy.objspace.std.fake:setfastscope) + ll_str unsupported for: + .. block at 118 with 1 exits + .. v469272 = mod(('calling %s: %s'), v469261) + + TyperError-46: (pypy.objspace.std.longobject:_long_true_divide) + don't know about built-in function + .. block at 183 with 1 exits + .. v437078 = simple_call((builtin_function_or_method ldexp), v437014, v437038) + + TyperError-47: (pypy.objspace.std.floatobject:abs__Float) + unimplemented operation: 'abs' on + .. block at -1 EH with 1 exits + .. v588581 = abs(v588570) + + TyperError-48: (pypy.objspace.std.tupleobject:unwrap) + missing PyObjRepr.rtype_method_append + .. block at 38 with 1 exits + .. v702495 = simple_call(_1_702450, v702479) + + TyperError-49: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) + cannot make repr of + .. block at 185 with 2 exits(v550361) + .. v550336 = contains(((u'+', u'-')), v550296) + + TyperError-50: (pypy.objspace.std.listobject:unwrap) + missing PyObjRepr.rtype_method_append + .. block at 45 with 1 exits + .. v701619 = simple_call(_1_701574, v701603) + + TyperError-51: (pypy.objspace.std.fake:run) + don't know about built-in function + .. block at 62 with 1 exits + .. v469642 = simple_call((builtin_function_or_method apply), v469624, v469625, v469626) + + TyperError-52: (pypy.objspace.std.objspace:wrap__object) + is not iterable + .. block at 547 with 2 exits(last_exception) + .. 'block-entry' + + TyperError-53: (pypy.objspace.std.floatobject:hash__Float) + unimplemented operation: 'hash' on + .. block at -1 with 1 exits + .. v545132 = hash(v545121) + + TyperError-54: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v734102) + .. link from block at -1 to block at 870 + + TyperError-55: (pypy.objspace.std.unicodeobject:repr__Unicode) + don't know how to convert from to + .. block at -1 with 1 exits + .. v642230 = simple_call((builtin_function_or_method join), v642219) + + * the PBCReprs generally lack a convert_from_to() to convert from a small PBC + set to a larger one. (at least as for what is triggered by the PyPy codebase + this is implemented) * the pypy trunk is still not annotable: - see issue92 about parser typing problems + progress has been made on this How to work in parallel: There is an environment variable to be set with your personal random seed. From pedronis at codespeak.net Thu Jul 21 21:11:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 21:11:12 +0200 (CEST) Subject: [pypy-svn] r14891 - pypy/dist/pypy/rpython Message-ID: <20050721191112.0DFBF27BAA@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 21:11:07 2005 New Revision: 14891 Modified: pypy/dist/pypy/rpython/rtyper.py Log: less crammed error listing Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 21 21:11:07 2005 @@ -162,8 +162,9 @@ func = "(%s:%s)" %(func.__module__ or '?', func.__name__) else: func = "(?:?)" - print "TyperError-%d: %s %r {%s}" % (c, func, block, position) + print "TyperError-%d: %s" % (c, func) print str(err) + print "" c += 1 raise TyperError("there were %d error" % len(self.typererrors)) From arigo at codespeak.net Thu Jul 21 22:23:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Jul 2005 22:23:27 +0200 (CEST) Subject: [pypy-svn] r14894 - pypy/dist/pypy/module/_codecs Message-ID: <20050721202327.3A71E27B86@code1.codespeak.net> Author: arigo Date: Thu Jul 21 22:23:26 2005 New Revision: 14894 Modified: pypy/dist/pypy/module/_codecs/app_codecs.py Log: Minor fix to ensure that encodings is imported even if _codec.register() is called before _codec.lookup(). Modified: pypy/dist/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/app_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Thu Jul 21 22:23:26 2005 @@ -41,6 +41,7 @@ codec_search_path = [] codec_search_cache = {} codec_error_registry = {} +codec_need_encodings = [True] def codec_register( search_function ): """register(search_function) @@ -63,10 +64,11 @@ result = codec_search_cache.get(encoding,None) if not result: - if len(codec_search_path) == 0: + if codec_need_encodings: import encodings if len(codec_search_path) == 0: raise LookupError("no codec search functions registered: can't find encoding") + del codec_need_encodings[:] if not isinstance(encoding,str): raise TypeError("Encoding must be a string") for search in codec_search_path: @@ -1607,4 +1609,4 @@ p += unichr(x) pos += count - return p \ No newline at end of file + return p From arigo at codespeak.net Thu Jul 21 22:31:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 21 Jul 2005 22:31:14 +0200 (CEST) Subject: [pypy-svn] r14895 - pypy/dist/pypy/interpreter Message-ID: <20050721203114.8263327B86@code1.codespeak.net> Author: arigo Date: Thu Jul 21 22:31:14 2005 New Revision: 14895 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: Trying to enable our own _codecs module by default. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 21 22:31:14 2005 @@ -145,7 +145,7 @@ self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin) self.setbuiltinmodule('unicodedata') # Uncomment the following line to enable the builtin _codecs module - #self.setbuiltinmodule('_codecs') + self.setbuiltinmodule('_codecs') # XXX we need to resolve unwrapping issues to # make this the default _sre module #self.setbuiltinmodule("_sre", "_sre_pypy") From pedronis at codespeak.net Thu Jul 21 23:08:35 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 21 Jul 2005 23:08:35 +0200 (CEST) Subject: [pypy-svn] r14896 - pypy/dist/pypy/rpython Message-ID: <20050721210835.8E9A027B44@code1.codespeak.net> Author: pedronis Date: Thu Jul 21 23:08:34 2005 New Revision: 14896 Modified: pypy/dist/pypy/rpython/rmodel.py Log: - default error fallback for hardwired_*call* - don't loop for setting rtype_contains default Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Thu Jul 21 23:08:34 2005 @@ -168,12 +168,18 @@ for opname in annmodel.UNARY_OPERATIONS: setattr_default(Repr, 'rtype_' + opname, missing_rtype_operation) + +# hardwired_*call* +setattr_default(Repr, 'rtype_hardwired_simple_call', missing_rtype_operation) +setattr_default(Repr, 'rtype_hardwired_call_args' , missing_rtype_operation) + for opname in annmodel.BINARY_OPERATIONS: setattr_default(pairtype(Repr, Repr), 'rtype_' + opname, missing_rtype_operation) + # not in BINARY_OPERATIONS - setattr_default(pairtype(Repr, Repr), - 'rtype_contains', missing_rtype_operation) +setattr_default(pairtype(Repr, Repr), + 'rtype_contains', missing_rtype_operation) class __extend__(pairtype(Repr, Repr)): def convert_from_to((r_from, r_to), v, llops): From ludal at codespeak.net Fri Jul 22 00:55:14 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 22 Jul 2005 00:55:14 +0200 (CEST) Subject: [pypy-svn] r14898 - in pypy/dist/pypy: interpreter/pyparser module/recparser Message-ID: <20050721225514.34C7E27B76@code1.codespeak.net> Author: ludal Date: Fri Jul 22 00:55:11 2005 New Revision: 14898 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/syntaxtree.py pypy/dist/pypy/module/recparser/__init__.py pypy/dist/pypy/module/recparser/pyparser.py Log: + implement parser.sequence2st this makes some of the regression tests in test_parser.py pass + still missing is validation of syntax trees (implemented, just need to add the exception wrapper and tweak it so it behaves like the test expects) Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Fri Jul 22 00:55:11 2005 @@ -149,7 +149,7 @@ # Do nothing, keep rule on top of the stack if rule.is_root(): elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.codename, source, elems) + self.stack[-1] = SyntaxNode(rule.codename, elems, source.current_lineno()) if self.debug: self.stack[-1].dumpstr() return True @@ -163,23 +163,23 @@ # replace N elements with 1 element regrouping them if elts_number >= 1: if is_root: - elem = SyntaxNode(rule.codename, source, items) + elem = SyntaxNode(rule.codename, items, source.current_lineno()) else: - elem = TempSyntaxNode(rule.codename, source, items) + elem = TempSyntaxNode(rule.codename, items, source.current_lineno()) del self.stack[-elts_number:] self.stack.append(elem) elif elts_number == 0: if is_root: - self.stack.append(SyntaxNode(rule.codename, source, [])) + self.stack.append(SyntaxNode(rule.codename, [], source.current_lineno())) else: - self.stack.append(TempSyntaxNode(rule.codename, source, [])) + self.stack.append(TempSyntaxNode(rule.codename, [], source.current_lineno())) if self.debug: self.stack[-1].dumpstr() return True def token(self, name, value, source): - self.stack.append(TokenNode(name, source, value)) + self.stack.append(TokenNode(name, value, source.current_lineno())) if self.debug: self.stack[-1].dumpstr() return True @@ -334,6 +334,11 @@ """ pass + def validate( self, syntax_node ): + """validate a syntax tree/subtree from this grammar node""" + pass + + class Alternative(GrammarElement): """Represents an alternative in a grammar rule (as in S -> A | B | C)""" def __init__(self, name, args): @@ -418,6 +423,18 @@ self.args[:] = not_empty_set self.args.extend( empty_set ) + def validate( self, syntax_node ): + """validate a syntax tree/subtree from this grammar node""" + if self.codename != syntax_node.name: + return False + if len(syntax_node.nodes) != 1: + return False + node = syntax_node.nodes[0] + for alt in self.args: + if alt.validate( node ): + return True + return False + class Sequence(GrammarElement): """Reprensents a Sequence in a grammar rule (as in S -> A B C)""" @@ -479,6 +496,18 @@ if EmptyToken not in rule.first_set: break + def validate( self, syntax_node ): + """validate a syntax tree/subtree from this grammar node""" + if self.codename != syntax_node.name: + return False + if len(syntax_node.nodes) != len(self.args): + return False + for i in xrange(len(self.args)): + rule = self.args[i] + node = syntax_node.nodes[i] + if not rule.validate( node ): + return False + return True class KleenStar(GrammarElement): @@ -554,6 +583,21 @@ self.first_set.append(EmptyToken) # self.first_set[EmptyToken] = 1 + def validate( self, syntax_node ): + """validate a syntax tree/subtree from this grammar node""" + if self.codename != syntax_node.name: + return False + rule = self.args[0] + if self.min > len(syntax_node.nodes): + return False + if self.max>=0 and self.max=0 and nodetype2: + lineno = space.int_w( items[2] ) + else: + lineno = -1 + return TokenNode( nodetype, value, lineno ) + +def sequence2st(space, w_sequence): + syntaxtree = unwrap_syntax_tree( space, w_sequence ) + return space.wrap( STType(space, syntaxtree) ) + From ludal at codespeak.net Fri Jul 22 01:46:28 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 22 Jul 2005 01:46:28 +0200 (CEST) Subject: [pypy-svn] r14899 - pypy/dist/pypy/module/recparser Message-ID: <20050721234628.03DE927B7B@code1.codespeak.net> Author: ludal Date: Fri Jul 22 01:46:27 2005 New Revision: 14899 Modified: pypy/dist/pypy/module/recparser/pyparser.py Log: should annotate fine now Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Fri Jul 22 01:46:27 2005 @@ -173,22 +173,20 @@ def unwrap_syntax_tree( space, w_sequence ): items = space.unpackiterable( w_sequence ) nodetype = space.int_w( items[0] ) - nodes = [] + is_syntax = True if nodetype>=0 and nodetype2: lineno = space.int_w( items[2] ) - else: - lineno = -1 return TokenNode( nodetype, value, lineno ) def sequence2st(space, w_sequence): From arigo at codespeak.net Fri Jul 22 14:01:12 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 14:01:12 +0200 (CEST) Subject: [pypy-svn] r14908 - pypy/dist/pypy/bin Message-ID: <20050722120112.5998427B80@code1.codespeak.net> Author: arigo Date: Fri Jul 22 14:01:11 2005 New Revision: 14908 Modified: pypy/dist/pypy/bin/translator.py Log: Removed reference to old 'llvm' directory. Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Fri Jul 22 14:01:11 2005 @@ -232,7 +232,7 @@ except ImportError, err: print "Disabling readline support (%s)" % err from pypy.translator.test import snippet as test - from pypy.translator.llvm.test import llvmsnippet as test2 + #from pypy.translator.llvm.test import llvmsnippet as test2 from pypy.rpython.rtyper import RPythonTyper try: setup_readline() From ludal at codespeak.net Fri Jul 22 14:12:56 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Fri, 22 Jul 2005 14:12:56 +0200 (CEST) Subject: [pypy-svn] r14910 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050722121256.2535D27B76@code1.codespeak.net> Author: ludal Date: Fri Jul 22 14:12:54 2005 New Revision: 14910 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py Log: small debugging function Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Fri Jul 22 14:12:54 2005 @@ -388,3 +388,18 @@ print "TOK:", tok.tok_name[name], name, value self.push_tok( name, value, source ) return True + +def show_stack(before, after): + L1 = len(before) + L2 = len(after) + for i in range(max(L1,L2)): + if i Author: cfbolz Date: Fri Jul 22 15:39:52 2005 New Revision: 14914 Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Log: I'll come on Sunday too... Modified: pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Hildesheim2-sprint.txt Fri Jul 22 15:39:52 2005 @@ -10,7 +10,7 @@ Armin Rigo 23rd-1st Samuele Pedroni 24th-1st Christian Tismer 25th-31st (?) - Carl Friedrich Bolz 25th-31st (not there on 27th) + Carl Friedrich Bolz 24th-31st (not there on 27th) Holger Krekel 24th-31st Richard Emslie 24th-1st From cfbolz at codespeak.net Fri Jul 22 15:48:02 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 22 Jul 2005 15:48:02 +0200 (CEST) Subject: [pypy-svn] r14915 - pypy/extradoc/minute Message-ID: <20050722134802.5DABB27B7C@code1.codespeak.net> Author: cfbolz Date: Fri Jul 22 15:48:01 2005 New Revision: 14915 Modified: pypy/extradoc/minute/pypy-sync-07-14.txt pypy/extradoc/minute/pypy-sync-07-21-2005.txt Log: nitpicking mode on (not that I mind too much if it's wrong but the chance is high that the correct version will propagate next meeting's minutes) Modified: pypy/extradoc/minute/pypy-sync-07-14.txt ============================================================================== --- pypy/extradoc/minute/pypy-sync-07-14.txt (original) +++ pypy/extradoc/minute/pypy-sync-07-14.txt Fri Jul 22 15:48:01 2005 @@ -4,7 +4,7 @@ Attendees: Samuele, Anders C., Anders L., Adrien Di Mascio, Ludovic Aubry, - Christian Tismer, Carl-Friedrich Bolz, Holger Krekel + Christian Tismer, Carl Friedrich Bolz, Holger Krekel Excused with Pre-Info: Armin Modified: pypy/extradoc/minute/pypy-sync-07-21-2005.txt ============================================================================== --- pypy/extradoc/minute/pypy-sync-07-21-2005.txt (original) +++ pypy/extradoc/minute/pypy-sync-07-21-2005.txt Fri Jul 22 15:48:01 2005 @@ -3,7 +3,7 @@ ============================================= Attendees: Anders Chrigstroem, Samuele Pedroni, Adrien Di Mascio, - Ludovic Aubry, Carl-Friedrich Bolz, Holger Krekel (minutes), + Ludovic Aubry, Carl Friedrich Bolz, Holger Krekel (minutes), Richard Emslie (partly) with pre-sent info: Anders Lehmann From arigo at codespeak.net Fri Jul 22 16:43:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 16:43:09 +0200 (CEST) Subject: [pypy-svn] r14916 - in pypy/dist/pypy: objspace/std translator/goal translator/test Message-ID: <20050722144309.B347527B7A@code1.codespeak.net> Author: arigo Date: Fri Jul 22 16:43:07 2005 New Revision: 14916 Modified: pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/translator/goal/ISSUES.txt pypy/dist/pypy/translator/test/test_annrpython.py Log: All the subclasses of TimSort should inherit from a common subclass, to hide the parent method TimSort.lt() from the annotator. Added a test that shows that this really hides the parent method. Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jul 22 16:43:07 2005 @@ -571,12 +571,16 @@ self.w_key = w_key self.w_item = w_item +# NOTE: all the subclasses of TimSort should inherit from a common subclass, +# so make sure that only SimpleSort inherits directly from TimSort. +# This is necessary to hide the parent method TimSort.lt() from the +# annotator. class SimpleSort(TimSort): def lt(self, a, b): space = self.space return space.is_true(space.lt(a, b)) -class CustomCompareSort(TimSort): +class CustomCompareSort(SimpleSort): def lt(self, a, b): space = self.space w_cmp = self.w_cmp @@ -590,7 +594,7 @@ raise return result < 0 -class CustomKeySort(TimSort): +class CustomKeySort(SimpleSort): def lt(self, a, b): assert isinstance(a, KeyContainer) assert isinstance(b, KeyContainer) Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 22 16:43:07 2005 @@ -13,11 +13,6 @@ .. block at -1 EH with 2 exits(v701741) .. v701737 = simple_call((builtin_function_or_method hasattr), v701728, ('fakedcpytype')) - TyperError-2: (pypy.objspace.std.listsort:lt) - unimplemented operation: 'lt' on (, ) - .. block at -1 with 1 exits - .. v795189 = lt(a_795178, b_795179) - TyperError-3: (pypy.module.sys.vm:getrefcount) don't know about built-in function .. block at -1 with 1 exits Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jul 22 16:43:07 2005 @@ -1439,8 +1439,28 @@ s = a.build_types(f, [float]) assert s.const == "dontknow" - - + def test_hidden_method(self): + class Base: + def method(self): + return ["should be hidden"] + def indirect(self): + return self.method() + class A(Base): + def method(self): + return "visible" + class B(A): + def method(self): + return None + def f(flag): + if flag: + obj = A() + else: + obj = B() + return obj.indirect() + a = self.RPythonAnnotator() + s = a.build_types(f, [bool]) + assert s == annmodel.SomeString(can_be_None=True) + def g(n): return [0,1,2,n] From arigo at codespeak.net Fri Jul 22 16:44:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 16:44:59 +0200 (CEST) Subject: [pypy-svn] r14917 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050722144459.8633527B7B@code1.codespeak.net> Author: arigo Date: Fri Jul 22 16:44:58 2005 New Revision: 14917 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Log: Merged rev 14916 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Fri Jul 22 16:44:58 2005 @@ -571,12 +571,16 @@ self.w_key = w_key self.w_item = w_item +# NOTE: all the subclasses of TimSort should inherit from a common subclass, +# so make sure that only SimpleSort inherits directly from TimSort. +# This is necessary to hide the parent method TimSort.lt() from the +# annotator. class SimpleSort(TimSort): def lt(self, a, b): space = self.space return space.is_true(space.lt(a, b)) -class CustomCompareSort(TimSort): +class CustomCompareSort(SimpleSort): def lt(self, a, b): space = self.space w_cmp = self.w_cmp @@ -590,7 +594,7 @@ raise return result < 0 -class CustomKeySort(TimSort): +class CustomKeySort(SimpleSort): def lt(self, a, b): assert isinstance(a, KeyContainer) assert isinstance(b, KeyContainer) From adim at codespeak.net Fri Jul 22 16:53:54 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 22 Jul 2005 16:53:54 +0200 (CEST) Subject: [pypy-svn] r14918 - in pypy/dist/pypy/interpreter: astcompiler stablecompiler Message-ID: <20050722145354.CDD1A27B7C@code1.codespeak.net> Author: adim Date: Fri Jul 22 16:53:52 2005 New Revision: 14918 Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py pypy/dist/pypy/interpreter/stablecompiler/transformer.py Log: Use empty lists instead of empty tuples (to avoid having lists when non empty and tuples when empty) Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/transformer.py Fri Jul 22 16:53:52 2005 @@ -273,7 +273,8 @@ if nodelist[2][0] == symbol.varargslist: names, defaults, flags = self.com_arglist(nodelist[2][1:]) else: - names = defaults = () + names = [] + defaults = [] flags = 0 # code for lambda Modified: pypy/dist/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/stablecompiler/transformer.py Fri Jul 22 16:53:52 2005 @@ -272,7 +272,8 @@ if nodelist[2][0] == symbol.varargslist: names, defaults, flags = self.com_arglist(nodelist[2][1:]) else: - names = defaults = () + names = [] + defaults = [] flags = 0 # code for lambda @@ -777,7 +778,6 @@ names = [] defaults = [] flags = 0 - i = 0 while i < len(nodelist): node = nodelist[i] From adim at codespeak.net Fri Jul 22 16:57:47 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 22 Jul 2005 16:57:47 +0200 (CEST) Subject: [pypy-svn] r14919 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050722145747.3284627B83@code1.codespeak.net> Author: adim Date: Fri Jul 22 16:57:45 2005 New Revision: 14919 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: - implemented specific backtracking for AstBuilder - added argparsing function - aded lambda constructs tests - all new tests pass Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Fri Jul 22 16:57:45 2005 @@ -1,6 +1,6 @@ -from grammar import BaseGrammarBuilder +from grammar import BaseGrammarBuilder, AbstractContext from pypy.interpreter.astcompiler import ast, consts import pypy.interpreter.pyparser.pysymbol as sym import pypy.interpreter.pyparser.pytoken as tok @@ -173,8 +173,8 @@ builder.push( left ) -def build_binary_expr( builder, nb, OP ): - L = get_atoms( builder, nb ) +def build_binary_expr(builder, nb, OP): + L = get_atoms(builder, nb) l = len(L) if l==1: builder.push( L[0] ) @@ -207,8 +207,8 @@ return build_binary_expr( builder, nb, ast.And ) def build_test( builder, nb ): - return build_binary_expr( builder, nb, ast.Or ) - + return build_binary_expr( builder, nb, ast.Or) + def build_testlist( builder, nb ): return build_binary_expr( builder, nb, ast.Tuple ) @@ -281,6 +281,66 @@ builder.push( Tuple( items ) ) return +def build_varargslist(builder, nb): + pass + +def build_lambdef(builder, nb): + L = get_atoms(builder, nb) + print "L:", L + code = L[-1] + names, defaults, flags = parse_arglist(L[1:-2]) + builder.push(ast.Lambda(names, defaults, flags, code)) + +def parse_arglist(tokens): + """returns names, defaults, flags""" + l = len(tokens) + index = 0 + defaults = [] + names = [] + flags = 0 + while index < l: + cur_token = tokens[index] + index += 1 + if not isinstance(cur_token, TokenObject): + # XXX: think of another way to write this test + defaults.append(cur_token) + elif cur_token.name == tok.COMMA: + # We could skip test COMMA by incrementing index cleverly + # but we might do some experiment on the grammar at some point + continue + elif cur_token.name == tok.STAR or cur_token.name == tok.DOUBLESTAR: + if cur_token.name == tok.STAR: + cur_token = tokens[index] + index += 1 + if cur_token.name == tok.NAME: + names.append(cur_token.value) + flags |= consts.CO_VARARGS + index += 1 + if index >= l: + break + else: + # still more tokens to read + cur_token = tokens[index] + index += 1 + else: + raise ValueError("FIXME: SyntaxError (incomplete varags) ?") + if cur_token.name != tok.DOUBLESTAR: + raise ValueError("Unexpected token: %s" % cur_token) + cur_token = tokens[index] + index += 1 + if cur_token.name == tok.NAME: + names.append(cur_token.value) + flags |= consts.CO_VARKEYWORDS + index += 1 + else: + raise ValueError("FIXME: SyntaxError (incomplete varags) ?") + if index < l: + raise ValueError("unexpected token: %s" % tokens[index]) + elif cur_token.name == tok.NAME: + names.append(cur_token.value) + return names, defaults, flags + + ASTRULES = { # "single_input" : build_single_input, sym.atom : build_atom, @@ -301,6 +361,8 @@ sym.simple_stmt : build_simple_stmt, sym.single_input : build_single_input, sym.testlist_gexp : build_testlist_gexp, + sym.lambdef : build_lambdef, + sym.varargslist : build_varargslist, } class RuleObject(ast.Node): @@ -335,7 +397,12 @@ return "" % (tok.tok_rpunct.get(self.name, tok.tok_name.get(self.name,str(self.name))), self.value) - + +class AstBuilderContext(AbstractContext): + """specific context management for AstBuidler""" + def __init__(self, rule_stack): + self.rule_stack = list(rule_stack) + class AstBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" @@ -343,6 +410,14 @@ BaseGrammarBuilder.__init__(self, rules, debug ) self.rule_stack = [] + def context(self): + return AstBuilderContext(self.rule_stack) + + def restore(self, ctx): + print "Restoring context (%s)" % (len(ctx.rule_stack)) + assert isinstance(ctx, AstBuilderContext) + self.rule_stack = ctx.rule_stack + def pop(self): return self.rule_stack.pop(-1) @@ -360,18 +435,24 @@ def alternative( self, rule, source ): # Do nothing, keep rule on top of the stack + rule_stack = self.rule_stack[:] if rule.is_root(): print "ALT:", sym.sym_name[rule.codename], self.rule_stack F = ASTRULES.get(rule.codename) if F: # print "REDUCING ALTERNATIVE %s" % sym.sym_name[rule.codename] F( self, 1 ) + else: + self.push_rule( rule.codename, 1, source ) else: self.push_rule( rule.codename, 1, source ) + # show_stack(rule_stack, self.rule_stack) + # x = raw_input("Continue ?") return True def sequence(self, rule, source, elts_number): """ """ + rule_stack = self.rule_stack[:] if rule.is_root(): print "SEQ:", sym.sym_name[rule.codename] F = ASTRULES.get(rule.codename) @@ -382,6 +463,8 @@ self.push_rule( rule.codename, elts_number, source ) else: self.push_rule( rule.codename, elts_number, source ) + # show_stack(rule_stack, self.rule_stack) + # x = raw_input("Continue ?") return True def token(self, name, value, source): @@ -401,5 +484,5 @@ obj2 = str(after[i]) else: obj2 = "-" - print "% 3d | %30s | %30s" + print "% 3d | %30s | %30s" % (i, obj1, obj2) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Fri Jul 22 16:57:45 2005 @@ -21,14 +21,24 @@ "x = a + 1 * b", "x = a * b / c", "x = a * (1 + c)", - "f = lambda x: x+1", "x, y, z = 1, 2, 3", "x = 'a' 'b' 'c'", -] -expression_tests = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15] # = range(len(expressions)) -# expression_tests = [14] +] +expression_tests = range(len(expressions)) +# expression_tests = [0] -failed_expression_tests = [ 13] +backtrackings = [ + "f = lambda x: x+1", + "f = lambda x,y: x+y", + "f = lambda x,y=1,z=t: x+y", + "f = lambda x,y=1,z=t,*args,**kwargs: x+y", + "f = lambda x,y=1,z=t,*args: x+y", + "f = lambda x,y=1,z=t,**kwargs: x+y", + "f = lambda: 1", + "f = lambda *args: 1", + "f = lambda **kwargs: 1", + ] +backtracking_tests = range(len(backtrackings)) comparisons = [ "a < b", @@ -38,6 +48,7 @@ "3 < x < 5", "(3 < x) < 5", ] + comparison_tests = [] failed_comparison_tests = range( len(comparisons) ) def ast_parse_expr( expr ): @@ -54,14 +65,17 @@ ast = tuple_parse_expr( expr ) print "ORIG :", ast print "BUILT:", r1.rule_stack[-1] - assert ast == r1.rule_stack[-1] + assert ast == r1.rule_stack[-1], 'failed on %r' % (expr) + +def test_backtracking_expressions(): + """tests for expressions that need backtracking""" + for i in backtracking_tests: + yield check_expression, backtrackings[i] def test_expressions(): -## py.test.skip("work in progress") for i in expression_tests: yield check_expression, expressions[i] def test_comparisons(): -## py.test.skip("work in progress") for i in comparison_tests: yield check_expression, comparisons[i] From arigo at codespeak.net Fri Jul 22 17:17:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 17:17:25 +0200 (CEST) Subject: [pypy-svn] r14920 - in pypy/dist/pypy/rpython: . test Message-ID: <20050722151725.07D6327B7A@code1.codespeak.net> Author: arigo Date: Fri Jul 22 17:17:23 2005 New Revision: 14920 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_robject.py Log: More special-casing necessary for lists of SomeObjects, to be able to call their methods (e.g. append()). Should fix a number of the TyperErrors in ISSUES.txt. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri Jul 22 17:17:23 2005 @@ -22,7 +22,11 @@ else: # built-in method case assert self.methodname is not None - return BuiltinMethodRepr(rtyper, self.s_self, self.methodname) + result = BuiltinMethodRepr(rtyper, self.s_self, self.methodname) + if result.self_repr == pyobj_repr: + return pyobj_repr # special case: methods of 'PyObject*' + else: + return result def rtyper_makekey(self): if self.s_self is None: # built-in function case Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Fri Jul 22 17:17:23 2005 @@ -27,8 +27,22 @@ def f(i, c): lis = [1, 2, 3, 4] lis[i] = c + lis.append(i) return len(lis) - res = interpret(f, [2, 'c'])#, view=True) - assert res == 4 + res = interpret(f, [2, 'c']) + assert res == 5 res = interpret(f, [3, 'c']) - assert res == 4 + assert res == 5 + +def inprogress_test_obj_iter(): + def f(flag): + if flag: + x = (1, 2) + else: + x = '34' + lst = [u for u in x] + return lst[flag] + res = interpret(f, [1], view=True) + assert res._obj.value == 2 + res = interpret(f, [0]) + assert res._obj.value == '3' From arigo at codespeak.net Fri Jul 22 17:42:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 17:42:32 +0200 (CEST) Subject: [pypy-svn] r14922 - in pypy/dist/pypy/rpython: . test Message-ID: <20050722154232.4C89C27B66@code1.codespeak.net> Author: arigo Date: Fri Jul 22 17:42:30 2005 New Revision: 14922 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_robject.py Log: Test iteration over PyObject*. This requires support for wrapping CPython exceptions (here StopIteration) into LLExceptions by the llinterpreter. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jul 22 17:42:30 2005 @@ -155,6 +155,12 @@ retval = ophandler(*vals) self.setvar(operation.result, retval) + def make_llexception(self, exc_class): + exdata = self.llinterpreter.typer.getexceptiondata() + evalue = exdata.ll_pyexcclass2exc(pyobjectptr(exc_class)) + etype = exdata.ll_type_of_exc_inst(evalue) + raise LLException(etype, evalue) + # __________________________________________________________ # misc LL operation implementations @@ -302,7 +308,11 @@ for pyo in pyobjs: assert typeOf(pyo) == Ptr(PyObject) func = opimpls[%(opname)r] - return pyobjectptr(func(*[pyo._obj.value for pyo in pyobjs])) + try: + pyo = func(*[pyo._obj.value for pyo in pyobjs]) + except Exception, e: + self.make_llexception(e.__class__) + return pyobjectptr(pyo) """ % locals()).compile() del opname Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Fri Jul 22 17:42:30 2005 @@ -34,7 +34,7 @@ res = interpret(f, [3, 'c']) assert res == 5 -def inprogress_test_obj_iter(): +def test_obj_iter(): def f(flag): if flag: x = (1, 2) @@ -42,7 +42,7 @@ x = '34' lst = [u for u in x] return lst[flag] - res = interpret(f, [1], view=True) + res = interpret(f, [1]) assert res._obj.value == 2 res = interpret(f, [0]) assert res._obj.value == '3' From arigo at codespeak.net Fri Jul 22 18:11:38 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 18:11:38 +0200 (CEST) Subject: [pypy-svn] r14924 - in pypy/dist/pypy/rpython: . test Message-ID: <20050722161138.5972627B80@code1.codespeak.net> Author: arigo Date: Fri Jul 22 18:11:36 2005 New Revision: 14924 Modified: pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/test/test_robject.py Log: Iteration over PyObject*. Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Fri Jul 22 18:11:36 2005 @@ -26,6 +26,8 @@ class PyObjRepr(Repr): def convert_const(self, value): return pyobjectptr(value) + def make_iterator_repr(self): + return pyobj_repr pyobj_repr = PyObjRepr() pyobj_repr.lowleveltype = Ptr(PyObject) Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Fri Jul 22 18:11:36 2005 @@ -46,3 +46,15 @@ assert res._obj.value == 2 res = interpret(f, [0]) assert res._obj.value == '3' + +def test_listofobj_iter(): + def f(look): + lst = ['*', 2, 5] + for u in lst: + if u == look: + return True + return False + res = interpret(f, [1]) + assert res is False + res = interpret(f, [2]) + assert res is True From arigo at codespeak.net Fri Jul 22 18:15:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 18:15:25 +0200 (CEST) Subject: [pypy-svn] r14925 - pypy/dist/pypy/translator/goal Message-ID: <20050722161525.233A927B80@code1.codespeak.net> Author: arigo Date: Fri Jul 22 18:15:23 2005 New Revision: 14925 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: Removing issues that are thought to be fixed. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 22 18:15:23 2005 @@ -18,11 +18,6 @@ .. block at -1 with 1 exits .. v412138 = simple_call((builtin_function_or_method getrefcount), w_obj_412119) - TyperError-4: (pypy.objspace.std.listobject:unwrap) - don't know how to convert from to - .. block at -1 with 1 exits - .. v701496 = getattr(v701490, ('append')) - TyperError-5: (pypy.objspace.std.objspace:wrap__object) don't know how to convert from to .. block at -1 with 2 exits(v733701) @@ -33,21 +28,11 @@ .. block at -1 with 1 exits .. v702025 = simple_call((type slice), v701937, v701973, v702012) - TyperError-7: (pypy.objspace.std.fake:fake__new__) - don't know how to convert from to - .. block at 9 with 1 exits - .. v521562 = getattr(v521553, ('append')) - TyperError-8: (pypy.objspace.std.fake:fake__new__) missing PyObjRepr.rtype_method_append .. block at 44 with 1 exits .. v521685 = simple_call(_1_521602, v521650) - TyperError-9: (pypy.objspace.std.objspace:wrap__object) - is not iterable - .. block at 533 with 1 exits - .. v733768 = iter(x_733662) - TyperError-10: (pypy.objspace.std.objspace:wrap__object) no list() support for .. block at 446 with 1 exits @@ -73,11 +58,6 @@ .. block at 870 with 1 exits .. v734154 = call_specialcase((function fake_object), v734137, v734138) - TyperError-15: (pypy.objspace.std.objspace:wrap__object) - is not iterable - .. block at -1 with 1 exits - .. 'block-entry' - TyperError-16: (pypy.objspace.std.objspace:wrap__object) call_specialcase: unknown tag override:wrap_exception_cls .. block at 811 with 2 exits(v734217) @@ -98,11 +78,6 @@ .. block at 143 with 1 exits .. v677171 = simple_call((builtin_function_or_method ldexp), frac_676983, v677155) - TyperError-20: (pypy.objspace.std.tupleobject:unwrap) - don't know how to convert from to - .. block at -1 with 1 exits - .. v702406 = getattr(v702400, ('append')) - TyperError-21: (pypy.objspace.std.tupleobject:unwrap) don't know about built-in function .. block at 66 with 1 exits @@ -158,11 +133,6 @@ .. block at -1 with 2 exits(v733237) .. link from block at -1 to block at -1 - TyperError-32: (pypy.objspace.std.objspace:wrap__object) - is not iterable - .. block at -1 with 1 exits - .. 'block-entry' - TyperError-33: (pypy.objspace.std.fake:fake__new__) missing PyObjRepr.rtype_method_append .. block at 44 with 1 exits @@ -213,16 +183,6 @@ .. block at 89 with 1 exits .. v676918 = simple_call((builtin_function_or_method frexp), v676907) - TyperError-43: (pypy.objspace.std.objspace:wrap__object) - is not iterable - .. block at 466 with 2 exits(last_exception) - .. 'block-entry' - - TyperError-44: (pypy.objspace.std.fake:fake__new__) - don't know how to convert from to - .. block at 9 with 1 exits - .. v642969 = getattr(v642960, ('append')) - TyperError-45: (pypy.objspace.std.fake:setfastscope) ll_str unsupported for: .. block at 118 with 1 exits @@ -258,11 +218,6 @@ .. block at 62 with 1 exits .. v469642 = simple_call((builtin_function_or_method apply), v469624, v469625, v469626) - TyperError-52: (pypy.objspace.std.objspace:wrap__object) - is not iterable - .. block at 547 with 2 exits(last_exception) - .. 'block-entry' - TyperError-53: (pypy.objspace.std.floatobject:hash__Float) unimplemented operation: 'hash' on .. block at -1 with 1 exits From adim at codespeak.net Fri Jul 22 18:25:08 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 22 Jul 2005 18:25:08 +0200 (CEST) Subject: [pypy-svn] r14926 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050722162508.AE7E527B80@code1.codespeak.net> Author: adim Date: Fri Jul 22 18:25:06 2005 New Revision: 14926 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: - implemented comparisons (+tests) - started to implement multi expressions (+tests) Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Fri Jul 22 18:25:06 2005 @@ -6,6 +6,7 @@ import pypy.interpreter.pyparser.pytoken as tok ## these tests should be methods of the ast objects +DEBUG_MODE = False def is_lvalue( ast_node ): return True @@ -197,12 +198,48 @@ def build_comparison( builder, nb ): L = get_atoms( builder, nb ) l = len(L) - if l==1: + if l == 1: builder.push( L[0] ) return - # TODO - assert False - + else: + # a < b < c is transalted into: + # Compare(Name('a'), [('<', Name(b)), ('<', Name(c))]) + left_token = L[0] + ops = [] + for i in range(1, l, 2): + # if tok.name isn't in rpunct, then it should be + # 'is', 'is not', 'not' or 'not in' => tok.value + op_name = tok.tok_rpunct.get(L[i].name, L[i].value) + ops.append((op_name, L[i+1])) + builder.push(ast.Compare(L[0], ops)) + +def build_comp_op(builder, nb): + """comp_op reducing has 2 different cases: + 1. There's only one token to reduce => nothing to + do, just re-push it on the stack + 2. Two tokens to reduce => it's either 'not in' or 'is not', + so we need to find out which one it is, and re-push a + single token + + Note: reducing comp_op is needed because reducing comparison + rules is much easier when we can assume the comparison + operator is one and only one token on the stack (which + is not the case, by default, with 'not in' and 'is not') + """ + L = get_atoms(builder, nb) + l = len(L) + # l==1 means '<', '>', '<=', etc. + if l == 1: + builder.push(L[0]) + # l==2 means 'not in' or 'is not' + elif l == 2: + if L[0].value == 'not': + builder.push(TokenObject(tok.NAME, 'not in', None)) + else: + builder.push(TokenObject(tok.NAME, 'is not', None)) + else: + assert False, "TODO" # uh ? + def build_and_test( builder, nb ): return build_binary_expr( builder, nb, ast.And ) @@ -253,9 +290,12 @@ l = len(L) nodes = [] for n in range(0,l,2): - nodes.append(L[n]) + node = L[n] + if isinstance(node, TokenObject) and node.name == tok.NEWLINE: + nodes.append(ast.Discard(ast.Const(None))) + else: + nodes.append(node) builder.push( ast.Stmt(nodes) ) - return def build_single_input( builder, nb ): L = get_atoms( builder, nb ) @@ -353,6 +393,7 @@ sym.xor_expr : build_xor_expr, sym.expr : build_expr, sym.comparison : build_comparison, + sym.comp_op : build_comp_op, sym.and_test : build_and_test, sym.test : build_test, sym.testlist : build_testlist, @@ -446,8 +487,9 @@ self.push_rule( rule.codename, 1, source ) else: self.push_rule( rule.codename, 1, source ) - # show_stack(rule_stack, self.rule_stack) - # x = raw_input("Continue ?") + if DEBUG_MODE: + show_stack(rule_stack, self.rule_stack) + x = raw_input("Continue ?") return True def sequence(self, rule, source, elts_number): @@ -463,8 +505,9 @@ self.push_rule( rule.codename, elts_number, source ) else: self.push_rule( rule.codename, elts_number, source ) - # show_stack(rule_stack, self.rule_stack) - # x = raw_input("Continue ?") + if DEBUG_MODE: + show_stack(rule_stack, self.rule_stack) + x = raw_input("Continue ?") return True def token(self, name, value, source): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Fri Jul 22 18:25:06 2005 @@ -44,13 +44,24 @@ "a < b", "a > b", "a not in b", + "a is not b", "a in b", + "a is b", "3 < x < 5", "(3 < x) < 5", + "a < b < c < d", + "(a < b) < (c < d)", + "a < (b < c) < d", + ] +comparison_tests = range(len(comparisons)) +# comparison_tests = [7] + +multiexpr = [ + 'a = b; c = d;', + 'a = b = c = d', + 'a = b\nc = d', ] -comparison_tests = [] -failed_comparison_tests = range( len(comparisons) ) def ast_parse_expr( expr ): builder = AstBuilder() PYTHON_PARSER.parse_source( expr, "single_input", builder ) @@ -67,6 +78,12 @@ print "BUILT:", r1.rule_stack[-1] assert ast == r1.rule_stack[-1], 'failed on %r' % (expr) + + +def test_multiexpr(): + for expr in multiexpr: + yield check_expression, expr + def test_backtracking_expressions(): """tests for expressions that need backtracking""" for i in backtracking_tests: From arigo at codespeak.net Fri Jul 22 18:26:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 18:26:21 +0200 (CEST) Subject: [pypy-svn] r14927 - pypy/dist/pypy/translator/goal Message-ID: <20050722162621.F173527B80@code1.codespeak.net> Author: arigo Date: Fri Jul 22 18:26:20 2005 New Revision: 14927 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: This seems to be done. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 22 18:26:20 2005 @@ -233,10 +233,6 @@ .. block at -1 with 1 exits .. v642230 = simple_call((builtin_function_or_method join), v642219) - * the PBCReprs generally lack a convert_from_to() to convert from a small PBC - set to a larger one. (at least as for what is triggered by the PyPy codebase - this is implemented) - * the pypy trunk is still not annotable: - see issue92 about parser typing problems progress has been made on this From arigo at codespeak.net Fri Jul 22 18:48:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 18:48:14 +0200 (CEST) Subject: [pypy-svn] r14929 - in pypy/dist/pypy: annotation rpython rpython/test translator/goal Message-ID: <20050722164814.4E6C627B76@code1.codespeak.net> Author: arigo Date: Fri Jul 22 18:48:11 2005 New Revision: 14929 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: setslice on lists, only for non-resizing expressions like lst1[x:y] = lst2 with y-x == len(lst2). Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Fri Jul 22 18:48:11 2005 @@ -434,9 +434,9 @@ return getbookkeeper().newlist(lst.listdef.read_item()) def setitem((lst, slic), s_iterable): - lst.listdef.resize() - s_iter = s_iterable.iter() - pair(lst, SomeInteger()).setitem(s_iter.next()) + # we need the same unifying effect as the extend() method for + # the case lst1[x:y] = lst2. + lst.method_extend(s_iterable) def delitem((lst1, slic)): lst1.listdef.resize() Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Fri Jul 22 18:48:11 2005 @@ -220,6 +220,16 @@ return hop.gendirectcall(ll_listslice_minusone, v_lst) raise TyperError(r_slic) + def rtype_setitem((r_lst, r_slic), hop): + #if r_slic == startonly_slice_repr: + # not implemented + if r_slic == startstop_slice_repr: + v_lst, v_slice, v_lst2 = hop.inputargs(r_lst, startstop_slice_repr, + r_lst) + hop.gendirectcall(ll_listsetslice, v_lst, v_slice, v_lst2) + return + raise TyperError(r_slic) + def rtype_delitem((r_lst, r_slic), hop): if r_slic == startonly_slice_repr: v_lst, v_start = hop.inputargs(r_lst, startonly_slice_repr) @@ -493,6 +503,16 @@ j += 1 l1.items = newitems +def ll_listsetslice(l1, slice, l2): + count = len(l2.items) + assert count == slice.stop - slice.start, ( + "setslice cannot resize lists in RPython") + start = slice.start + j = 0 + while j < count: + l1.items[start+j] = l2.items[j] + j += 1 + # ____________________________________________________________ # # Comparison. 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 Jul 22 18:48:11 2005 @@ -8,7 +8,7 @@ from pypy.rpython.test.test_llinterp import find_exception -def sample_list(): +def sample_list(): # [42, 43, 44, 45] rlist = ListRepr(signed_repr) rlist.setup() l = ll_newlist(rlist.lowleveltype, 3) @@ -82,6 +82,22 @@ del expected[start:stop] check_list(l, expected) +def test_rlist_setslice(): + n = 100 + for start in range(5): + for stop in range(start, 5): + l1 = sample_list() + l2 = sample_list() + expected = [42, 43, 44, 45] + for i in range(start, stop): + expected[i] = n + ll_setitem(l2, i, n) + n += 1 + s = ll_newslice(start, stop) + l2 = ll_listslice(l2, s) + ll_listsetslice(l1, s, l2) + check_list(l1, expected) + # ____________________________________________________________ def rtype(fn, argtypes=[]): @@ -154,6 +170,17 @@ del l[:] rtype(dummyfn) +def test_setslice(): + def dummyfn(): + l = [10, 9, 8, 7] + l[:2] = [6, 5] + return l[0], l[1], l[2], l[3] + res = interpret(dummyfn, ()) + assert res.item0 == 6 + assert res.item1 == 5 + assert res.item2 == 8 + assert res.item3 == 7 + def test_insert_pop(): def dummyfn(): l = [6, 7, 8] Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 22 18:48:11 2005 @@ -63,11 +63,6 @@ .. block at 811 with 2 exits(v734217) .. v734191 = call_specialcase(v734159, x_734142) - TyperError-17: (pypy.objspace.std.longobject:_k_mul) - unimplemented operation: 'setitem' on (, ) - .. block at 546 with 2 exits(v368685) - .. v368346 = setitem(v368281, v368345, v368259) - TyperError-18: (pypy.objspace.std.longobject:longval) don't know about built-in function .. block at 50 with 1 exits @@ -83,11 +78,6 @@ .. block at 66 with 1 exits .. v702466 = simple_call((type tuple), v702461) - TyperError-22: (pypy.objspace.std.longobject:_k_mul) - unimplemented operation: 'setitem' on (, ) - .. block at 435 with 2 exits(v368115) - .. v368040 = setitem(v367904, v368039, v367883) - TyperError-23: (pypy.objspace.std.objspace:unwrap) unimplemented operation: 'mod' on (, ) .. block at 63 with 1 exits @@ -168,11 +158,6 @@ .. block at -1 EH with 1 exits .. v655549 = getitem((('\x00\x00\x00\x00\x...02\x02')), v655545) - TyperError-40: (pypy.interpreter.pyframe:setfastscope) - unimplemented operation: 'setitem' on ( * GcStruct object { ... } } } } }>, ) - .. block at 47 with 1 exits - .. v31663 = setitem(v31641, v31662, scope_w_31634) - TyperError-41: (pypy.objspace.std.objspace:unwrap) don't know how to convert from to .. block at -1 EH with 2 exits(v585990) From arigo at codespeak.net Fri Jul 22 18:57:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Jul 2005 18:57:08 +0200 (CEST) Subject: [pypy-svn] r14931 - in pypy/dist/pypy: rpython translator/c/src translator/c/test translator/goal Message-ID: <20050722165708.61B1B27B76@code1.codespeak.net> Author: arigo Date: Fri Jul 22 18:57:04 2005 New Revision: 14931 Modified: pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/translator/c/src/float.h pypy/dist/pypy/translator/c/test/test_annotated.py pypy/dist/pypy/translator/goal/ISSUES.txt Log: abs(float) in the rtyper and the C back-end. Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Fri Jul 22 18:57:04 2005 @@ -124,6 +124,10 @@ vlist = hop.inputargs(Float) return vlist[0] + def rtype_abs(_, hop): + vlist = hop.inputargs(Float) + return hop.genop('float_abs', vlist, resulttype=Float) + def rtype_int(_, hop): vlist = hop.inputargs(Float) return hop.genop('cast_float_to_int', vlist, resulttype=Signed) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Fri Jul 22 18:57:04 2005 @@ -202,10 +202,6 @@ def get_ll_eq_function(self): return None - def rtype_float(_, hop): - vlist = hop.inputargs(Float) - return vlist[0] - def rtype_chr(_, hop): vlist = hop.inputargs(Signed) return hop.genop('cast_int_to_char', vlist, resulttype=Char) Modified: pypy/dist/pypy/translator/c/src/float.h ============================================================================== --- pypy/dist/pypy/translator/c/src/float.h (original) +++ pypy/dist/pypy/translator/c/src/float.h Fri Jul 22 18:57:04 2005 @@ -3,14 +3,11 @@ /*** C header subsection: operations between floats ***/ -/* XXX INCOMPLETE */ - - /*** unary operations ***/ #define OP_FLOAT_IS_TRUE(x,r,err) OP_FLOAT_NE(x,0.0,r,err) -#define OP_FLOAT_NEG(x,r,err) r = -x; - +#define OP_FLOAT_NEG(x,r,err) r = -x; +#define OP_FLOAT_ABS(x,r,err) r = fabs(x); /*** binary operations ***/ Modified: pypy/dist/pypy/translator/c/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/c/test/test_annotated.py Fri Jul 22 18:57:04 2005 @@ -158,3 +158,10 @@ return g3.next.next.value fn = self.getcompiled(do_things) assert fn() == 1 + + def test_float_ops(self): + def f(x=float): + return abs((-x) ** 3 + 1) + fn = self.getcompiled(f) + assert fn(-4.5) == 92.125 + assert fn(4.5) == 90.125 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Fri Jul 22 18:57:04 2005 @@ -178,11 +178,6 @@ .. block at 183 with 1 exits .. v437078 = simple_call((builtin_function_or_method ldexp), v437014, v437038) - TyperError-47: (pypy.objspace.std.floatobject:abs__Float) - unimplemented operation: 'abs' on - .. block at -1 EH with 1 exits - .. v588581 = abs(v588570) - TyperError-48: (pypy.objspace.std.tupleobject:unwrap) missing PyObjRepr.rtype_method_append .. block at 38 with 1 exits From pedronis at codespeak.net Fri Jul 22 19:44:51 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 22 Jul 2005 19:44:51 +0200 (CEST) Subject: [pypy-svn] r14939 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050722174451.87AE227B7B@code1.codespeak.net> Author: pedronis Date: Fri Jul 22 19:44:50 2005 New Revision: 14939 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/translator/test/test_annrpython.py Log: nonneg cleverness should not kill unsignedness + test Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Fri Jul 22 19:44:50 2005 @@ -257,11 +257,11 @@ 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)) + SomeInteger(nonneg=True, unsigned=int2.unsigned)) 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)) + SomeInteger(nonneg=True, unsigned=int1.unsigned)) if knowntypedata: r.knowntypedata = knowntypedata return r Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jul 22 19:44:50 2005 @@ -1272,6 +1272,24 @@ s = a.build_types(f, [int, int]) assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 2) + def test_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(unsigned=True)]) + wg1 = a.translator.getflowgraph(witness1) + wg2 = a.translator.getflowgraph(witness2) + assert a.binding(wg1.getargs()[0]).unsigned is True + assert a.binding(wg2.getargs()[0]).unsigned is True + + def test_attr_moving_into_parent(self): class A: pass class B(A): pass From pedronis at codespeak.net Fri Jul 22 22:55:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 22 Jul 2005 22:55:07 +0200 (CEST) Subject: [pypy-svn] r14942 - pypy/dist/pypy/interpreter Message-ID: <20050722205507.93E9527B7B@code1.codespeak.net> Author: pedronis Date: Fri Jul 22 22:55:06 2005 New Revision: 14942 Modified: pypy/dist/pypy/interpreter/function.py Log: avoid co_freevars to be attached to eval.Code Modified: pypy/dist/pypy/interpreter/function.py ============================================================================== --- pypy/dist/pypy/interpreter/function.py (original) +++ pypy/dist/pypy/interpreter/function.py Fri Jul 22 22:55:06 2005 @@ -150,11 +150,15 @@ return space.wrap(self.code) def fset_func_code(space, self, w_code): + from pypy.interpreter.pycode import PyCode code = space.interpclass_w(w_code) if not isinstance(code, Code): raise OperationError(space.w_TypeError, space.wrap("func_code must be set to a code object") ) - if len(self.code.co_freevars) != len(code.co_freevars): - raise OperationError(space.w_ValueError, space.wrap("%s() requires a code object with %s free vars, not %s " % (self.name, len(self.code.co_freevars), len(code.co_freevars)))) + closure_len = 0 + if self.closure: + closure_len = len(self.closure) + if isinstance(code, PyCode) and closure_len != len(code.co_freevars): + raise OperationError(space.w_ValueError, space.wrap("%s() requires a code object with %s free vars, not %s " % (self.name, closure_len, len(code.co_freevars)))) self.code = code def fget_func_closure(space, self): From pedronis at codespeak.net Sat Jul 23 00:05:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 00:05:01 +0200 (CEST) Subject: [pypy-svn] r14943 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050722220501.BE21327B76@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 00:05:00 2005 New Revision: 14943 Modified: pypy/dist/pypy/interpreter/pyparser/automata.py Log: make the signatures of recognized uniform Modified: pypy/dist/pypy/interpreter/pyparser/automata.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/automata.py (original) +++ pypy/dist/pypy/interpreter/pyparser/automata.py Sat Jul 23 00:05:00 2005 @@ -30,7 +30,7 @@ self.start = start # ____________________________________________________________ - def recognize (self, inVec, pos = 0, greedy = True): + def recognize (self, inVec, pos = 0): # greedy = True crntState = self.start i = pos lastAccept = False From pedronis at codespeak.net Sat Jul 23 00:06:09 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 00:06:09 +0200 (CEST) Subject: [pypy-svn] r14944 - in pypy/dist/pypy/rpython: . test Message-ID: <20050722220609.BB9E027B74@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 00:06:08 2005 New Revision: 14944 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: some support for multiple functions with multiple patterns as long as the functions have identical signatures (defaults included); the parser contains some instances of this, it is reasonable enough to support. With test. --This line, and those below, will be ignored-- M rpython/rpbc.py M rpython/test/test_rpbc.py M rpython/normalizecalls.py Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Sat Jul 23 00:06:08 2005 @@ -67,11 +67,21 @@ if classdef is None and not isinstance(func, (type, types.ClassType, types.MethodType))] if len(functions) > 1: # otherwise, nothing to do + fully_normalized = True if len(family.patterns) > 1: - raise TyperError("don't support multiple call patterns " - "to multiple functions for now %r" % ( - functions)) - pattern, = family.patterns + argspec = inspect.getargspec(functions[0]) + for func in functions: + if inspect.getargspec(func) != argspec: + raise TyperError("don't support multiple call patterns " + "to multiple functions with different signatures for now %r" % ( + functions)) + args, varargs, varkwds, _ = argspec + assert varargs is None, "XXX not implemented" + assert varkwds is None, "XXX not implemented" + pattern = (len(args), (), False, False) + fully_normalized = False + else: + pattern, = family.patterns shape_cnt, shape_keys, shape_star, shape_stst = pattern assert not shape_star, "XXX not implemented" assert not shape_stst, "XXX not implemented" @@ -150,7 +160,7 @@ # finished checkgraph(graph) annotator.annotated[newblock] = annotator.annotated[oldblock] - graph.normalized_for_calls = True + graph.normalized_for_calls = fully_normalized # convert the return value too annotator.setbinding(graph.getreturnvar(), generalizedresult) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jul 23 00:06:08 2005 @@ -340,6 +340,14 @@ rresult = Void return f, rinputs, rresult +def samesig(funcs): + import inspect + argspec = inspect.getargspec(funcs[0]) + for func in funcs: + if inspect.getargspec(func) != argspec: + return False + return True + class FunctionsPBCRepr(Repr): """Representation selected for a PBC of function(s).""" @@ -389,8 +397,10 @@ vlist = hop.inputargs(self, *rinputs) else: # if not normalized, should be a call to a known function - assert len(self.function_signatures()) == 1, "normalization bug" - func, = self.function_signatures().keys() + # or to functions all with same signature + funcs = self.function_signatures().keys() + assert samesig(funcs), "normalization bug" + func = funcs[0] vlist = [hop.inputarg(self, arg=0)] vlist += callparse.callparse('simple_call', func, rinputs, hop) @@ -412,8 +422,10 @@ vlist = vlist[:1] + vlist[2:] else: # if not normalized, should be a call to a known function - assert len(self.function_signatures()) == 1, "normalization bug" - func, = self.function_signatures().keys() + # or to functions all with same signature + funcs = self.function_signatures().keys() + assert samesig(funcs), "normalization bug" + func = funcs[0] vlist = [hop.inputarg(self, arg=0)] vlist += callparse.callparse('call_args', func, rinputs, hop) 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 Jul 23 00:06:08 2005 @@ -763,3 +763,29 @@ res = interpret(f, [3, 0]) assert res == 5 + +def test_various_patterns_but_one_signature_method(): + class A: + def meth(self, a, b=0): + raise NotImplementedError + class B(A): + def meth(self, a, b=0): + return a+b + + class C(A): + def meth(self, a, b=0): + return a*b + def f(i): + if i == 0: + x = B() + else: + x = C() + r1 = x.meth(1) + r2 = x.meth(3, 2) + r3 = x.meth(7, b=11) + return r1+r2+r3 + res = interpret(f, [0]) + assert res == 1+3+2+7+11 + res = interpret(f, [1]) + assert res == 3*2+11*7 + From pedronis at codespeak.net Sat Jul 23 00:26:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 00:26:12 +0200 (CEST) Subject: [pypy-svn] r14945 - pypy/dist/pypy/rpython Message-ID: <20050722222612.5161527B74@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 00:26:11 2005 New Revision: 14945 Modified: pypy/dist/pypy/rpython/rstr.py Log: sanity check the join method argument Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 23 00:26:11 2005 @@ -123,6 +123,9 @@ if hop.s_result.is_constant(): return inputconst(string_repr, hop.s_result.const) r_lst = hop.args_r[1] + from pypy.rpython.rlist import ListRepr + if not isinstance(r_lst, ListRepr): + raise TyperError("string.join of non-list: %r" % r_lst) v_str, v_lst = hop.inputargs(string_repr, r_lst) cname = inputconst(Void, "items") v_items = hop.genop("getfield", [v_lst, cname], From ericvrp at codespeak.net Sat Jul 23 00:35:10 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Jul 2005 00:35:10 +0200 (CEST) Subject: [pypy-svn] r14946 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050722223510.5AF5027B74@code1.codespeak.net> Author: ericvrp Date: Sat Jul 23 00:35:09 2005 New Revision: 14946 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/opwriter.py Log: added pointer and shift operations Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 23 00:35:09 2005 @@ -86,6 +86,9 @@ def binaryop(self, name, targetvar, type_, ref1, ref2): self.indent("%s = %s %s %s, %s" % (targetvar, name, type_, ref1, ref2)) + def shiftop(self, name, targetvar, type_, ref1, ref2): + self.indent("%s = %s %s %s, ubyte %s" % (targetvar, name, type_, ref1, ref2)) + def call(self, targetvar, returntype, functionref, argrefs, argtypes): arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref, Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 23 00:35:09 2005 @@ -16,6 +16,9 @@ 'int_sub': 'sub', 'int_floordiv': 'div', 'int_mod': 'rem', + 'int_and': 'and', + 'int_or': 'or', + 'int_xor': 'xor', 'int_lt': 'setlt', 'int_le': 'setle', 'int_eq': 'seteq', @@ -28,6 +31,9 @@ 'uint_sub': 'sub', 'uint_floordiv': 'div', 'uint_mod': 'rem', + 'uint_and': 'and', + 'uint_or': 'or', + 'uint_xor': 'xor', 'uint_lt': 'setlt', 'uint_le': 'setle', 'uint_eq': 'seteq', @@ -53,6 +59,16 @@ 'float_ne': 'setne', 'float_ge': 'setge', 'float_gt': 'setgt', + + 'ptr_eq': 'seteq', + 'ptr_ne': 'setne', + } + + shift_operations = {'int_lshift': 'shl', + 'int_rshift': 'shr', + + 'uint_lshift': 'shl', + 'uint_rshift': 'shr', } def __init__(self, db, codewriter): @@ -62,6 +78,8 @@ def write_operation(self, op): if op.opname in self.binary_operations: self.binaryop(op) + elif op.opname in self.shift_operations: + self.shiftop(op) else: meth = getattr(self, op.opname, None) assert meth is not None, "operation %r not found" %(op.opname,) @@ -83,7 +101,6 @@ "true") - def binaryop(self, op): name = self.binary_operations[op.opname] assert len(op.args) == 2 @@ -93,6 +110,20 @@ self.db.repr_arg(op.args[0]), self.db.repr_arg(op.args[1])) + def shiftop(self, op): + name = self.shift_operations[op.opname] + assert len(op.args) == 2 + if isinstance(op.args[1], Constant): + tmpvar = op.args[1] + else: + tmpvar = self.db.repr_tmpvar() + self.codewriter.cast(tmpvar, self.db.repr_arg_type(op.args[1]), self.db.repr_arg(op.args[1]), 'ubyte') + self.codewriter.shiftop(name, + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + tmpvar) + def cast_primitive(self, op): #works for all primitives assert len(op.args) == 1 targetvar = self.db.repr_arg(op.result) @@ -113,7 +144,6 @@ self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), "0") - uint_is_true = int_is_true def float_is_true(self, op): @@ -122,7 +152,21 @@ self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), "0.0") - + + def ptr_nonzero(self, op): + self.codewriter.binaryop("setne", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "null") + + def ptr_iszero(self, op): + self.codewriter.binaryop("seteq", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + "null") + def direct_call(self, op): assert len(op.args) >= 1 targetvar = self.db.repr_arg(op.result) From ericvrp at codespeak.net Sat Jul 23 00:49:32 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Jul 2005 00:49:32 +0200 (CEST) Subject: [pypy-svn] r14947 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050722224932.C018A27B69@code1.codespeak.net> Author: ericvrp Date: Sat Jul 23 00:49:31 2005 New Revision: 14947 Added: pypy/dist/pypy/translator/llvm2/test/test_exception.py Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py pypy/dist/pypy/translator/llvm2/test/test_lltype.py pypy/dist/pypy/translator/llvm2/test/test_snippet.py Log: Lots more test pass now (107 passed, 17 failed, of which 11 are exceptions tests). Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 23 00:49:31 2005 @@ -68,6 +68,12 @@ def writeimpl(self, codewriter): assert self._issetup graph = self.graph + #dir(graph)==['__class__', '__delattr__', '__dict__', '__doc__', + # '__getattribute__', '__hash__', '__init__', '__module__', + # '__new__', '__reduce__', '__reduce_ex__', '__repr__', + # '__setattr__', '__str__', '__weakref__', 'exceptblock', + # 'func', 'getargs', 'getreturnvar', 'name', 'returnblock', + # 'show', 'source', 'startblock'] log.writeimpl(graph.name) codewriter.openfunc(self.getdecl()) nextblock = graph.startblock Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jul 23 00:49:31 2005 @@ -1,3 +1,5 @@ +from __future__ import division + #function snippets def simple1(): return 1 @@ -375,52 +377,6 @@ return len((1, 2, "asdf")) + i -#exception snippets: -def simple_exception(n): - lst = range(10) - try: - lst[n] - except IndexError: - return 2 - return 4 - -def two_exceptions(n): - lst = range(10) - try: - lst[n] - except IndexError: - return 2 - except KeyError: - return 3 - return 4 - -def catch_base_exception(n): - lst = range(10) - try: - lst[n] - except LookupError: - return 2 - return 4 - -class MyException(Exception): - def __init__(self, n): - self.n = n - -def raises(i): - if i == 3: - raise MyException, 12 - if i == 4: - raise IndexError - if i > 5: - raise MyException(i) - return 1 - -def catches(i): - try: - return raises(i) - except MyException, e: - return e.n - #PBC snippets class PBCClass(object): Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Sat Jul 23 00:49:31 2005 @@ -52,15 +52,15 @@ def test_global_instance(self): f = compile_function(llvmsnippet.global_instance, [int]) - assert f(-1) == 41 + assert f(-1) == llvmsnippet.global_instance(-1) for i in range(20): - assert f(i) == 2 * i + assert f(i) == llvmsnippet.global_instance(i) def test_call_degrading_func(self): f = compile_function(llvmsnippet.call_degrading_func, [bool]) - assert f(True) == -36 - assert f(False) == 14 + assert f(True) == llvmsnippet.call_degrading_func(True) #-36 + assert f(False) == llvmsnippet.call_degrading_func(False) #14 - def DONOTtest_circular_classdef(self): + def test_circular_classdef(self): f = compile_function(llvmsnippet.circular_classdef, []) assert f() == 10 Added: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sat Jul 23 00:49:31 2005 @@ -0,0 +1,159 @@ +from pypy.translator.llvm2.genllvm import compile_function +from pypy.translator.test.snippet import try_raise_choose + +class TestException(Exception): + pass + +class MyException(Exception): + def __init__(self, n): + self.n = n + +def test_simple1(): + def raise_(i): + if i: + raise TestException() + else: + return 1 + def fn(i): + try: + return raise_(i) + except TestException: + return 0 + 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: + 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_pass_exc(): + def fn(n): + lst = range(10) + try: + 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_divzero(): + def fn(n): + try: + n/0 + except: + return 2 + return 4 + f = compile_function(fn, [int]) + assert f(0) == fn(0) + +def test_reraise1(): + def fn(n): + lst = range(10) + try: + lst[n] + except: + raise + return 4 + f = compile_function(fn, [int]) + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == fn(10) + +def test_reraise2(): + def fn(n): + lst = range(10) + try: + lst[n] + except e: + raise e + return 4 + f = compile_function(fn, [int]) + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == fn(10) + +def test_simple_exception(): + def fn(n): + lst = range(10) + try: + 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_exceptions(): + def fn(n): + lst = range(10) + try: + 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: + 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 + 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)") + 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 Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Sat Jul 23 00:49:31 2005 @@ -20,14 +20,14 @@ import time def fn(): return time.time() - f = compile_function(fn, [], view=False) + f = compile_function(fn, []) assert abs(f()-fn()) < 10.0 def test_external_function_ll_time_clock(): import time def fn(): return time.clock() - f = compile_function(fn, [], view=False) + f = compile_function(fn, []) assert abs(f()-fn()) < 10.0 def test_external_function_ll_time_sleep(): @@ -35,7 +35,7 @@ def fn(t): time.sleep(t) return 666 - f = compile_function(fn, [float], view=False) + f = compile_function(fn, [float]) start_time = time.time() delay_time = 2.0 d = f(delay_time) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jul 23 00:49:31 2005 @@ -15,7 +15,7 @@ f = compile_function(simple1, []) assert f() == 1 -def DONTtest_simple_function_pointer(): +def test_simple_function_pointer(): def f1(x): return x + 1 def f2(x): @@ -331,28 +331,12 @@ f = compile_function(method_call, []) assert f() == 4 -class TestException(Exception): - pass - -def DONTtest_exception(): - def raise_(i): - if i: - raise TestException() - else: - return 1 - def catch(i): - try: - return raise_(i) - except TestException: - return 0 - f = compile_function(catch, [int]) - -def Xtest_dict_creation(): +def test_dict_creation(): d = {'hello' : 23, 'world' : 21} l = ["hello", "world"] def createdict(i, j): return d[l[i]] + d[l[j]] - f = compile_function(createdict, [int, int], view=True) - - assert createdict(0, 1) == 43 + assert createdict(0,1) == 44 + f = compile_function(createdict, [int, int]) + assert f(0,1) == createdict(0,1) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Sat Jul 23 00:49:31 2005 @@ -8,25 +8,6 @@ from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.llvm2.test import llvmsnippet -class TestLLVMRepr(object): - def DONTtest_simple1(self): - t = Translator(llvmsnippet.simple1) - a = t.annotate([]) - gen = LLVMGenerator(t) - l_repr = gen.get_repr(t.getflowgraph().startblock.exits[0].args[0]) - assert l_repr.llvmname() == "1" - assert l_repr.typed_name() == "int 1" - - def DONTtest_simple2(self): - t = Translator(llvmsnippet.simple2) - a = t.annotate([]) - gen = LLVMGenerator(t) - print gen - print t.getflowgraph().startblock.exits[0].args[0] - l_repr = gen.get_repr(t.getflowgraph().startblock.exits[0].args[0]) - assert l_repr.llvmname() == "false" - assert l_repr.typed_name() == "bool false" - class TestGenLLVM(object): def test_simple1(self): f = compile_function(llvmsnippet.simple1, []) @@ -57,28 +38,31 @@ f = compile_function(llvmsnippet.calling1, [int]) assert f(10) == 1 - def DONOTtest_call_default_arguments(self): + def test_call_default_arguments(self): 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 DONOTtest_call_list_default_argument(self): + def test_call_list_default_argument(self): f = compile_function(llvmsnippet.call_list_default_argument, [int]) for i in range(20): assert f(i) == llvmsnippet.call_list_default_argument(i) - def DONOTtest_return_none(self): - f = compile_function(llvmsnippet.return_none, []) - assert f() is None - def test_shift(self): shl = compile_function(llvmsnippet.shiftleft, [int, int]) shr = compile_function(llvmsnippet.shiftright, [int, int]) + assert shl(42,2) == llvmsnippet.shiftleft(42, 2) + assert shr(42,2) == llvmsnippet.shiftright(42,2) + + def test_shift_with_overflow(self): + shl = compile_function(llvmsnippet.shiftleft, [int, int]) + shr = compile_function(llvmsnippet.shiftright, [int, int]) for i in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: for j in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: assert shl(i, j) == i << j assert shr(i, j) == i >> j + class TestFloat(object): def test_float_f1(self): f = compile_function(llvmsnippet.float_f1, [float]) @@ -95,38 +79,6 @@ assert chr(f(1, 0)) == "a" -class TestException(object): - def test_simple_exception(self): - f = compile_function(llvmsnippet.simple_exception, [int]) - for i in range(10): - assert f(i) == 4 - for i in range(10, 20): - assert f(i) == 2 - - def test_two_exception(self): - f = compile_function(llvmsnippet.two_exceptions, [int]) - for i in range(10): - assert f(i) == 4 - for i in range(10, 20): - assert f(i) == 2 - - def test_catch_base_exception(self): - f = compile_function(llvmsnippet.catch_base_exception, [int]) - for i in range(10): - assert f(i) == 4 - for i in range(10, 20): - assert f(i) == 2 - - def DONOT_test_catch_instance(self): - f = compile_function(llvmsnippet.catches, [int]) - assert f(1) == 1 - assert f(2) == 1 - assert f(3) == 12 - py.test.raises(RuntimeError, "f(4)") - assert f(5) == 1 - assert f(6) == 6 - assert f(13) == 13 - class TestPBC(object): def test_pbc_function1(self): f = compile_function(llvmsnippet.pbc_function1, [int]) @@ -135,7 +87,7 @@ assert f(2) == 6 assert f(3) == 8 - def DONOTtest_pbc_function2(self): + def test_pbc_function2(self): f = compile_function(llvmsnippet.pbc_function2, [int]) assert f(0) == 13 assert f(1) == 15 Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_lltype.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Sat Jul 23 00:49:31 2005 @@ -28,8 +28,8 @@ def struct_constant(): x1 = s.signed + s.unsigned return x1 - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == 3 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_struct_constant2(): S2 = lltype.GcStruct("struct2", ('a', lltype.Signed), ('s1', S), ('s2', S)) @@ -41,8 +41,8 @@ s.s2.b = 3 def struct_constant(): return s.a + s.s2.b + s.s1.a + s.s1.b - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == 14 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_struct_constant3(): structs = [] @@ -62,8 +62,8 @@ return (top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.a - top.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.b) - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == 5 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_struct_constant4(): SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed)) @@ -73,8 +73,8 @@ s.sptr.a = 21 def struct_constant(): return s.sptr.a * 2 - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == 42 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_struct_constant5(): SPTR = lltype.GcStruct('sptr', ('a', lltype.Signed), ('b', S)) @@ -86,8 +86,8 @@ s.sptr.b.b = 10 def struct_constant(): return s.sptr.a + s.sptr.b.a + s.sptr.b.b - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == 42 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_struct_constant6(): U = lltype.Struct('inlined', ('z', lltype.Signed)) @@ -101,8 +101,8 @@ s.p = s.u def struct_constant(): return s.x.y + s.p.z - fn = compile_function(struct_constant, [], embedexterns=False) - assert fn() == -58 + f = compile_function(struct_constant, [], embedexterns=False) + assert f() == struct_constant() def test_array_constant(): A = lltype.GcArray(lltype.Signed) @@ -112,8 +112,8 @@ a[2] = 102 def array_constant(): return a[0] + a[1] + a[2] - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 303 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_array_constant2(): A = lltype.GcArray(lltype.Signed) @@ -124,8 +124,8 @@ def array_constant(): a[0] = 0 return a[0] + a[1] + a[2] - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 203 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_array_constant3(): A = lltype.GcArray(('x', lltype.Signed)) @@ -135,8 +135,8 @@ a[2].x = 102 def array_constant(): return a[0].x + a[1].x + a[2].x - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 303 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_struct_array1(): A = lltype.GcArray(lltype.Signed) @@ -147,8 +147,8 @@ a[1] = 101 def array_constant(): return s.aptr[1] - a[0] - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 1 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_struct_array2(): A = lltype.Array(lltype.Signed) @@ -159,8 +159,8 @@ s.b[1] = 101 def array_constant(): return s.b[1] - s.b[0] + s.a - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 42 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_struct_array3(): A = lltype.Array(lltype.Signed) @@ -175,8 +175,8 @@ def array_constant(): s = b.p return s.b[1] - s.b[0] + s.a - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 42 + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() def test_struct_opaque(): PRTTI = lltype.Ptr(lltype.RuntimeTypeInfo) @@ -185,6 +185,5 @@ s.a = 42 def array_constant(): return s.a - fn = compile_function(array_constant, [], embedexterns=False) - assert fn() == 42 - + f = compile_function(array_constant, [], embedexterns=False) + assert f() == array_constant() Modified: pypy/dist/pypy/translator/llvm2/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_snippet.py Sat Jul 23 00:49:31 2005 @@ -1,9 +1,7 @@ from __future__ import division -import py -from pypy.translator.translator import Translator +from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.test import snippet as test -from pypy.objspace.flow.model import Constant, Variable class TestSnippet(object): def test_if_then_else(self): @@ -29,12 +27,10 @@ assert f(0) == 0 def test_two_plus_two(self): - py.test.skip("two_plus_two not working yet") f = compile_function(test.two_plus_two, []) assert f() == 4 def test_sieve_of_eratosthenes(self): - py.test.skip("sieve_of_eratosthenes not working yet") f = compile_function(test.sieve_of_eratosthenes, []) assert f() == 1028 @@ -66,31 +62,22 @@ assert factorial(5) == 120 def test_set_attr(self): - py.test.skip("set_attr not working yet") set_attr = compile_function(test.set_attr, []) assert set_attr() == 2 - def DONOT_test_try_raise_choose(self): - try_raise_choose = compile_function(test.try_raise_choose, [int]) - for i in [-1, 0, 1, 2]: - assert try_raise_choose(i) == i - def test_merge_setattr(self): - py.test.skip("merge_setattr not working yet") merge_setattr = compile_function(test.merge_setattr, [bool]) assert merge_setattr(1) == 1 def test_simple_method(self): - py.test.skip("simple_method not working yet") simple_method = compile_function(test.simple_method, [int]) assert simple_method(65) == 65 def test_with_init(self): - py.test.skip("with_init not working yet") with_init = compile_function(test.with_init, [int]) assert with_init(42) == 42 - def DONOT_test_with_more_init(self): + 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 From pedronis at codespeak.net Sat Jul 23 01:32:39 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 01:32:39 +0200 (CEST) Subject: [pypy-svn] r14948 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050722233239.4E47227B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 01:32:38 2005 New Revision: 14948 Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Log: self.name is a number! avoid that treenodes in dumptree becomes a list of SomeObjects Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py (original) +++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py Sat Jul 23 01:32:38 2005 @@ -21,7 +21,7 @@ def dumptree(self, treenodes, indent): """helper function used to dump the syntax tree""" - treenodes.append(self.name) + treenodes.append(str(self.name)) if len(self.nodes) > 1: treenodes.append(" -> (\n") treenodes.append(indent+" ") From ericvrp at codespeak.net Sat Jul 23 01:41:29 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Jul 2005 01:41:29 +0200 (CEST) Subject: [pypy-svn] r14949 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050722234129.40B8427B6D@code1.codespeak.net> Author: ericvrp Date: Sat Jul 23 01:41:28 2005 New Revision: 14949 Modified: pypy/dist/pypy/translator/llvm2/extfunction.py pypy/dist/pypy/translator/llvm2/funcnode.py Log: storing raised exception type and value in a global variable (throught some ugly casting for now) Modified: pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/extfunction.py Sat Jul 23 01:41:28 2005 @@ -14,6 +14,8 @@ %st.rpy_string.0 = type {int, {int, [0 x sbyte]}} +%last_exception_type = global long 0 +%last_exception_value = global long 0 """ gc_boehm = """ Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 23 01:41:28 2005 @@ -153,4 +153,19 @@ codewriter.ret_void() def write_exceptblock(self, codewriter, block): + assert len(block.inputargs) == 2 + self.write_block_phi_nodes(codewriter, block) + inputargs = self.db.repr_arg_multi(block.inputargs) + inputargtypes = self.db.repr_arg_type_multi(block.inputargs) + + #XXX add pending last_exception global here + t = 'long' #void* + tmpvar = self.db.repr_tmpvar() + codewriter.cast(tmpvar, inputargtypes[0], inputargs[0], t) + codewriter.store(t, tmpvar, 'last_exception_type') + + tmpvar = self.db.repr_tmpvar() + codewriter.cast(tmpvar, inputargtypes[1], inputargs[1], t) + codewriter.store(t, tmpvar, 'last_exception_value') + codewriter.unwind() From pedronis at codespeak.net Sat Jul 23 01:49:30 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 01:49:30 +0200 (CEST) Subject: [pypy-svn] r14950 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050722234930.50A5427B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 01:49:29 2005 New Revision: 14950 Modified: pypy/dist/pypy/interpreter/pyparser/automata.py Log: the rtyper does not support dict with str or None keys. ugly workaround for now. string-keyed dicts do not seem the best way to store these char indexed tables Modified: pypy/dist/pypy/interpreter/pyparser/automata.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/automata.py (original) +++ pypy/dist/pypy/interpreter/pyparser/automata.py Sat Jul 23 01:49:29 2005 @@ -18,7 +18,7 @@ # a simple None works fine. # (Having a DefaultClass inheriting from str makes # the annotator crash) -DEFAULT = None +DEFAULT = "\00default" # PYPY Modification : removed all automata functions (any, maybe, # newArcPair, etc.) From pedronis at codespeak.net Sat Jul 23 01:51:26 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 01:51:26 +0200 (CEST) Subject: [pypy-svn] r14951 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050722235126.D0AD027B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 01:51:26 2005 New Revision: 14951 Modified: pypy/dist/pypy/interpreter/pyparser/automata.py Log: oops there was a xxx comment too Modified: pypy/dist/pypy/interpreter/pyparser/automata.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/automata.py (original) +++ pypy/dist/pypy/interpreter/pyparser/automata.py Sat Jul 23 01:51:26 2005 @@ -18,7 +18,8 @@ # a simple None works fine. # (Having a DefaultClass inheriting from str makes # the annotator crash) -DEFAULT = "\00default" +DEFAULT = "\00default" # XXX hack, the rtyper does not support dict of with str|None keys + # anyway using dicts doesn't seem the best final way to store these char indexed tables # PYPY Modification : removed all automata functions (any, maybe, # newArcPair, etc.) From pedronis at codespeak.net Sat Jul 23 02:26:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 02:26:28 +0200 (CEST) Subject: [pypy-svn] r14952 - pypy/dist/pypy/objspace/std Message-ID: <20050723002628.9298627B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 02:26:27 2005 New Revision: 14952 Modified: pypy/dist/pypy/objspace/std/longtype.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/strutil.py Log: now W_LongObject.digits are just ints Modified: pypy/dist/pypy/objspace/std/longtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/longtype.py (original) +++ pypy/dist/pypy/objspace/std/longtype.py Sat Jul 23 02:26:27 2005 @@ -3,7 +3,6 @@ from pypy.interpreter.error import OperationError from pypy.objspace.std.inttype import int_typedef from pypy.interpreter.gateway import NoneNotWrapped -from pypy.rpython.rarithmetic import r_uint def descr__new__(space, w_longtype, w_x=0, w_base=NoneNotWrapped): from pypy.objspace.std.longobject import W_LongObject, args_from_long @@ -44,7 +43,7 @@ sign = 1 else: sign = 0 - w_value = W_LongObject(space, [r_uint(abs(intval))], sign) + w_value = W_LongObject(space, [abs(intval)], sign) else: raise OperationError(space.w_ValueError, space.wrap("value can't be converted to long")) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Sat Jul 23 02:26:27 2005 @@ -260,12 +260,12 @@ def newfloat(self, floatval): return W_FloatObject(self, floatval) - def newlong(self, uint): # for now just take a r_uint - if uint == 0: + def newlong(self, val): # val is an int + if val == 0: sign = 0 else: sign = 1 - return W_LongObject(self, [uint], sign) + return W_LongObject(self, [val], sign) def newtuple(self, list_w): assert isinstance(list_w, list) Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Sat Jul 23 02:26:27 2005 @@ -124,8 +124,8 @@ p = NumberStringParser(s, literal, base, 'long') else: p = parser - w_base = space.newlong(r_uint(p.base)) - w_result = space.newlong(r_uint(0)) + w_base = space.newlong(p.base) + w_result = space.newlong(0) while True: digit = p.next_digit() if digit == -1: @@ -135,7 +135,7 @@ from pypy.objspace.std.longobject import W_LongObject assert isinstance(w_result, W_LongObject) return w_result - w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) + w_result = space.add(space.mul(w_result,w_base), space.newlong(digit)) def break_up_float(s): i = 0 From pedronis at codespeak.net Sat Jul 23 02:27:30 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 02:27:30 +0200 (CEST) Subject: [pypy-svn] r14953 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050723002730.74FEC27B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 02:27:29 2005 New Revision: 14953 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/objspace/std/typeobject.py Log: have a fakedcpytype by default, avoid hasattr and the warnings in the rtyper. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Sat Jul 23 02:27:29 2005 @@ -19,6 +19,8 @@ self.hasdict |= __base.hasdict self.rawdict = rawdict self.acceptable_as_base_class = True + # xxx used by faking + self.fakedcpytype = None def _freeze_(self): # hint for the annotator: track individual constant instances of TypeDef Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Sat Jul 23 02:27:29 2005 @@ -258,7 +258,7 @@ return W_DictProxyObject(space, space.newdict(dictspec)) def unwrap(w_self): - if hasattr(w_self.instancetypedef, 'fakedcpytype'): + if w_self.instancetypedef.fakedcpytype is not None: return w_self.instancetypedef.fakedcpytype from pypy.objspace.std.model import UnwrapError raise UnwrapError(w_self) From pedronis at codespeak.net Sat Jul 23 02:28:04 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 02:28:04 +0200 (CEST) Subject: [pypy-svn] r14954 - pypy/dist/pypy/translator/goal Message-ID: <20050723002804.4A7A927B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 02:28:03 2005 New Revision: 14954 Modified: pypy/dist/pypy/translator/goal/module-list.pedronis Log: add recparser to the module list Modified: pypy/dist/pypy/translator/goal/module-list.pedronis ============================================================================== --- pypy/dist/pypy/translator/goal/module-list.pedronis (original) +++ pypy/dist/pypy/translator/goal/module-list.pedronis Sat Jul 23 02:28:03 2005 @@ -1,4 +1,5 @@ # +pypy.interpreter.pyparse pypy.objspace.std.listobject pypy.objspace.std.listobject:unwrap pypy.interpreter.argument From pedronis at codespeak.net Sat Jul 23 02:48:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 02:48:07 +0200 (CEST) Subject: [pypy-svn] r14955 - in pypy/branch/pypy-translation-snapshot: interpreter module objspace Message-ID: <20050723004807.45BE727B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 02:48:06 2005 New Revision: 14955 Removed: pypy/branch/pypy-translation-snapshot/interpreter/ pypy/branch/pypy-translation-snapshot/module/ pypy/branch/pypy-translation-snapshot/objspace/ Log: prepare for a new snapshot from the trunk From pedronis at codespeak.net Sat Jul 23 02:52:49 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 02:52:49 +0200 (CEST) Subject: [pypy-svn] r14956 - in pypy/branch/pypy-translation-snapshot: interpreter module objspace objspace/flow objspace/std Message-ID: <20050723005249.528F527B6D@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 02:52:47 2005 New Revision: 14956 Added: pypy/branch/pypy-translation-snapshot/interpreter/ - copied from r14951, pypy/dist/pypy/interpreter/ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py - copied unchanged from r14953, pypy/dist/pypy/interpreter/typedef.py pypy/branch/pypy-translation-snapshot/module/ - copied from r14951, pypy/dist/pypy/module/ pypy/branch/pypy-translation-snapshot/objspace/ - copied from r14951, pypy/dist/pypy/objspace/ pypy/branch/pypy-translation-snapshot/objspace/std/longtype.py - copied unchanged from r14952, pypy/dist/pypy/objspace/std/longtype.py pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py - copied unchanged from r14952, pypy/dist/pypy/objspace/std/objspace.py pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py - copied unchanged from r14952, pypy/dist/pypy/objspace/std/strutil.py pypy/branch/pypy-translation-snapshot/objspace/std/typeobject.py - copied unchanged from r14953, pypy/dist/pypy/objspace/std/typeobject.py Removed: pypy/branch/pypy-translation-snapshot/objspace/flow/ Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Log: new translation snapshot from the trunk Modified: pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/longobject.py Sat Jul 23 02:52:47 2005 @@ -63,7 +63,7 @@ # False == no checking at all # True == check 0 <= value <= MASK -CHECK_DIGITS = True +CHECK_DIGITS = False if CHECK_DIGITS: class DigitArray(list): From pedronis at codespeak.net Sat Jul 23 03:14:43 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 03:14:43 +0200 (CEST) Subject: [pypy-svn] r14957 - pypy/dist/pypy/translator/goal Message-ID: <20050723011443.9AE9D27B73@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 03:14:37 2005 New Revision: 14957 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: new list of rtyper problems on the fresh new snapshot. some problems are gone because there were already changes fixing them on the trunk, some new problems appeared because of new things that were only on ther trunk (pyparser, more extensive unicodedb...) Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Sat Jul 23 03:14:37 2005 @@ -6,216 +6,228 @@ * how to implement the three overrides of translator/ann_override.py ? + * a new snapshot (14956) of the trunk (which is again annotable has been made) + * current list of RTyper problems: + + TyperError-1: (pypy.interpreter.pyparser.grammar:match_token) + contains() on non-const tuple + .. block at 80 with 1 exits + .. v933696 = contains(v933690, v933668) + + TyperError-2: (pypy.interpreter.pyparser.pythonlexer:generate_tokens) + slice start must be proved non-negative + .. block at 1651 with 1 exits + .. v826009 = newslice(v825696, pos_825675, (None)) + + TyperError-3: (pypy.interpreter.pyparser.pythonlexer:generate_tokens) + slice stop must be proved non-negative + .. block at 269 with 1 exits + .. v808425 = newslice((None), pos_807666, (None)) + + TyperError-4: (pypy.interpreter.pyparser.tuplebuilder:sequence) + + .. block at 37 with 1 exits + .. v937261 = setitem(v937229, v937260, v937217) + + TyperError-5: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) + can only iterate over tuples of length 1 for now + .. block at 73 with 2 exits(v911582) + .. 'block-entry' + + TyperError-6: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) + can only iterate over tuples of length 1 for now + .. block at 64 with 2 exits(last_exception) + .. 'block-entry' - TyperError-1: (pypy.objspace.std.typeobject:unwrap) - don't know about built-in function - .. block at -1 EH with 2 exits(v701741) - .. v701737 = simple_call((builtin_function_or_method hasattr), v701728, ('fakedcpytype')) + TyperError-7: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) + can only iterate over tuples of length 1 for now + .. block at 63 with 1 exits + .. v911538 = iter((('latin-1', 'iso-lat...8859-1'))) - TyperError-3: (pypy.module.sys.vm:getrefcount) + TyperError-8: (pypy.objspace.std.listobject:unwrap) + no list() support for + .. block at 73 with 1 exits + .. v644424 = simple_call((type list), v644419) + + TyperError-9: (pypy.module.__builtin__.importing:load_part) + don't know about built-in function + .. block at 201 with 2 exits(v755595) + .. v755564 = simple_call((function isdir), v755527) + + TyperError-10: (pypy.module.__builtin__.importing:try_import_mod) + don't know about built-in function + .. block at -1 with 2 exits(v905077) + .. v905061 = simple_call((function exists), f_905031) + + TyperError-11: (pypy.module.sys.vm:getrefcount) don't know about built-in function .. block at -1 with 1 exits - .. v412138 = simple_call((builtin_function_or_method getrefcount), w_obj_412119) + .. v294775 = simple_call((builtin_function_or_method getrefcount), w_obj_294756) - TyperError-5: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v733701) - .. link from block at -1 to block at -1 + TyperError-12: (pypy.module.unicodedata.function:normalize) + cannot make repr of + .. block at 1498 with 2 exits(last_exception) + .. v389623 = getitem(({(104, 770): 293, (6...8): 366}), v389526) + + TyperError-13: (pypy.module.unicodedata.unicodedb:name) + unimplemented operation: 'divmod' on (, ) + .. block at 170 EH with 1 exits + .. v885420 = divmod(v885413, (21)) + + TyperError-14: (pypy.module.unicodedata.unicodedb:name) + unimplemented operation: 'divmod' on (, ) + .. block at 157 with 1 exits + .. v885379 = divmod(v885353, (28)) - TyperError-6: (pypy.objspace.std.sliceobject:unwrap) - don't know about built-in function - .. block at -1 with 1 exits - .. v702025 = simple_call((type slice), v701937, v701973, v702012) + TyperError-15: (pypy.objspace.std.fake:fake__new__) + don't know about built-in function + .. block at 145 with 1 exits + .. v314219 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v314191, v314192) + + TyperError-16: (pypy.objspace.std.fake:setfastscope) + ll_str unsupported for: + .. block at 118 with 1 exits + .. v339770 = mod(('calling %s: %s'), v339759) - TyperError-8: (pypy.objspace.std.fake:fake__new__) - missing PyObjRepr.rtype_method_append - .. block at 44 with 1 exits - .. v521685 = simple_call(_1_521602, v521650) + TyperError-17: (pypy.objspace.std.fake:run) + don't know about built-in function + .. block at 62 with 1 exits + .. v342110 = simple_call((builtin_function_or_method apply), v342092, v342093, v342094) - TyperError-10: (pypy.objspace.std.objspace:wrap__object) - no list() support for - .. block at 446 with 1 exits - .. v733690 = simple_call((type list), x_733593) + TyperError-18: (pypy.objspace.std.fake:fake__new__) + don't know about built-in function + .. block at 145 with 1 exits + .. v501617 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v501589, v501590) - TyperError-11: (pypy.module.__builtin__.compiling:compile) - call_specialcase: unknown tag override:cpy_compile - .. block at 161 with 1 exits - .. v549464 = call_specialcase(v549422, str__549335, filename_549331, mode_549332, flags_549333) - - TyperError-12: (pypy.module.__builtin__.importing:load_part) - don't know about built-in function - .. block at 201 with 2 exits(v769301) - .. v769270 = simple_call((function isdir), v769233) + TyperError-19: (pypy.objspace.std.floatobject:hash__Float) + unimplemented operation: 'hash' on + .. block at -1 with 1 exits + .. v436008 = hash(v435997) - TyperError-13: (pypy.objspace.std.longobject:_FromDouble) + TyperError-20: (pypy.objspace.std.longobject:_FromDouble) don't know about built-in function .. block at 245 with 1 exits - .. v677356 = simple_call((builtin_function_or_method ldexp), v677334, (15)) + .. v441291 = simple_call((builtin_function_or_method ldexp), v441269, (15)) - TyperError-14: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:fake_object - .. block at 870 with 1 exits - .. v734154 = call_specialcase((function fake_object), v734137, v734138) - - TyperError-16: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:wrap_exception_cls - .. block at 811 with 2 exits(v734217) - .. v734191 = call_specialcase(v734159, x_734142) - - TyperError-18: (pypy.objspace.std.longobject:longval) - don't know about built-in function - .. block at 50 with 1 exits - .. v723409 = simple_call((type long), d_723372) + TyperError-21: (pypy.objspace.std.longobject:_long_true_divide) + don't know about built-in function + .. block at 183 with 1 exits + .. v489794 = simple_call((builtin_function_or_method ldexp), v489730, v489754) - TyperError-19: (pypy.objspace.std.longobject:_FromDouble) + TyperError-22: (pypy.objspace.std.longobject:_FromDouble) don't know about built-in function .. block at 143 with 1 exits - .. v677171 = simple_call((builtin_function_or_method ldexp), frac_676983, v677155) + .. v441106 = simple_call((builtin_function_or_method ldexp), frac_440918, v441090) - TyperError-21: (pypy.objspace.std.tupleobject:unwrap) - don't know about built-in function - .. block at 66 with 1 exits - .. v702466 = simple_call((type tuple), v702461) - - TyperError-23: (pypy.objspace.std.objspace:unwrap) - unimplemented operation: 'mod' on (, ) - .. block at 63 with 1 exits - .. v586013 = mod(('cannot unwrap: %r'), v586007) + TyperError-23: (pypy.objspace.std.longobject:_AsDouble) + don't know about built-in function + .. block at 53 with 1 exits + .. v610741 = simple_call((builtin_function_or_method ldexp), v610725, v610729) - TyperError-24: (pypy.module.unicodedata.unicodedb:bidirectional) - non-constant tuple index - .. block at -1 EH with 1 exits - .. v703906 = getitem((('\x04\x04\x04\x04\x...00\x00')), v703902) + TyperError-24: (pypy.objspace.std.longobject:longval) + don't know about built-in function + .. block at 50 with 1 exits + .. v692507 = simple_call((type long), d_692470) - TyperError-25: (pypy.objspace.std.unicodeobject:unwrap) - don't know how to convert from to - .. block at -1 with 1 exits - .. v701468 = simple_call((builtin_function_or_method join), v701459) + TyperError-25: (pypy.objspace.std.longobject:_FromDouble) + don't know about built-in function + .. block at 89 with 1 exits + .. v440853 = simple_call((builtin_function_or_method frexp), v440842) - TyperError-26: (pypy.module.__builtin__.importing:try_import_mod) - don't know about built-in function - .. block at -1 with 2 exits(v799443) - .. v799427 = simple_call((function exists), f_799397) + TyperError-26: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v736063) + .. link from block at -1 to block at -1 - TyperError-27: (pypy.objspace.std.fake:fake__new__) - don't know about built-in function - .. block at 145 with 1 exits - .. v643239 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v643211, v643212) + TyperError-27: (pypy.objspace.std.objspace:wrap__object) + no unichr() support for + .. block at 265 with 1 exits + .. v735961 = simple_call((builtin_function_or_method unichr), v735931) - TyperError-28: (pypy.objspace.std.fake:fake__new__) - don't know about built-in function - .. block at 145 with 1 exits - .. v521832 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v521804, v521805) + TyperError-28: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v736503) + .. link from block at -1 to block at -1 - TyperError-29: (pypy.objspace.std.listobject:unwrap) + TyperError-29: (pypy.objspace.std.objspace:wrap__object) no list() support for - .. block at 73 with 1 exits - .. v701590 = simple_call((type list), v701585) + .. block at 446 with 1 exits + .. v736052 = simple_call((type list), x_735955) - TyperError-30: (pypy.interpreter.executioncontext:__init__) - cannot create non-StrDicts, got - .. block at -1 with 1 exits - .. v371306 = newdict() + TyperError-30: (pypy.objspace.std.objspace:unwrap) + don't know how to convert from to + .. block at -1 EH with 2 exits(v502133) + .. link from block at -1 EH to codeless block - TyperError-31: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v733237) + TyperError-31: (pypy.objspace.std.objspace:unwrap) + unimplemented operation: 'mod' on (, ) + .. block at 63 with 1 exits + .. v502156 = mod(('cannot unwrap: %r'), v502150) + + TyperError-32: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v735576) .. link from block at -1 to block at -1 - TyperError-33: (pypy.objspace.std.fake:fake__new__) - missing PyObjRepr.rtype_method_append - .. block at 44 with 1 exits - .. v643092 = simple_call(_1_643009, v643057) + TyperError-33: (pypy.objspace.std.objspace:wrap__object) + call_specialcase: unknown tag override:fake_object + .. block at 945 with 1 exits + .. v736591 = call_specialcase((function fake_object), v736570, v736571) TyperError-34: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v733214) + don't know how to convert from to + .. block at -1 with 2 exits(v735599) .. link from block at -1 to block at -1 TyperError-35: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v734039) - .. link from block at -1 to block at -1 + don't know how to convert from to + .. block at -1 with 2 exits(v736550) + .. link from block at -1 to block at 945 TyperError-36: (pypy.objspace.std.objspace:wrap__object) - no unichr() support for - .. block at 265 with 1 exits - .. v733599 = simple_call((builtin_function_or_method unichr), v733569) - - TyperError-37: (pypy.objspace.std.longobject:_AsDouble) - don't know about built-in function - .. block at 53 with 1 exits - .. v628723 = simple_call((builtin_function_or_method ldexp), v628707, v628711) - - TyperError-38: (pypy.objspace.std.longobject:_x_divrem) - comparing a signed and an unsigned number - .. block at 709 with 2 exits(v742285) - .. v742180 = eq(v742103, (-1)) - - TyperError-39: (pypy.module.unicodedata.unicodedb:category) - non-constant tuple index - .. block at -1 EH with 1 exits - .. v655549 = getitem((('\x00\x00\x00\x00\x...02\x02')), v655545) - - TyperError-41: (pypy.objspace.std.objspace:unwrap) - don't know how to convert from to - .. block at -1 EH with 2 exits(v585990) - .. link from block at -1 EH to codeless block - - TyperError-42: (pypy.objspace.std.longobject:_FromDouble) - don't know about built-in function - .. block at 89 with 1 exits - .. v676918 = simple_call((builtin_function_or_method frexp), v676907) + call_specialcase: unknown tag override:wrap_exception_cls + .. block at 886 with 2 exits(v736673) + .. v736633 = call_specialcase(v736596, x_736575) - TyperError-45: (pypy.objspace.std.fake:setfastscope) - ll_str unsupported for: - .. block at 118 with 1 exits - .. v469272 = mod(('calling %s: %s'), v469261) + TyperError-37: (pypy.objspace.std.sliceobject:unwrap) + don't know about built-in function + .. block at -1 with 1 exits + .. v643574 = simple_call((type slice), v643486, v643522, v643561) - TyperError-46: (pypy.objspace.std.longobject:_long_true_divide) - don't know about built-in function - .. block at 183 with 1 exits - .. v437078 = simple_call((builtin_function_or_method ldexp), v437014, v437038) + TyperError-38: (pypy.objspace.std.tupleobject:unwrap) + don't know about built-in function + .. block at 66 with 1 exits + .. v643722 = simple_call((type tuple), v643717) - TyperError-48: (pypy.objspace.std.tupleobject:unwrap) - missing PyObjRepr.rtype_method_append - .. block at 38 with 1 exits - .. v702495 = simple_call(_1_702450, v702479) + TyperError-39: (pypy.objspace.std.unicodeobject:unwrap) + don't know how to convert from to + .. block at -1 with 1 exits + .. v644571 = simple_call((builtin_function_or_method join), v644562) - TyperError-49: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) + TyperError-40: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) cannot make repr of - .. block at 185 with 2 exits(v550361) - .. v550336 = contains(((u'+', u'-')), v550296) - - TyperError-50: (pypy.objspace.std.listobject:unwrap) - missing PyObjRepr.rtype_method_append - .. block at 45 with 1 exits - .. v701619 = simple_call(_1_701574, v701603) - - TyperError-51: (pypy.objspace.std.fake:run) - don't know about built-in function - .. block at 62 with 1 exits - .. v469642 = simple_call((builtin_function_or_method apply), v469624, v469625, v469626) - - TyperError-53: (pypy.objspace.std.floatobject:hash__Float) - unimplemented operation: 'hash' on - .. block at -1 with 1 exits - .. v545132 = hash(v545121) + .. block at 185 with 2 exits(v750416) + .. v750391 = contains(((u'+', u'-')), v750351) - TyperError-54: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v734102) - .. link from block at -1 to block at 870 + TyperError-41: (pypy.module.recparser.pyparser:visit_syntaxnode) + inconsistent type for the result of 'getitem': + annotator says SomeList(listdef=), + whose repr is * GcStruct object { ... } } } } }> + but rtype_getitem returned <* GcStruct list { items: * GcArray of * GcStruct W_TupleObject { super: GcStruct W_Object { super: GcStruct W_Root { super: GcStruct object { typeptr: * Struct object_vtable { parenttypeptr: * Struct object_vtable { ... }, rtti: * RuntimeTypeInfo (opaque), name: * Array of Char , instantiate: * Func ( ) -> * GcStruct object { ... } } } }, inst_space: Void }, inst_wrappeditems: * GcStruct list { items: * GcArray of * GcStruct W_Root { super: GcStruct object { typeptr: * Struct object_vtable { parenttypeptr: * Struct object_vtable { ... }, rtti: * RuntimeTypeInfo (opaque), name: * Array of Char , instantiate: * Func ( ) -> * GcStruct object { ... } } } } } } }> + .. block at 48 with 1 exits + .. v714944 = getitem(v714920, v714943) + + TyperError-42: (pypy.interpreter.pycompiler:compile) + call_specialcase: unknown tag override:cpy_stablecompiler + .. block at 156 with 1 exits + .. v730727 = call_specialcase(v730690, parse_result_730673, filename_730669, mode_730670) - TyperError-55: (pypy.objspace.std.unicodeobject:repr__Unicode) - don't know how to convert from to + TyperError-43: (pypy.rpython.rarithmetic:ovfcheck_float_to_int) + don't know about built-in function .. block at -1 with 1 exits - .. v642230 = simple_call((builtin_function_or_method join), v642219) + .. v911394 = simple_call((builtin_function_or_method modf), x_911387) - * the pypy trunk is still not annotable: - - see issue92 about parser typing problems - progress has been made on this How to work in parallel: There is an environment variable to be set with your personal random seed. From pedronis at codespeak.net Sat Jul 23 03:18:40 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 23 Jul 2005 03:18:40 +0200 (CEST) Subject: [pypy-svn] r14958 - pypy/dist/pypy/translator/goal Message-ID: <20050723011840.0D79A27B73@code1.codespeak.net> Author: pedronis Date: Sat Jul 23 03:18:36 2005 New Revision: 14958 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: typo Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Sat Jul 23 03:18:36 2005 @@ -6,7 +6,7 @@ * how to implement the three overrides of translator/ann_override.py ? - * a new snapshot (14956) of the trunk (which is again annotable has been made) + * a new snapshot (14956) of the trunk (which is again annotable) has been made * current list of RTyper problems: From ericvrp at codespeak.net Sat Jul 23 23:33:33 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Jul 2005 23:33:33 +0200 (CEST) Subject: [pypy-svn] r14965 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050723213333.4649527B6C@code1.codespeak.net> Author: ericvrp Date: Sat Jul 23 23:33:32 2005 New Revision: 14965 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: Starting to use invoke for last direct_call in 'try' block. Not finished yet. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 23 23:33:32 2005 @@ -98,6 +98,15 @@ arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] self.indent("call void %s(%s)" % (functionref, ", ".join(arglist))) + def invoke(self, targetvar, returntype, functionref, argrefs, argtypes, label, except_label): + arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] + self.indent("%s = invoke %s %s(%s) to label %s except label %s" % (targetvar, returntype, functionref, + ", ".join(arglist), label, except_label)) + + def invoke_void(self, functionref, argrefs, argtypes, label, except_label): + arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] + self.indent("invoke void %s(%s) to label %s except label %s" % (functionref, ", ".join(arglist), label, except_label)) + def cast(self, targetvar, fromtype, fromvar, targettype): self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 23 23:33:32 2005 @@ -1,6 +1,6 @@ import py from pypy.objspace.flow.model import Block, Constant, Variable, Link -from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.objspace.flow.model import flatten, mkentrymap, traverse, last_exception from pypy.rpython import lltype from pypy.translator.backendoptimization import remove_same_as from pypy.translator.unsimplify import remove_double_links @@ -126,6 +126,12 @@ codewriter.phi(arg, type_, names, blocknames) def write_block_branches(self, codewriter, block): + + #BLOCK.EXITS[%fn]=3 ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__slots__', '__str__', 'at', 'closeblock', 'dead', 'exc_handler', 'exits', 'exitswitch', 'fillcolor', 'framestate', 'getconstants', 'getvariables', 'inputargs', 'isstartblock', 'operations', 'patchframe', 'recloseblock', 'renamevariables' + + print 'BLOCK.EXITS[%s], exitswitch=%s' % (self.ref, str(block.exitswitch)) + + #assert len(block.exits) <= 2 #more exits are possible (esp. in combination with exceptions) if len(block.exits) == 1: codewriter.br_uncond(self.block_to_name[block.exits[0].target]) elif len(block.exits) == 2: @@ -135,9 +141,18 @@ def write_block_operations(self, codewriter, block): opwriter = OpWriter(self.db, codewriter) - for op in block.operations: + last_direct_call = -1 + if block.exitswitch == Constant(last_exception): + for op_index, op in enumerate(block.operations): + if op.opname == 'direct_call': + last_direct_call = op_index + for op_index, op in enumerate(block.operations): codewriter.comment(str(op), indent=True) - opwriter.write_operation(op) + opname = op.opname + if op_index == last_direct_call: + opname = 'direct_invoke' + opwriter.write_operation(op, opname) + def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) self.write_block_branches(codewriter, block) @@ -162,10 +177,10 @@ t = 'long' #void* tmpvar = self.db.repr_tmpvar() codewriter.cast(tmpvar, inputargtypes[0], inputargs[0], t) - codewriter.store(t, tmpvar, 'last_exception_type') + codewriter.store(t, tmpvar, '%last_exception_type') tmpvar = self.db.repr_tmpvar() codewriter.cast(tmpvar, inputargtypes[1], inputargs[1], t) - codewriter.store(t, tmpvar, 'last_exception_value') + codewriter.store(t, tmpvar, '%last_exception_value') codewriter.unwind() Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 23 23:33:32 2005 @@ -75,14 +75,16 @@ self.db = db self.codewriter = codewriter - def write_operation(self, op): - if op.opname in self.binary_operations: + def write_operation(self, op, opname=None): + if not opname: + opname = op.opname + if opname in self.binary_operations: self.binaryop(op) - elif op.opname in self.shift_operations: + elif opname in self.shift_operations: self.shiftop(op) else: - meth = getattr(self, op.opname, None) - assert meth is not None, "operation %r not found" %(op.opname,) + meth = getattr(self, opname, None) + assert meth is not None, "operation %r not found" %(opname,) meth(op) def int_neg(self, op): @@ -180,6 +182,19 @@ else: self.codewriter.call_void(functionref, argrefs, argtypes) + def direct_invoke(self, op): + assert len(op.args) >= 1 + targetvar = self.db.repr_arg(op.result) + returntype = self.db.repr_arg_type(op.result) + functionref = self.db.repr_arg(op.args[0]) + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) + if returntype != "void": + self.codewriter.invoke(targetvar, returntype, functionref, argrefs, + argtypes, 'PYPY_LABEL', 'PYPY_EXCEPT_LABEL') + else: + self.codewriter.invoke_void(functionref, argrefs, argtypes, 'PYPY_LABEL', 'PYPY_EXCEPT_LABEL') + def malloc(self, op): targetvar = self.db.repr_arg(op.result) arg = op.args[0] Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sat Jul 23 23:33:32 2005 @@ -9,16 +9,20 @@ self.n = n def test_simple1(): + import time def raise_(i): if i: raise TestException() else: - return 1 + return 3 def fn(i): try: - return raise_(i) + a = time.time() + raise_(i) + 11 + b = time.time() + raise_(i) + 12 + c = time.time() + raise_(i) + 13 + return a+b+c except TestException: - return 0 + return 7 f = compile_function(fn, [int]) assert f(0) == fn(0) assert f(1) == fn(1) From ericvrp at codespeak.net Sun Jul 24 17:34:50 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 24 Jul 2005 17:34:50 +0200 (CEST) Subject: [pypy-svn] r14987 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050724153450.05C8127B56@code1.codespeak.net> Author: ericvrp Date: Sun Jul 24 17:34:50 2005 New Revision: 14987 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: Moving stuff to other computer and avoiding long time between checkins Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 24 17:34:50 2005 @@ -100,12 +100,12 @@ def invoke(self, targetvar, returntype, functionref, argrefs, argtypes, label, except_label): arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] - self.indent("%s = invoke %s %s(%s) to label %s except label %s" % (targetvar, returntype, functionref, + self.indent("%s = invoke %s %s(%s) to label %%%s except label %%%s" % (targetvar, returntype, functionref, ", ".join(arglist), label, except_label)) def invoke_void(self, functionref, argrefs, argtypes, label, except_label): arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] - self.indent("invoke void %s(%s) to label %s except label %s" % (functionref, ", ".join(arglist), label, except_label)) + self.indent("invoke void %s(%s) to label %%%s except label %%%s" % (functionref, ", ".join(arglist), label, except_label)) def cast(self, targetvar, fromtype, fromvar, targettype): self.indent("%(targetvar)s = cast %(fromtype)s " Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 24 17:34:50 2005 @@ -150,7 +150,9 @@ codewriter.comment(str(op), indent=True) opname = op.opname if op_index == last_direct_call: - opname = 'direct_invoke' + opname = 'direct_invoke' #XXX or can op.opname be overwritten? + opwriter.node = self #XXX or make all operations know their node? + opwriter.block = block #XXX or make all operations know their block? opwriter.write_operation(op, opname) def write_startblock(self, codewriter, block): Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sun Jul 24 17:34:50 2005 @@ -7,7 +7,7 @@ from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -#from pypy.rpython.extfunctable import table as extfunctable +nextexclabel = py.std.itertools.count().next log = log.opwriter class OpWriter(object): @@ -189,11 +189,23 @@ functionref = self.db.repr_arg(op.args[0]) argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) + + link = self.block.exits[0] + assert link.exitcase is None + label = self.node.block_to_name[link.target] + + assert len(self.block.exits) > 1 + link = self.block.exits[1] #XXX need an additional block if we catch multiple exc.types! + exc_label = self.node.block_to_name[link.target] + #exc_label = 'exception_block.%d' % nextexclabel() + if returntype != "void": self.codewriter.invoke(targetvar, returntype, functionref, argrefs, - argtypes, 'PYPY_LABEL', 'PYPY_EXCEPT_LABEL') + argtypes, label, exc_label) else: - self.codewriter.invoke_void(functionref, argrefs, argtypes, 'PYPY_LABEL', 'PYPY_EXCEPT_LABEL') + self.codewriter.invoke_void(functionref, argrefs, argtypes, label, exc_label) + + #self.codewriter.label(exc_label) def malloc(self, op): targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sun Jul 24 17:34:50 2005 @@ -9,7 +9,6 @@ self.n = n def test_simple1(): - import time def raise_(i): if i: raise TestException() @@ -17,9 +16,9 @@ return 3 def fn(i): try: - a = time.time() + raise_(i) + 11 - b = time.time() + raise_(i) + 12 - c = time.time() + raise_(i) + 13 + a = raise_(i) + 11 + b = raise_(i) + 12 + c = raise_(i) + 13 return a+b+c except TestException: return 7 From arigo at codespeak.net Sun Jul 24 18:40:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 24 Jul 2005 18:40:13 +0200 (CEST) Subject: [pypy-svn] r14989 - in pypy/dist/pypy: annotation interpreter/pyparser rpython translator Message-ID: <20050724164013.5E42427B60@code1.codespeak.net> Author: arigo Date: Sun Jul 24 18:40:03 2005 New Revision: 14989 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/translator/unsimplify.py Log: Minor annotation-related fixes. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sun Jul 24 18:40:03 2005 @@ -413,7 +413,8 @@ class __extend__(pairtype(SomeList, SomeInteger)): def mul((lst1, int2)): - return getbookkeeper().newlist(lst1.listdef.read_item()) + #return getbookkeeper().newlist(lst1.listdef.read_item()) + return SomeList(lst1.listdef) def getitem((lst1, int2)): getbookkeeper().count("list_getitem", int2) @@ -431,7 +432,8 @@ class __extend__(pairtype(SomeList, SomeSlice)): def getitem((lst, slic)): - return getbookkeeper().newlist(lst.listdef.read_item()) + #return getbookkeeper().newlist(lst.listdef.read_item()) + return SomeList(lst.listdef) def setitem((lst, slic), s_iterable): # we need the same unifying effect as the extend() method for @@ -465,7 +467,8 @@ class __extend__(pairtype(SomeInteger, SomeList)): def mul((int1, lst2)): - return getbookkeeper().newlist(lst2.listdef.read_item()) + #return getbookkeeper().newlist(lst2.listdef.read_item()) + return SomeList(lst2.listdef) class __extend__(pairtype(SomeInstance, SomeInstance)): Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Sun Jul 24 18:40:03 2005 @@ -61,7 +61,7 @@ encoding = encoding.replace('_', '-').lower() if encoding.startswith('utf-8'): return 'utf-8' - for variant in ('latin-1', 'iso-latin-1', 'iso-8859-1'): + for variant in ['latin-1', 'iso-latin-1', 'iso-8859-1']: if encoding.startswith(variant): return 'iso-8859-1' return encoding Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jul 24 18:40:03 2005 @@ -218,7 +218,7 @@ if r_slic == minusone_slice_repr: v_lst, v_ignored = hop.inputargs(r_lst, minusone_slice_repr) return hop.gendirectcall(ll_listslice_minusone, v_lst) - raise TyperError(r_slic) + raise TyperError('getitem does not support slices with %r' % (r_slic,)) def rtype_setitem((r_lst, r_slic), hop): #if r_slic == startonly_slice_repr: @@ -228,7 +228,7 @@ r_lst) hop.gendirectcall(ll_listsetslice, v_lst, v_slice, v_lst2) return - raise TyperError(r_slic) + raise TyperError('setitem does not support slices with %r' % (r_slic,)) def rtype_delitem((r_lst, r_slic), hop): if r_slic == startonly_slice_repr: @@ -239,7 +239,7 @@ v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr) hop.gendirectcall(ll_listdelslice, v_lst, v_slice) return - raise TyperError(r_slic) + raise TyperError('delitem does not support slices with %r' % (r_slic,)) class __extend__(pairtype(ListRepr, ListRepr)): def convert_from_to((r_lst1, r_lst2), v, llops): Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Sun Jul 24 18:40:03 2005 @@ -14,7 +14,16 @@ def insert_empty_block(translator, link, newops=[]): """Insert and return a new block along the given link.""" - vars = uniqueitems([v for v in link.args if isinstance(v, Variable)]) + vars = {} + for v in link.args: + if isinstance(v, Variable): + vars[v] = True + for op in newops: + for v in op.args: + if isinstance(v, Variable): + vars.setdefault(v, True) + vars[op.result] = False + vars = [v for v, keep in vars.items() if keep] mapping = {} for v in vars: mapping[v] = copyvar(translator, v) From arigo at codespeak.net Sun Jul 24 18:43:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 24 Jul 2005 18:43:58 +0200 (CEST) Subject: [pypy-svn] r14990 - pypy/branch/pypy-translation-snapshot/interpreter/pyparser Message-ID: <20050724164358.830B327B60@code1.codespeak.net> Author: arigo Date: Sun Jul 24 18:43:58 2005 New Revision: 14990 Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py Log: Merged trunk rev 14989. Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py Sun Jul 24 18:43:58 2005 @@ -61,7 +61,7 @@ encoding = encoding.replace('_', '-').lower() if encoding.startswith('utf-8'): return 'utf-8' - for variant in ('latin-1', 'iso-latin-1', 'iso-8859-1'): + for variant in ['latin-1', 'iso-latin-1', 'iso-8859-1']: if encoding.startswith(variant): return 'iso-8859-1' return encoding From ericvrp at codespeak.net Mon Jul 25 00:09:19 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 25 Jul 2005 00:09:19 +0200 (CEST) Subject: [pypy-svn] r14992 - pypy/dist/pypy/translator/c/test Message-ID: <20050724220919.AEFED27B60@code1.codespeak.net> Author: ericvrp Date: Mon Jul 25 00:09:19 2005 New Revision: 14992 Modified: pypy/dist/pypy/translator/c/test/test_exception.py Log: Added a failing exception test. The 'main' block has a KeyError and IndexError exit, but there is never an exception raised Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Mon Jul 25 00:09:19 2005 @@ -5,6 +5,23 @@ class MyException(Exception): pass +def test_simple2(): #taken from ../../llvm2/test/test_exception.py + def fn(n): + lst = range(10) + try: + lst[n] + except: + return 2 + return 4 + t = Translator(fn) + t.annotate([int]).simplify() + t.specialize() + #t.view() + f = t.ccompile() + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == fn(10) + def test_myexception(): def g(): raise MyException From ericvrp at codespeak.net Mon Jul 25 00:13:13 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 25 Jul 2005 00:13:13 +0200 (CEST) Subject: [pypy-svn] r14993 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050724221313.DD6B727B60@code1.codespeak.net> Author: ericvrp Date: Mon Jul 25 00:13:12 2005 New Revision: 14993 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/opwriter.py Log: Some more exception implementation. Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Mon Jul 25 00:13:12 2005 @@ -112,7 +112,6 @@ self.write_block_operations(codewriter, block) self.write_block_branches(codewriter, block) - def write_block_phi_nodes(self, codewriter, block): entrylinks = mkentrymap(self.graph)[block] entrylinks = [x for x in entrylinks if x.prevblock is not None] @@ -126,11 +125,6 @@ codewriter.phi(arg, type_, names, blocknames) def write_block_branches(self, codewriter, block): - - #BLOCK.EXITS[%fn]=3 ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__slots__', '__str__', 'at', 'closeblock', 'dead', 'exc_handler', 'exits', 'exitswitch', 'fillcolor', 'framestate', 'getconstants', 'getvariables', 'inputargs', 'isstartblock', 'operations', 'patchframe', 'recloseblock', 'renamevariables' - - print 'BLOCK.EXITS[%s], exitswitch=%s' % (self.ref, str(block.exitswitch)) - #assert len(block.exits) <= 2 #more exits are possible (esp. in combination with exceptions) if len(block.exits) == 1: codewriter.br_uncond(self.block_to_name[block.exits[0].target]) @@ -139,21 +133,21 @@ codewriter.br(switch, self.block_to_name[block.exits[0].target], self.block_to_name[block.exits[1].target]) + def _last_operation(self, block, opname): + last_index = None + for op_index, op in enumerate(block.operations): + if op.opname == opname: + last_index = op_index + return last_index + def write_block_operations(self, codewriter, block): - opwriter = OpWriter(self.db, codewriter) - last_direct_call = -1 - if block.exitswitch == Constant(last_exception): - for op_index, op in enumerate(block.operations): - if op.opname == 'direct_call': - last_direct_call = op_index + opwriter = OpWriter(self.db, codewriter, self, block) + last_direct_call_index = self._last_operation(block, 'direct_call') for op_index, op in enumerate(block.operations): codewriter.comment(str(op), indent=True) - opname = op.opname - if op_index == last_direct_call: - opname = 'direct_invoke' #XXX or can op.opname be overwritten? - opwriter.node = self #XXX or make all operations know their node? - opwriter.block = block #XXX or make all operations know their block? - opwriter.write_operation(op, opname) + if op_index == last_direct_call_index and block.exitswitch == Constant(last_exception): + op.opname = 'direct_invoke' + opwriter.write_operation(op) def write_startblock(self, codewriter, block): self.write_block_operations(codewriter, block) @@ -169,20 +163,37 @@ else: codewriter.ret_void() + def _is_raise_new_exception(self, block): + is_raise_new = False + entrylinks = mkentrymap(self.graph)[block] + entrylinks = [x for x in entrylinks if x.prevblock is not None] + inputargs = self.db.repr_arg_multi(block.inputargs) + for i, arg in enumerate(inputargs): + names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) + for name in names: #These tests-by-name are a bit yikes, but I don't see a better way right now + if not name.startswith('%last_exception_') and not name.startswith('%last_exc_value_'): + is_raise_new = True + return is_raise_new + def write_exceptblock(self, codewriter, block): assert len(block.inputargs) == 2 - self.write_block_phi_nodes(codewriter, block) - inputargs = self.db.repr_arg_multi(block.inputargs) - inputargtypes = self.db.repr_arg_type_multi(block.inputargs) - #XXX add pending last_exception global here - t = 'long' #void* - tmpvar = self.db.repr_tmpvar() - codewriter.cast(tmpvar, inputargtypes[0], inputargs[0], t) - codewriter.store(t, tmpvar, '%last_exception_type') - - tmpvar = self.db.repr_tmpvar() - codewriter.cast(tmpvar, inputargtypes[1], inputargs[1], t) - codewriter.store(t, tmpvar, '%last_exception_value') + if self._is_raise_new_exception(block): + self.write_block_phi_nodes(codewriter, block) + + inputargs = self.db.repr_arg_multi(block.inputargs) + inputargtypes = self.db.repr_arg_type_multi(block.inputargs) + + tmptype, tmpvar = 'long', self.db.repr_tmpvar() + codewriter.cast(tmpvar, inputargtypes[0], inputargs[0], tmptype) + codewriter.store(tmptype, tmpvar, '%last_exception_type') + + tmptype, tmpvar = 'long', self.db.repr_tmpvar() + codewriter.cast(tmpvar, inputargtypes[1], inputargs[1], tmptype) + codewriter.store(tmptype, tmpvar, '%last_exception_value') + #else: + # Reraising last_exception. + # Which is already stored in the global variables. + # So nothing needs to happen here! codewriter.unwind() Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Mon Jul 25 00:13:12 2005 @@ -71,20 +71,20 @@ 'uint_rshift': 'shr', } - def __init__(self, db, codewriter): + def __init__(self, db, codewriter, node, block): self.db = db self.codewriter = codewriter + self.node = node + self.block = block - def write_operation(self, op, opname=None): - if not opname: - opname = op.opname - if opname in self.binary_operations: + def write_operation(self, op): + if op.opname in self.binary_operations: self.binaryop(op) - elif opname in self.shift_operations: + elif op.opname in self.shift_operations: self.shiftop(op) else: - meth = getattr(self, opname, None) - assert meth is not None, "operation %r not found" %(opname,) + meth = getattr(self, op.opname, None) + assert meth is not None, "operation %r not found" %(op.opname,) meth(op) def int_neg(self, op): @@ -197,6 +197,11 @@ assert len(self.block.exits) > 1 link = self.block.exits[1] #XXX need an additional block if we catch multiple exc.types! exc_label = self.node.block_to_name[link.target] + + if len(self.block.exits) > 2: + msg = 'XXX Exception handling incomplete implementation warning: n_exits=%d' % (len(self.block.exits),) + print msg + self.codewriter.comment(msg, indent=True) #exc_label = 'exception_block.%d' % nextexclabel() if returntype != "void": From adim at codespeak.net Mon Jul 25 11:03:09 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 11:03:09 +0200 (CEST) Subject: [pypy-svn] r14995 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050725090309.1A58F27B55@code1.codespeak.net> Author: adim Date: Mon Jul 25 11:03:07 2005 New Revision: 14995 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: implemented func calls (+ tests) The hack for now is to have a ArglistObject (extending ast.Node) class and to use a temporary instance of this class during Ast building. Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 11:03:07 2005 @@ -107,8 +107,11 @@ L = get_atoms( builder, nb ) if len(L) == 1: builder.push( L[0] ) + elif len(L) == 2: + arguments, stararg, dstararg = L[1].value + builder.push(ast.CallFunc(L[0], arguments, stararg, dstararg)) elif len(L) == 3: - builder.push( ast.Power( [ L[0], L[2] ] ) ) + builder.push(ast.Power([L[0], L[2]])) else: raise ValueError, "unexpected tokens: %s" % L @@ -326,11 +329,70 @@ def build_lambdef(builder, nb): L = get_atoms(builder, nb) - print "L:", L code = L[-1] names, defaults, flags = parse_arglist(L[1:-2]) builder.push(ast.Lambda(names, defaults, flags, code)) + +def build_trailer(builder, nb): + """trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME + """ + L = get_atoms(builder, nb) + # Case 1 : '(' ... + if L[0].name == tok.LPAR: + if len(L) == 2: # and L[1].token == tok.RPAR: + builder.push(ArglistObject('arglist', ([], None, None), None)) + elif len(L) == 3: # '(' Arglist ')' + # push arglist on the stack + builder.push(L[1]) + else: + assert False, "Trailer reducing implementation incomplete !" + +def build_arglist(builder, nb): + L = get_atoms(builder, nb) + builder.push(ArglistObject('arglist', parse_argument(L), None)) + + +def parse_argument(tokens): + """parses function call arguments""" + l = len(tokens) + index = 0 + arguments = [] + last_token = None + building_kw = False + kw_built = False + stararg_token = None + dstararg_token = None + while index < l: + cur_token = tokens[index] + index += 1 + if not isinstance(cur_token, TokenObject): + if not building_kw: + arguments.append(cur_token) + elif kw_built: + raise SyntaxError("non-keyword arg after keyword arg (%s)" % (cur_token)) + else: + last_token = arguments.pop() + assert isinstance(last_token, ast.Name) # used by rtyper + arguments.append(ast.Keyword(last_token.name, cur_token)) + building_kw = False + kw_built = True + elif cur_token.name == tok.COMMA: + continue + elif cur_token.name == tok.EQUAL: + building_kw = True + continue + elif cur_token.name == tok.STAR or cur_token.name == tok.DOUBLESTAR: + if cur_token.name == tok.STAR: + stararg_token = tokens[index] + index += 1 + if index >= l: + break + index += 2 # Skip COMMA and DOUBLESTAR + dstararg_token = tokens[index] + break + return arguments, stararg_token, dstararg_token + def parse_arglist(tokens): """returns names, defaults, flags""" l = len(tokens) @@ -404,6 +466,8 @@ sym.testlist_gexp : build_testlist_gexp, sym.lambdef : build_lambdef, sym.varargslist : build_varargslist, + sym.trailer : build_trailer, + sym.arglist : build_arglist, } class RuleObject(ast.Node): @@ -430,15 +494,31 @@ self.col = 0 # src.getcol() def __str__(self): - return "" % (tok.tok_rpunct.get(self.name, + return "" % (tok.tok_rpunct.get(self.name, tok.tok_name.get(self.name,str(self.name))), self.value) def __repr__(self): - return "" % (tok.tok_rpunct.get(self.name, + return "" % (tok.tok_rpunct.get(self.name, tok.tok_name.get(self.name,str(self.name))), self.value) +class ArglistObject(ast.Node): + """helper class to build function's arg list""" + def __init__(self, name, value, src): + self.name = name + self.value = value + self.count = 0 + self.line = 0 # src.getline() + self.col = 0 # src.getcol() + + def __str__(self): + return "" % self.value + + def __repr__(self): + return "" % self.value + + class AstBuilderContext(AbstractContext): """specific context management for AstBuidler""" def __init__(self, rule_stack): @@ -484,6 +564,8 @@ # print "REDUCING ALTERNATIVE %s" % sym.sym_name[rule.codename] F( self, 1 ) else: + print "No reducing implementation for %s, just push it on stack" % ( + sym.sym_name[rule.codename]) self.push_rule( rule.codename, 1, source ) else: self.push_rule( rule.codename, 1, source ) @@ -502,6 +584,8 @@ # print "REDUCING SEQUENCE %s" % sym.sym_name[rule.codename] F( self, elts_number ) else: + print "No reducing implementation for %s, just push it on stack" % ( + sym.sym_name[rule.codename]) self.push_rule( rule.codename, elts_number, source ) else: self.push_rule( rule.codename, elts_number, source ) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 11:03:07 2005 @@ -1,3 +1,4 @@ +import os from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER from pypy.interpreter.pyparser.astbuilder import AstBuilder @@ -23,9 +24,18 @@ "x = a * (1 + c)", "x, y, z = 1, 2, 3", "x = 'a' 'b' 'c'", + "l = func()", + "l = func(10)", + "l = func(10, 12, a, b=c, *args)", + "l = func(10, 12, a, b=c, **kwargs)", + "l = func(10, 12, a, b=c, *args, **kwargs)", + "l = func(10, 12, a, b=c)", + # "l = [i for i in range(10)]", + # "l = [i for i in range(10) if i%2 == 0]", + # "l = [1, 2, 3]", ] expression_tests = range(len(expressions)) -# expression_tests = [0] +# expression_tests = [-1] backtrackings = [ "f = lambda x: x+1", @@ -62,24 +72,23 @@ 'a = b\nc = d', ] -def ast_parse_expr( expr ): +def ast_parse_expr(expr): builder = AstBuilder() - PYTHON_PARSER.parse_source( expr, "single_input", builder ) + PYTHON_PARSER.parse_source(expr, 'single_input', builder) return builder -def tuple_parse_expr( expr ): +def tuple_parse_expr(expr): t = Transformer() - return ast_from_input( expr, "single", t ) + return ast_from_input(expr, 'single', t) -def check_expression( expr ): - r1 = ast_parse_expr( expr ) - ast = tuple_parse_expr( expr ) +def check_expression(expr): + r1 = ast_parse_expr(expr) + ast = tuple_parse_expr(expr) print "ORIG :", ast print "BUILT:", r1.rule_stack[-1] assert ast == r1.rule_stack[-1], 'failed on %r' % (expr) - def test_multiexpr(): for expr in multiexpr: yield check_expression, expr @@ -96,3 +105,37 @@ def test_comparisons(): for i in comparison_tests: yield check_expression, comparisons[i] + +SNIPPETS = [ +# 'snippet_1.py', +# 'snippet_2.py', +# 'snippet_3.py', +# 'snippet_4.py', +# 'snippet_comment.py', +# 'snippet_encoding_declaration2.py', +# 'snippet_encoding_declaration3.py', +# 'snippet_encoding_declaration.py', +# 'snippet_function_calls.py', +# 'snippet_generator.py', +# 'snippet_import_statements.py', +# 'snippet_list_comps.py', +# 'snippet_multiline.py', +# 'snippet_numbers.py', +# 'snippet_only_one_comment.py', +# 'snippet_redirected_prints.py', +# 'snippet_samples.py', +# 'snippet_simple_assignment.py', +# 'snippet_simple_class.py', +# 'snippet_simple_for_loop.py', +# 'snippet_simple_in_expr.py', +# 'snippet_slice.py', +# 'snippet_whitespaces.py', + ] + +def test_snippets(): + py.test.skip('Not ready to test on real snippet files') + for snippet_name in SNIPPETS: + filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name) + source = file(filepath).read() + yield check_expression, source + From tismer at codespeak.net Mon Jul 25 11:38:12 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 11:38:12 +0200 (CEST) Subject: [pypy-svn] r14996 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050725093812.4A2A327B55@code1.codespeak.net> Author: tismer Date: Mon Jul 25 11:38:11 2005 New Revision: 14996 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py Log: changed tuple to list Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Mon Jul 25 11:38:11 2005 @@ -651,7 +651,7 @@ raise RuntimeError("Unexpected token type %r" % other) if other is EmptyToken: return False - res = other.codename == self.codename and self.value in (None, other.value) + res = other.codename == self.codename and self.value in [None, other.value] #print "matching", self, other, res return res From arigo at codespeak.net Mon Jul 25 11:46:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 11:46:11 +0200 (CEST) Subject: [pypy-svn] r14997 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050725094611.C009927B55@code1.codespeak.net> Author: arigo Date: Mon Jul 25 11:46:08 2005 New Revision: 14997 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Log: Fixes to make the RTyper happy: the main problem is to ensure that the annotator can prove that slice start and stop cannot be negative. Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Mon Jul 25 11:46:08 2005 @@ -126,7 +126,7 @@ raise TokenError("EOF in multi-line string", line, (lnum, 0), token_list) endmatch = endDFA.recognize(line) - if -1 != endmatch: + if endmatch >= 0: pos = end = endmatch tok = Token(pytoken.STRING, contstr + line[:end]) token_list.append((tok, line, lnum, pos)) @@ -135,7 +135,8 @@ # strstart, (lnum, end), contline + line)) contstr, needcont = '', 0 contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + elif (needcont and not line.endswith('\\\n') and + not line.endswith('\\\r\n')): tok = Token(pytoken.ERRORTOKEN, contstr + line) token_list.append((tok, line, lnum, pos)) last_comment = '' @@ -193,10 +194,10 @@ while pos < max: pseudomatch = pseudoDFA.recognize(line, pos) - if -1 != pseudomatch: # scan for tokens + if pseudomatch >= 0: # scan for tokens # JDR: Modified start = whiteSpaceDFA.recognize(line, pos) - if -1 == start: + if start < 0: start = pos end = pseudomatch @@ -235,7 +236,7 @@ elif token in triple_quoted: endDFA = endDFAs[token] endmatch = endDFA.recognize(line, pos) - if -1 != endmatch: # all on one line + if endmatch >= 0: # all on one line pos = endmatch token = line[start:pos] tok = Token(pytoken.STRING, token) Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Mon Jul 25 11:46:08 2005 @@ -73,11 +73,12 @@ num = rule.codename node = [rule.codename] if elts_number > 0: - sequence_elements = self.stack[-elts_number:] + sequence_elements = [self.stack.pop() for i in range(elts_number)] + sequence_elements.reverse() nodes = expand_nodes( sequence_elements ) - self.stack[-elts_number:] = [NonTerminal(num, nodes)] else: - self.stack.append( NonTerminal(num, []) ) + nodes = [] + self.stack.append( NonTerminal(num, nodes) ) return True def token(self, codename, value, source): From arigo at codespeak.net Mon Jul 25 11:47:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 11:47:26 +0200 (CEST) Subject: [pypy-svn] r14998 - pypy/branch/pypy-translation-snapshot/interpreter/pyparser Message-ID: <20050725094726.4994927B55@code1.codespeak.net> Author: arigo Date: Mon Jul 25 11:47:25 2005 New Revision: 14998 Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/grammar.py pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py pypy/branch/pypy-translation-snapshot/interpreter/pyparser/tuplebuilder.py Log: Merged revisions 14996 and 14997 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyparser/grammar.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyparser/grammar.py Mon Jul 25 11:47:25 2005 @@ -651,7 +651,7 @@ raise RuntimeError("Unexpected token type %r" % other) if other is EmptyToken: return False - res = other.codename == self.codename and self.value in (None, other.value) + res = other.codename == self.codename and self.value in [None, other.value] #print "matching", self, other, res return res Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyparser/pythonlexer.py Mon Jul 25 11:47:25 2005 @@ -126,7 +126,7 @@ raise TokenError("EOF in multi-line string", line, (lnum, 0), token_list) endmatch = endDFA.recognize(line) - if -1 != endmatch: + if endmatch >= 0: pos = end = endmatch tok = Token(pytoken.STRING, contstr + line[:end]) token_list.append((tok, line, lnum, pos)) @@ -135,7 +135,8 @@ # strstart, (lnum, end), contline + line)) contstr, needcont = '', 0 contline = None - elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + elif (needcont and not line.endswith('\\\n') and + not line.endswith('\\\r\n')): tok = Token(pytoken.ERRORTOKEN, contstr + line) token_list.append((tok, line, lnum, pos)) last_comment = '' @@ -193,10 +194,10 @@ while pos < max: pseudomatch = pseudoDFA.recognize(line, pos) - if -1 != pseudomatch: # scan for tokens + if pseudomatch >= 0: # scan for tokens # JDR: Modified start = whiteSpaceDFA.recognize(line, pos) - if -1 == start: + if start < 0: start = pos end = pseudomatch @@ -235,7 +236,7 @@ elif token in triple_quoted: endDFA = endDFAs[token] endmatch = endDFA.recognize(line, pos) - if -1 != endmatch: # all on one line + if endmatch >= 0: # all on one line pos = endmatch token = line[start:pos] tok = Token(pytoken.STRING, token) Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyparser/tuplebuilder.py Mon Jul 25 11:47:25 2005 @@ -73,11 +73,12 @@ num = rule.codename node = [rule.codename] if elts_number > 0: - sequence_elements = self.stack[-elts_number:] + sequence_elements = [self.stack.pop() for i in range(elts_number)] + sequence_elements.reverse() nodes = expand_nodes( sequence_elements ) - self.stack[-elts_number:] = [NonTerminal(num, nodes)] else: - self.stack.append( NonTerminal(num, []) ) + nodes = [] + self.stack.append( NonTerminal(num, nodes) ) return True def token(self, codename, value, source): From adim at codespeak.net Mon Jul 25 12:12:12 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 12:12:12 +0200 (CEST) Subject: [pypy-svn] r14999 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20050725101212.74D8427B55@code1.codespeak.net> Author: adim Date: Mon Jul 25 12:12:09 2005 New Revision: 14999 Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/dist/pypy/interpreter/astcompiler/transformer.py Log: - ast.List's constructor uses an empty list instead of an empty tuple to make things homogeneous - fixed a bug in ast.Node comparison Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.py Mon Jul 25 12:12:09 2005 @@ -36,7 +36,11 @@ def __eq__(self, right): if type(self)!=type(right): return False - for i,j in zip(self.getChildren(),right.getChildren()): + self_child = self.getChildren() + right_child = right.getChildren() + if len(self_child) != len(right_child): + return False + for i,j in zip(self_child, right_child): if not i==j: return False return True @@ -977,6 +981,7 @@ def accept(self, visitor, args): return visitor.visitListComp(self, args) + class ListCompFor(Node): def __init__(self, assign, list, ifs, lineno=None): self.assign = assign Modified: pypy/dist/pypy/interpreter/astcompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/transformer.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/transformer.py Mon Jul 25 12:12:09 2005 @@ -703,7 +703,7 @@ def atom_lsqb(self, nodelist): if nodelist[1][0] == token.RSQB: - return List(()) + return List([]) return self.com_list_constructor(nodelist[1]) def atom_lbrace(self, nodelist): From hpk at codespeak.net Mon Jul 25 12:21:18 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 12:21:18 +0200 (CEST) Subject: [pypy-svn] r15001 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050725102118.BFE8527B55@code1.codespeak.net> Author: hpk Date: Mon Jul 25 12:21:17 2005 New Revision: 15001 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: use 'fn' for filename instead of 'f' Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Mon Jul 25 12:21:17 2005 @@ -15,19 +15,19 @@ # XXX posixpath/ntpath/macpath modules. -def try_import_mod(space, w_modulename, f, w_parent, w_name, pkgdir=None): +def try_import_mod(space, w_modulename, fn, w_parent, w_name, pkgdir=None): w = space.wrap - if os.path.exists(f): + if os.path.exists(fn): w_mod = space.wrap(Module(space, w_modulename)) space.sys.setmodule(w_mod) - space.setattr(w_mod, w('__file__'), w(f)) + space.setattr(w_mod, w('__file__'), w(fn)) space.setattr(w_mod, w('__doc__'), space.w_None) if pkgdir is not None: space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) w_dict = space.getattr(w_mod, w('__dict__')) e = None try: - space.builtin.call('execfile', w(f), w_dict, w_dict) + space.builtin.call('execfile', w(fn), w_dict, w_dict) except OperationError, e: if e.match(space, space.w_SyntaxError): w_mods = space.sys.get('modules') @@ -180,13 +180,13 @@ for path in space.unpackiterable(w_path): dir = os.path.join(space.str_w(path), partname) if os.path.isdir(dir): - f = os.path.join(dir,'__init__.py') - w_mod = try_import_mod(space, w_modulename, f, w_parent, + fn = os.path.join(dir,'__init__.py') + w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname), pkgdir=dir) if w_mod is not None: return w_mod - f = os.path.join(space.str_w(path), partname + '.py') - w_mod = try_import_mod(space, w_modulename, f, w_parent, + fn = os.path.join(space.str_w(path), partname + '.py') + w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname)) if w_mod is not None: return w_mod From tismer at codespeak.net Mon Jul 25 12:28:05 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 12:28:05 +0200 (CEST) Subject: [pypy-svn] r15002 - pypy/dist/pypy/rpython/module Message-ID: <20050725102805.D04D627B55@code1.codespeak.net> Author: tismer Date: Mon Jul 25 12:28:04 2005 New Revision: 15002 Added: pypy/dist/pypy/rpython/module/ll_os_path.py (contents, props changed) Log: added a stub for os.path functions Added: pypy/dist/pypy/rpython/module/ll_os_path.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/ll_os_path.py Mon Jul 25 12:28:04 2005 @@ -0,0 +1,21 @@ +""" +Dummy low-level implementations for the external functions of the 'os.path' module. +""" + +# see ll_os.py for comments + +import os +from pypy.rpython.rstr import STR +from pypy.rpython.module.ll_os import from_rstr + + +# Does a path exist? +# This is false for dangling symbolic links. + +def ll_os_path_exists(path): + """Test whether a path exists""" + try: + st = os.stat(from_rstr(path)) + except os.error: + return False + return True From arigo at codespeak.net Mon Jul 25 12:33:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 12:33:32 +0200 (CEST) Subject: [pypy-svn] r15003 - pypy/dist/pypy/translator/goal Message-ID: <20050725103332.D171927B55@code1.codespeak.net> Author: arigo Date: Mon Jul 25 12:33:30 2005 New Revision: 15003 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: New list of issues from rev 14997. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 25 12:33:30 2005 @@ -9,224 +9,189 @@ * a new snapshot (14956) of the trunk (which is again annotable) has been made * current list of RTyper problems: - - TyperError-1: (pypy.interpreter.pyparser.grammar:match_token) - contains() on non-const tuple - .. block at 80 with 1 exits - .. v933696 = contains(v933690, v933668) - - TyperError-2: (pypy.interpreter.pyparser.pythonlexer:generate_tokens) - slice start must be proved non-negative - .. block at 1651 with 1 exits - .. v826009 = newslice(v825696, pos_825675, (None)) - - TyperError-3: (pypy.interpreter.pyparser.pythonlexer:generate_tokens) - slice stop must be proved non-negative - .. block at 269 with 1 exits - .. v808425 = newslice((None), pos_807666, (None)) - - TyperError-4: (pypy.interpreter.pyparser.tuplebuilder:sequence) - - .. block at 37 with 1 exits - .. v937261 = setitem(v937229, v937260, v937217) - - TyperError-5: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) - can only iterate over tuples of length 1 for now - .. block at 73 with 2 exits(v911582) - .. 'block-entry' - - TyperError-6: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) - can only iterate over tuples of length 1 for now - .. block at 64 with 2 exits(last_exception) - .. 'block-entry' - TyperError-7: (pypy.interpreter.pyparser.pythonlexer:_normalize_encoding) - can only iterate over tuples of length 1 for now - .. block at 63 with 1 exits - .. v911538 = iter((('latin-1', 'iso-lat...8859-1'))) - - TyperError-8: (pypy.objspace.std.listobject:unwrap) + TyperError-1: (pypy.objspace.std.listobject:unwrap) no list() support for .. block at 73 with 1 exits - .. v644424 = simple_call((type list), v644419) + .. v591333 = simple_call((type list), v591328) - TyperError-9: (pypy.module.__builtin__.importing:load_part) - don't know about built-in function - .. block at 201 with 2 exits(v755595) - .. v755564 = simple_call((function isdir), v755527) - - TyperError-10: (pypy.module.__builtin__.importing:try_import_mod) - don't know about built-in function - .. block at -1 with 2 exits(v905077) - .. v905061 = simple_call((function exists), f_905031) + TyperError-2: (pypy.module.__builtin__.importing:load_part) + don't know about built-in function + .. block at 201 with 2 exits(v766387) + .. v766356 = simple_call((function isdir), v766319) + + TyperError-3: (pypy.module.__builtin__.importing:try_import_mod) + don't know about built-in function + .. block at -1 with 2 exits(v901991) + .. v901975 = simple_call((function exists), f_901945) - TyperError-11: (pypy.module.sys.vm:getrefcount) + TyperError-4: (pypy.module.sys.vm:getrefcount) don't know about built-in function .. block at -1 with 1 exits - .. v294775 = simple_call((builtin_function_or_method getrefcount), w_obj_294756) + .. v210471 = simple_call((builtin_function_or_method getrefcount), w_obj_210452) - TyperError-12: (pypy.module.unicodedata.function:normalize) - cannot make repr of + TyperError-5: (pypy.module.unicodedata.function:normalize) + cannot make repr of .. block at 1498 with 2 exits(last_exception) - .. v389623 = getitem(({(104, 770): 293, (6...8): 366}), v389526) + .. v341362 = getitem(({(104, 770): 293, (6...8): 366}), v341265) - TyperError-13: (pypy.module.unicodedata.unicodedb:name) + TyperError-6: (pypy.module.unicodedata.unicodedb:name) unimplemented operation: 'divmod' on (, ) .. block at 170 EH with 1 exits - .. v885420 = divmod(v885413, (21)) + .. v791070 = divmod(v791063, (21)) - TyperError-14: (pypy.module.unicodedata.unicodedb:name) + TyperError-7: (pypy.module.unicodedata.unicodedb:name) unimplemented operation: 'divmod' on (, ) .. block at 157 with 1 exits - .. v885379 = divmod(v885353, (28)) + .. v791029 = divmod(v791003, (28)) - TyperError-15: (pypy.objspace.std.fake:fake__new__) + TyperError-8: (pypy.objspace.std.fake:fake__new__) don't know about built-in function .. block at 145 with 1 exits - .. v314219 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v314191, v314192) + .. v531481 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v531453, v53 + 1454) - TyperError-16: (pypy.objspace.std.fake:setfastscope) - ll_str unsupported for: - .. block at 118 with 1 exits - .. v339770 = mod(('calling %s: %s'), v339759) + TyperError-9: (pypy.objspace.std.fake:fake__new__) + don't know about built-in function + .. block at 145 with 1 exits + .. v356204 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v356176, v35 + 6177) - TyperError-17: (pypy.objspace.std.fake:run) + TyperError-10: (pypy.objspace.std.fake:run) don't know about built-in function .. block at 62 with 1 exits - .. v342110 = simple_call((builtin_function_or_method apply), v342092, v342093, v342094) + .. v358126 = simple_call((builtin_function_or_method apply), v358108, v358109, v358110) - TyperError-18: (pypy.objspace.std.fake:fake__new__) - don't know about built-in function - .. block at 145 with 1 exits - .. v501617 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v501589, v501590) + TyperError-11: (pypy.objspace.std.fake:setfastscope) + ll_str unsupported for: + .. block at 118 with 1 exits + .. v357756 = mod(('calling %s: %s'), v357745) - TyperError-19: (pypy.objspace.std.floatobject:hash__Float) + TyperError-12: (pypy.objspace.std.floatobject:hash__Float) unimplemented operation: 'hash' on .. block at -1 with 1 exits - .. v436008 = hash(v435997) + .. v463799 = hash(v463788) - TyperError-20: (pypy.objspace.std.longobject:_FromDouble) + TyperError-13: (pypy.objspace.std.longobject:_FromDouble) don't know about built-in function .. block at 245 with 1 exits - .. v441291 = simple_call((builtin_function_or_method ldexp), v441269, (15)) - - TyperError-21: (pypy.objspace.std.longobject:_long_true_divide) - don't know about built-in function - .. block at 183 with 1 exits - .. v489794 = simple_call((builtin_function_or_method ldexp), v489730, v489754) - - TyperError-22: (pypy.objspace.std.longobject:_FromDouble) - don't know about built-in function - .. block at 143 with 1 exits - .. v441106 = simple_call((builtin_function_or_method ldexp), frac_440918, v441090) + .. v427244 = simple_call((builtin_function_or_method ldexp), v427222, (15)) - TyperError-23: (pypy.objspace.std.longobject:_AsDouble) + TyperError-14: (pypy.objspace.std.longobject:_AsDouble) don't know about built-in function .. block at 53 with 1 exits - .. v610741 = simple_call((builtin_function_or_method ldexp), v610725, v610729) + .. v672412 = simple_call((builtin_function_or_method ldexp), v672396, v672400) - TyperError-24: (pypy.objspace.std.longobject:longval) + TyperError-15: (pypy.objspace.std.longobject:longval) don't know about built-in function .. block at 50 with 1 exits - .. v692507 = simple_call((type long), d_692470) + .. v604056 = simple_call((type long), d_604019) - TyperError-25: (pypy.objspace.std.longobject:_FromDouble) + TyperError-16: (pypy.objspace.std.longobject:_FromDouble) don't know about built-in function .. block at 89 with 1 exits - .. v440853 = simple_call((builtin_function_or_method frexp), v440842) + .. v426806 = simple_call((builtin_function_or_method frexp), v426795) - TyperError-26: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v736063) - .. link from block at -1 to block at -1 + TyperError-17: (pypy.objspace.std.longobject:_long_true_divide) + don't know about built-in function + .. block at 183 with 1 exits + .. v539689 = simple_call((builtin_function_or_method ldexp), v539625, v539649) - TyperError-27: (pypy.objspace.std.objspace:wrap__object) - no unichr() support for - .. block at 265 with 1 exits - .. v735961 = simple_call((builtin_function_or_method unichr), v735931) + TyperError-18: (pypy.objspace.std.longobject:_FromDouble) + don't know about built-in function + .. block at 143 with 1 exits + .. v427059 = simple_call((builtin_function_or_method ldexp), frac_426871, v427043) - TyperError-28: (pypy.objspace.std.objspace:wrap__object) + TyperError-19: (pypy.objspace.std.objspace:unwrap) + unimplemented operation: 'mod' on (, + ) + .. block at 63 with 1 exits + .. v507742 = mod(('cannot unwrap: %r'), v507736) + + TyperError-20: (pypy.objspace.std.objspace:wrap__object) don't know how to convert from to - .. block at -1 with 2 exits(v736503) + .. block at -1 with 2 exits(v675927) .. link from block at -1 to block at -1 - TyperError-29: (pypy.objspace.std.objspace:wrap__object) - no list() support for - .. block at 446 with 1 exits - .. v736052 = simple_call((type list), x_735955) + TyperError-21: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v675023) + .. link from block at -1 to block at -1 - TyperError-30: (pypy.objspace.std.objspace:unwrap) - don't know how to convert from to - .. block at -1 EH with 2 exits(v502133) - .. link from block at -1 EH to codeless block + TyperError-22: (pypy.objspace.std.objspace:wrap__object) + call_specialcase: unknown tag override:wrap_exception_cls + .. block at 886 with 2 exits(v676097) + .. v676057 = call_specialcase(v676020, x_675999) - TyperError-31: (pypy.objspace.std.objspace:unwrap) - unimplemented operation: 'mod' on (, ) - .. block at 63 with 1 exits - .. v502156 = mod(('cannot unwrap: %r'), v502150) + TyperError-23: (pypy.objspace.std.objspace:wrap__object) + no unichr() support for + .. block at 265 with 1 exits + .. v675385 = simple_call((builtin_function_or_method unichr), v675355) - TyperError-32: (pypy.objspace.std.objspace:wrap__object) + TyperError-24: (pypy.objspace.std.objspace:unwrap) + don't know how to convert from to + .. block at -1 EH with 2 exits(v507719) + .. link from block at -1 EH to codeless block + + TyperError-25: (pypy.objspace.std.objspace:wrap__object) don't know how to convert from to - .. block at -1 with 2 exits(v735576) + .. block at -1 with 2 exits(v675000) .. link from block at -1 to block at -1 - TyperError-33: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:fake_object - .. block at 945 with 1 exits - .. v736591 = call_specialcase((function fake_object), v736570, v736571) - - TyperError-34: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v735599) + TyperError-26: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v675487) .. link from block at -1 to block at -1 - TyperError-35: (pypy.objspace.std.objspace:wrap__object) + TyperError-27: (pypy.objspace.std.objspace:wrap__object) don't know how to convert from to - .. block at -1 with 2 exits(v736550) + .. block at -1 with 2 exits(v675974) .. link from block at -1 to block at 945 - TyperError-36: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:wrap_exception_cls - .. block at 886 with 2 exits(v736673) - .. v736633 = call_specialcase(v736596, x_736575) + TyperError-28: (pypy.objspace.std.objspace:wrap__object) + call_specialcase: unknown tag override:fake_object + .. block at 945 with 1 exits + .. v676015 = call_specialcase((function fake_object), v675994, v675995) + + TyperError-29: (pypy.objspace.std.objspace:wrap__object) + no list() support for + .. block at 446 with 1 exits + .. v675476 = simple_call((type list), x_675379) - TyperError-37: (pypy.objspace.std.sliceobject:unwrap) + TyperError-30: (pypy.objspace.std.sliceobject:unwrap) don't know about built-in function .. block at -1 with 1 exits - .. v643574 = simple_call((type slice), v643486, v643522, v643561) + .. v591645 = simple_call((type slice), v591557, v591593, v591632) - TyperError-38: (pypy.objspace.std.tupleobject:unwrap) + TyperError-31: (pypy.objspace.std.tupleobject:unwrap) don't know about built-in function .. block at 66 with 1 exits - .. v643722 = simple_call((type tuple), v643717) + .. v590595 = simple_call((type tuple), v590590) - TyperError-39: (pypy.objspace.std.unicodeobject:unwrap) + TyperError-32: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) + cannot make repr of + .. block at 185 with 2 exits(v596694) + .. v596669 = contains(((u'+', u'-')), v596629) + + TyperError-33: (pypy.objspace.std.unicodeobject:unwrap) don't know how to convert from to .. block at -1 with 1 exits - .. v644571 = simple_call((builtin_function_or_method join), v644562) - - TyperError-40: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) - cannot make repr of - .. block at 185 with 2 exits(v750416) - .. v750391 = contains(((u'+', u'-')), v750351) + .. v591049 = simple_call((builtin_function_or_method join), v591040) - TyperError-41: (pypy.module.recparser.pyparser:visit_syntaxnode) - inconsistent type for the result of 'getitem': - annotator says SomeList(listdef=), - whose repr is * GcStruct object { ... } } } } }> - but rtype_getitem returned <* GcStruct list { items: * GcArray of * GcStruct W_TupleObject { super: GcStruct W_Object { super: GcStruct W_Root { super: GcStruct object { typeptr: * Struct object_vtable { parenttypeptr: * Struct object_vtable { ... }, rtti: * RuntimeTypeInfo (opaque), name: * Array of Char , instantiate: * Func ( ) -> * GcStruct object { ... } } } }, inst_space: Void }, inst_wrappeditems: * GcStruct list { items: * GcArray of * GcStruct W_Root { super: GcStruct object { typeptr: * Struct object_vtable { parenttypeptr: * Struct object_vtable { ... }, rtti: * RuntimeTypeInfo (opaque), name: * Array of Char , instantiate: * Func ( ) -> * GcStruct object { ... } } } } } } }> - .. block at 48 with 1 exits - .. v714944 = getitem(v714920, v714943) + TyperError-34: (pypy.rpython.rarithmetic:ovfcheck_float_to_int) + don't know about built-in function + .. block at -1 with 1 exits + .. v910653 = simple_call((builtin_function_or_method modf), x_910646) - TyperError-42: (pypy.interpreter.pycompiler:compile) + TyperError-35: (pypy.interpreter.pycompiler:compile) call_specialcase: unknown tag override:cpy_stablecompiler .. block at 156 with 1 exits - .. v730727 = call_specialcase(v730690, parse_result_730673, filename_730669, mode_730670) + .. v783803 = call_specialcase(v783766, parse_result_783749, filename_783745, mode_783746) - TyperError-43: (pypy.rpython.rarithmetic:ovfcheck_float_to_int) - don't know about built-in function - .. block at -1 with 1 exits - .. v911394 = simple_call((builtin_function_or_method modf), x_911387) How to work in parallel: From arigo at codespeak.net Mon Jul 25 13:12:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 13:12:59 +0200 (CEST) Subject: [pypy-svn] r15007 - pypy/dist/pypy/module/unicodedata Message-ID: <20050725111259.EAF5427B55@code1.codespeak.net> Author: arigo Date: Mon Jul 25 13:12:51 2005 New Revision: 15007 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: - allow generate_unicodedb.py to run on a narrow Python build - there was a table in the generated file that was not sorted, making looking at diffs harder. Sorting and regenerating... 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 Mon Jul 25 13:12:51 2005 @@ -1,5 +1,6 @@ #!/usr/bin/env python -import sys + +MAXUNICODE = 0x10FFFF # the value of sys.maxunicode of wide Python builds class Unicodechar: def __init__(self, data): @@ -76,7 +77,7 @@ def read_unicodedata(unicodedata_file, exclusions_file, east_asian_width_file): rangeFirst = {} rangeLast = {} - table = [None] * (sys.maxunicode + 1) + table = [None] * (MAXUNICODE + 1) for line in unicodedata_file: line = line.split('#', 1)[0].strip() if not line: @@ -211,6 +212,7 @@ char.db_record = (char.category, char.bidirectional, char.east_asian_width, flags, char.combining) db_records[char.db_record] = 1 db_records = db_records.keys() + db_records.sort() print >> outfile, '_db_records = [' for record in db_records: print >> outfile, '%r,'%(record,) @@ -446,7 +448,7 @@ if __name__ == '__main__': - import getopt, re + import getopt, re, sys infile = None outfile = sys.stdout unidata_version = None Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Mon Jul 25 13:12:51 2005 @@ -13876,226 +13876,226 @@ return _charnames[code] _db_records = [ -('Mn', 'NSM', 'N', 0, 222), +('Cc', 'B', 'N', 5, 0), +('Cc', 'BN', 'N', 0, 0), +('Cc', 'S', 'N', 1, 0), +('Cc', 'WS', 'N', 1, 0), +('Cf', 'AL', 'N', 0, 0), +('Cf', 'BN', 'N', 0, 0), +('Cf', 'L', 'N', 0, 0), +('Cf', 'LRE', 'N', 0, 0), +('Cf', 'LRO', 'N', 0, 0), +('Cf', 'PDF', 'N', 0, 0), ('Cf', 'R', 'N', 0, 0), -('Lu', 'L', 'N', 10, 0), +('Cf', 'RLE', 'N', 0, 0), +('Cf', 'RLO', 'N', 0, 0), +('Cn', '', 'N', 0, 0), +('Co', 'L', 'A', 0, 0), +('Cs', 'L', 'N', 0, 0), +('Ll', 'L', 'A', 34, 0), +('Ll', 'L', 'F', 34, 0), +('Ll', 'L', 'N', 34, 0), +('Ll', 'L', 'Na', 34, 0), +('Lm', 'AL', 'N', 2, 0), +('Lm', 'L', 'A', 2, 0), +('Lm', 'L', 'H', 2, 0), ('Lm', 'L', 'N', 2, 0), -('Ps', 'ON', 'Na', 512, 0), -('Cf', 'PDF', 'N', 0, 0), -('Mn', 'NSM', 'W', 0, 222), -('Cf', 'LRE', 'N', 0, 0), -('Pc', 'ON', 'F', 0, 0), -('Sm', 'ON', 'A', 0, 0), -('No', 'EN', 'A', 192, 0), -('Mn', 'NSM', 'N', 0, 36), -('Mn', 'NSM', 'N', 0, 15), -('So', 'ON', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 26), -('Mn', 'NSM', 'N', 0, 19), -('Pc', 'ON', 'H', 0, 0), -('Po', 'ET', 'F', 0, 0), -('Mn', 'NSM', 'N', 0, 103), -('Pd', 'ET', 'Na', 0, 0), -('Po', 'ON', 'F', 0, 0), -('Nd', 'L', 'N', 448, 0), +('Lm', 'L', 'W', 2, 0), ('Lo', 'AL', 'N', 2, 0), -('Sm', 'ON', 'Na', 0, 0), -('Pc', 'ON', 'N', 0, 0), -('Nd', 'EN', 'Na', 448, 0), -('Pe', 'ON', 'H', 512, 0), -('Cc', 'B', 'N', 5, 0), -('Sc', 'ET', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 216), -('Zs', 'CS', 'N', 1, 0), -('Po', 'ON', 'W', 0, 0), -('So', 'ON', 'F', 0, 0), -('So', 'L', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 107), -('Pc', 'ON', 'Na', 0, 0), -('Po', 'ET', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 118), -('Zs', 'WS', 'F', 1, 0), -('So', 'ON', 'H', 0, 0), -('Sm', 'ET', 'F', 0, 0), -('Pe', 'ON', 'N', 512, 0), -('Mc', 'L', 'N', 0, 226), -('Mn', 'NSM', 'N', 0, 9), -('Mn', 'NSM', 'N', 0, 27), -('Mn', 'NSM', 'N', 0, 20), -('Mn', 'NSM', 'A', 0, 230), -('Pe', 'ON', 'F', 512, 0), -('Pf', 'ON', 'A', 0, 0), -('No', 'EN', 'N', 448, 0), -('Ps', 'ON', 'W', 0, 0), -('Po', 'ET', 'W', 0, 0), -('So', 'ON', 'N', 0, 0), -('Pd', 'ON', 'N', 0, 0), -('Nd', 'EN', 'N', 448, 0), -('Sm', 'ON', 'A', 512, 0), -('Lm', 'AL', 'N', 2, 0), -('Lo', 'L', 'N', 2, 0), -('Nd', 'AN', 'N', 448, 0), -('Sk', 'ON', 'Na', 0, 0), -('Cs', 'L', 'N', 0, 0), -('Po', 'R', 'N', 0, 0), -('Mn', 'NSM', 'W', 0, 8), -('So', 'L', 'W', 0, 0), -('Mn', 'NSM', 'N', 0, 129), -('Sk', 'ON', 'F', 0, 0), -('So', 'ET', 'N', 0, 0), -('Co', 'L', 'A', 0, 0), ('Lo', 'L', 'H', 2, 0), -('Mn', 'NSM', 'N', 0, 91), -('So', 'ET', 'A', 0, 0), -('Po', 'ON', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 10), -('Mn', 'NSM', 'N', 0, 1), -('Mn', 'NSM', 'N', 0, 28), -('Mn', 'NSM', 'N', 0, 21), +('Lo', 'L', 'N', 2, 0), ('Lo', 'L', 'W', 2, 0), -('Pf', 'ON', 'N', 512, 0), -('Pi', 'ON', 'N', 0, 0), -('Lm', 'L', 'W', 2, 0), -('Pc', 'ON', 'W', 0, 0), -('Sk', 'ON', 'N', 0, 0), -('Pi', 'ON', 'N', 512, 0), -('Mc', 'L', 'N', 0, 0), -('Po', 'ET', 'A', 0, 0), -('Cc', 'BN', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 228), -('No', 'EN', 'A', 64, 0), -('Zl', 'WS', 'N', 5, 0), -('No', 'L', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 130), -('Nl', 'L', 'N', 0, 0), -('Pd', 'ON', 'W', 0, 0), -('Cn', '', 'N', 0, 0), -('Sm', 'ON', 'N', 512, 0), -('Pd', 'ET', 'W', 0, 0), -('Mn', 'NSM', 'W', 0, 224), -('Mn', 'NSM', 'N', 0, 32), -('Mn', 'NSM', 'N', 0, 122), -('Mn', 'NSM', 'N', 0, 11), -('Lu', 'L', 'Na', 10, 0), -('Mn', 'NSM', 'N', 0, 29), -('Mn', 'NSM', 'N', 0, 22), -('Mn', 'NSM', 'A', 0, 234), -('Cf', 'AL', 'N', 0, 0), -('Sm', 'ON', 'N', 0, 0), -('Mn', 'NSM', 'A', 0, 220), +('Lo', 'R', 'N', 2, 0), ('Lt', 'L', 'N', 18, 0), -('Po', 'CS', 'N', 0, 0), -('Cf', 'BN', 'N', 0, 0), -('Pe', 'ON', 'W', 0, 0), -('Zp', 'B', 'N', 5, 0), -('Ps', 'ON', 'W', 512, 0), ('Lu', 'L', 'A', 10, 0), -('No', 'ON', 'A', 192, 0), -('No', 'L', 'W', 64, 0), -('Pe', 'ON', 'W', 512, 0), -('Cf', 'L', 'N', 0, 0), -('Po', 'CS', 'F', 0, 0), -('Nl', 'L', 'W', 64, 0), -('Sm', 'L', 'N', 0, 0), ('Lu', 'L', 'F', 10, 0), -('Ll', 'L', 'N', 34, 0), -('So', 'ON', 'A', 0, 0), -('Sc', 'ET', 'Na', 0, 0), -('Sm', 'ON', 'Na', 512, 0), +('Lu', 'L', 'N', 10, 0), +('Lu', 'L', 'Na', 10, 0), +('Mc', 'L', 'N', 0, 0), ('Mc', 'L', 'N', 0, 216), -('Mn', 'NSM', 'W', 0, 232), -('Mn', 'NSM', 'N', 0, 33), -('Po', 'CS', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 12), -('Mn', 'NSM', 'N', 0, 30), -('Mn', 'NSM', 'N', 0, 23), -('Mn', 'NSM', 'N', 0, 16), +('Mc', 'L', 'N', 0, 226), +('Me', 'NSM', 'N', 0, 0), +('Mn', 'NSM', 'A', 0, 0), +('Mn', 'NSM', 'A', 0, 1), +('Mn', 'NSM', 'A', 0, 202), +('Mn', 'NSM', 'A', 0, 216), +('Mn', 'NSM', 'A', 0, 220), +('Mn', 'NSM', 'A', 0, 230), +('Mn', 'NSM', 'A', 0, 232), ('Mn', 'NSM', 'A', 0, 233), +('Mn', 'NSM', 'A', 0, 234), ('Mn', 'NSM', 'A', 0, 240), +('Mn', 'NSM', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 1), +('Mn', 'NSM', 'N', 0, 7), +('Mn', 'NSM', 'N', 0, 9), +('Mn', 'NSM', 'N', 0, 10), +('Mn', 'NSM', 'N', 0, 11), +('Mn', 'NSM', 'N', 0, 12), +('Mn', 'NSM', 'N', 0, 13), +('Mn', 'NSM', 'N', 0, 14), +('Mn', 'NSM', 'N', 0, 15), +('Mn', 'NSM', 'N', 0, 16), +('Mn', 'NSM', 'N', 0, 17), +('Mn', 'NSM', 'N', 0, 18), +('Mn', 'NSM', 'N', 0, 19), +('Mn', 'NSM', 'N', 0, 20), +('Mn', 'NSM', 'N', 0, 21), +('Mn', 'NSM', 'N', 0, 22), +('Mn', 'NSM', 'N', 0, 23), ('Mn', 'NSM', 'N', 0, 24), -('Sk', 'ON', 'W', 0, 0), -('Sm', 'ET', 'N', 0, 0), -('Me', 'NSM', 'N', 0, 0), -('Pd', 'ON', 'A', 0, 0), -('Ll', 'L', 'F', 34, 0), -('No', 'EN', 'A', 448, 0), -('Ll', 'L', 'A', 34, 0), -('Zs', 'WS', 'Na', 1, 0), -('Ps', 'ON', 'N', 512, 0), -('Nd', 'EN', 'F', 448, 0), -('Sc', 'ET', 'N', 0, 0), -('Cf', 'RLE', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 230), -('Sm', 'ET', 'Na', 0, 0), -('Po', 'L', 'N', 0, 0), -('Cf', 'LRO', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 220), -('Sc', 'ET', 'H', 0, 0), -('No', 'EN', 'N', 192, 0), -('No', 'ON', 'N', 64, 0), -('So', 'L', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 25), +('Mn', 'NSM', 'N', 0, 26), +('Mn', 'NSM', 'N', 0, 27), +('Mn', 'NSM', 'N', 0, 28), +('Mn', 'NSM', 'N', 0, 29), +('Mn', 'NSM', 'N', 0, 30), +('Mn', 'NSM', 'N', 0, 31), +('Mn', 'NSM', 'N', 0, 32), +('Mn', 'NSM', 'N', 0, 33), +('Mn', 'NSM', 'N', 0, 34), +('Mn', 'NSM', 'N', 0, 35), +('Mn', 'NSM', 'N', 0, 36), +('Mn', 'NSM', 'N', 0, 84), +('Mn', 'NSM', 'N', 0, 91), +('Mn', 'NSM', 'N', 0, 103), +('Mn', 'NSM', 'N', 0, 107), +('Mn', 'NSM', 'N', 0, 118), +('Mn', 'NSM', 'N', 0, 122), +('Mn', 'NSM', 'N', 0, 129), +('Mn', 'NSM', 'N', 0, 130), ('Mn', 'NSM', 'N', 0, 132), -('Ll', 'L', 'Na', 34, 0), +('Mn', 'NSM', 'N', 0, 216), +('Mn', 'NSM', 'N', 0, 220), +('Mn', 'NSM', 'N', 0, 222), +('Mn', 'NSM', 'N', 0, 228), +('Mn', 'NSM', 'N', 0, 230), +('Mn', 'NSM', 'W', 0, 8), ('Mn', 'NSM', 'W', 0, 218), -('Zs', 'BN', 'N', 1, 0), -('Sm', 'ET', 'A', 0, 0), +('Mn', 'NSM', 'W', 0, 222), +('Mn', 'NSM', 'W', 0, 224), +('Mn', 'NSM', 'W', 0, 228), +('Mn', 'NSM', 'W', 0, 232), +('Nd', 'AN', 'N', 448, 0), +('Nd', 'EN', 'F', 448, 0), +('Nd', 'EN', 'N', 448, 0), +('Nd', 'EN', 'Na', 448, 0), +('Nd', 'L', 'N', 448, 0), ('Nl', 'L', 'A', 64, 0), -('Mn', 'NSM', 'N', 0, 34), -('Mn', 'NSM', 'N', 0, 13), -('Mn', 'NSM', 'N', 0, 31), -('Po', 'ON', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 17), -('Mn', 'NSM', 'A', 0, 232), -('Po', 'AN', 'N', 0, 0), -('Sc', 'ET', 'F', 0, 0), -('No', 'ON', 'A', 64, 0), -('Pe', 'ON', 'N', 0, 0), -('Po', 'ET', 'N', 0, 0), -('Zs', 'WS', 'N', 1, 0), +('Nl', 'L', 'N', 0, 0), +('Nl', 'L', 'N', 64, 0), +('Nl', 'L', 'W', 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', '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), -('Sk', 'ON', 'A', 0, 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), -('Nl', 'L', 'N', 64, 0), -('Sm', 'ON', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 1), -('Sm', 'ON', 'H', 0, 0), -('Sm', 'ET', 'W', 0, 0), -('Cc', 'S', 'N', 1, 0), +('Pd', 'ET', 'Na', 0, 0), +('Pd', 'ET', 'W', 0, 0), +('Pd', 'ON', 'A', 0, 0), +('Pd', 'ON', 'N', 0, 0), +('Pd', 'ON', 'W', 0, 0), +('Pe', 'ON', 'F', 512, 0), +('Pe', 'ON', 'H', 512, 0), +('Pe', 'ON', 'N', 0, 0), +('Pe', 'ON', 'N', 512, 0), +('Pe', 'ON', 'Na', 512, 0), +('Pe', 'ON', 'W', 0, 0), +('Pe', 'ON', 'W', 512, 0), +('Pf', 'ON', 'A', 0, 0), +('Pf', 'ON', 'N', 512, 0), +('Pi', 'ON', 'A', 0, 0), +('Pi', 'ON', 'N', 0, 0), +('Pi', 'ON', 'N', 512, 0), +('Po', 'AL', 'N', 0, 0), +('Po', 'AN', 'N', 0, 0), +('Po', 'CS', 'F', 0, 0), +('Po', 'CS', 'N', 0, 0), +('Po', 'CS', 'Na', 0, 0), +('Po', 'CS', 'W', 0, 0), ('Po', 'ES', 'F', 0, 0), -('Lo', 'R', 'N', 2, 0), -('Ps', 'ON', 'F', 512, 0), +('Po', 'ES', 'Na', 0, 0), +('Po', 'ET', 'A', 0, 0), +('Po', 'ET', 'F', 0, 0), +('Po', 'ET', 'N', 0, 0), +('Po', 'ET', 'Na', 0, 0), +('Po', 'ET', 'W', 0, 0), +('Po', 'L', 'N', 0, 0), +('Po', 'ON', 'A', 0, 0), +('Po', 'ON', 'F', 0, 0), +('Po', 'ON', 'H', 0, 0), ('Po', 'ON', 'N', 0, 0), -('Pi', 'ON', 'A', 0, 0), -('Lm', 'L', 'A', 2, 0), +('Po', 'ON', 'Na', 0, 0), +('Po', 'ON', 'W', 0, 0), +('Po', 'R', 'N', 0, 0), +('Ps', 'ON', 'F', 512, 0), ('Ps', 'ON', 'H', 512, 0), -('So', 'AL', 'N', 0, 0), -('Po', 'ON', 'H', 0, 0), -('Mn', 'NSM', 'W', 0, 228), -('Mn', 'NSM', 'N', 0, 35), -('Cc', 'WS', 'N', 1, 0), -('Mn', 'NSM', 'N', 0, 14), -('Mn', 'NSM', 'N', 0, 7), -('Mn', 'NSM', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 25), -('Mn', 'NSM', 'N', 0, 18), -('Po', 'ES', 'Na', 0, 0), -('Po', 'CS', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 202), -('Mn', 'NSM', 'A', 0, 216), -('Cf', 'RLO', 'N', 0, 0), ('Ps', 'ON', 'N', 0, 0), -('Lm', 'L', 'H', 2, 0), +('Ps', 'ON', 'N', 512, 0), +('Ps', 'ON', 'Na', 512, 0), +('Ps', 'ON', 'W', 0, 0), +('Ps', 'ON', 'W', 512, 0), +('Sc', 'AL', 'N', 0, 0), +('Sc', 'ET', 'A', 0, 0), +('Sc', 'ET', 'F', 0, 0), +('Sc', 'ET', 'H', 0, 0), +('Sc', 'ET', 'N', 0, 0), +('Sc', 'ET', 'Na', 0, 0), ('Sc', 'ET', 'W', 0, 0), -('Po', 'AL', 'N', 0, 0), +('Sk', 'ON', 'A', 0, 0), +('Sk', 'ON', 'F', 0, 0), +('Sk', 'ON', 'N', 0, 0), +('Sk', 'ON', 'Na', 0, 0), +('Sk', 'ON', '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), ('Sm', 'ON', 'F', 0, 0), -('Mn', 'NSM', 'N', 0, 84), -('Sc', 'AL', 'N', 0, 0), -('No', 'ON', 'N', 192, 0), -('So', 'ON', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 0), -('Pe', 'ON', 'Na', 512, 0), ('Sm', 'ON', 'F', 512, 0), +('Sm', 'ON', 'H', 0, 0), +('Sm', 'ON', 'N', 0, 0), +('Sm', 'ON', 'N', 512, 0), +('Sm', 'ON', 'Na', 0, 0), +('Sm', 'ON', 'Na', 512, 0), +('Sm', 'ON', 'W', 0, 0), +('So', 'AL', 'N', 0, 0), +('So', 'ET', 'A', 0, 0), +('So', 'ET', 'N', 0, 0), +('So', 'L', 'A', 0, 0), +('So', 'L', 'N', 0, 0), +('So', 'L', 'W', 0, 0), +('So', 'ON', 'A', 0, 0), +('So', 'ON', 'F', 0, 0), +('So', 'ON', 'H', 0, 0), +('So', 'ON', 'N', 0, 0), +('So', 'ON', 'Na', 0, 0), +('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&\'()*+,,,,,,,,,,,,' @@ -14168,282 +14168,282 @@ '222222222222222222222222222222222222222222222222222222222222222D' ) _db_pages = ( -'UUUUUUUUU\xb9\x1b\xb9\xc5\x1bUUUUUUUUUUUUUU\x1b\x1b\x1b\xb9\x90\xa7\xa7$|$\xa7\xa7\x04\xda\xa7\x96\x81\x13\x81\xcb\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x81\xa7}\x17}\xa7' -'\xa7dddddddddddddddddddddddddd\x04\xa7\xda;#;\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x04\x17\xda\x17U' -'UUUUU\x1bUUUUUUUUUUUUUUUUUUUUUUUUUU\x1eG||\x1c|\r{\xb24\x8fR\x17\x8c{;F\xa2\x8e\x8e\xb2z{G\xb2\x8e\x8fM\xac\xac\xacG' -'\x02\x02\x02\x02\x02\x02q\x02\x02\x02\x02\x02\x02\x02\x02\x02q\x02\x02\x02\x02\x02\x02\tq\x02\x02\x02\x02\x02q\x8f\x8f\x8fzzzz\x8fz\x8f\x8f\x8fz\x8f\x8fzz\x8fz\x8f\x8fzzz\t\x8f\x8f\x8fz\x8fz\x8fz' -'\x02\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02\x8f\x02\x8f\x02z\x02z\x02z\x02\x8f\x02z\x02z\x02z\x02z\x02zq\x8f\x02z\x02\x8f\x02z\x02z\x02\x8fq\x8f\x02z\x02z\x8f\x02z\x02z\x02zq' -'\x8fq\x8f\x02\x8f\x02z\x02\x8f\x8fq\x8f\x02\x8f\x02z\x02zq\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zq\x8f\x02z\x02\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02\x02z\x02z\x02zz' -'z\x02\x02z\x02z\x02\x02z\x02\x02\x02zz\x02\x02\x02\x02z\x02\x02z\x02\x02\x02zzz\x02\x02z\x02\x02z\x02z\x02z\x02\x02z\x02zz\x02z\x02\x02z\x02\x02\x02z\x02z\x02\x02zz9\x02zzz' -'9999\x02kz\x02kz\x02kz\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8fz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zz\x02kz\x02z\x02\x02\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]z\x8fzzzzzzzzzzzzzzz\x8fzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz]]\x03\x03\x03\x03\x03\x03\x03\x03\x03QQ\x03\x03\x03\x03\x03' -'\x03\x03QQ\xb2QQ\xb2Q\xb2\xb2\xb2Q\xb2QQ\xbf\x03QQQQQQ\xb2\xb2\xb2\xb2Q\xb2Q\xb2\x03\x03\x03\x03\x03QQQQQQQQQ\x03]]]]]]]]]]]]]]]]]' -'.....................\xa9jjjj\xa9\xcejjjjj\xcd\xcdjjjj\xcd\xcdjjjjjjjjjjj\xb6\xb6\xb6\xb6\xb6jjjj...' -'.....\x87.jjj...jj\xd9]]]]]]]]]]]]]]]]gg\x86.............]]]]QQ]]]]\x03]]]\xbd]' -']]]]QQ\x02\xbd\x02\x02\x02]\x02]\x02\x02zqqqqqqqqqqqqqqqqq]qqqqqqq\x02\x02zzzzz\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f' -'\x8f\x8fz\x8f\x8f\x8f\x8f\x8f\x8f\x8fzzzzz]zz\x02\x02\x02zzz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zzzzz\x02zi]]]]]]]]]' -'\x02q\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f' -'\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8fz\x8fzzzzzzzzzzzzzz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x9d\x95\x95\x95\x95]\x8b\x8b\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02\x02z\x02z\x02z\x02z\x02z\x02z\x02z]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]\x02z]]]]]]' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02]]\x03\x97\x97\x97\x97\x97\x97]zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzz]\x975]]]]]]\x99\x95\x95\x95\x95\x99\x95\x95\x95\x00\x99\x95\x95\x95\x95\x95\x95]\x99\x99\x99\x99\x99\x95\x95\x99\x95\x95\x00V\x95Hc\x82\xa5\xc6\x0c\x85\xa8\xca\x0f]-Kf=\x84' -'=\x88\xc9=\x95]]]]]]]]]]]\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb]]]]]\xbb\xbb\xbb==]]]]]]]]]]]' -']]]]]]]]]]]]l]]]]]]]]]]]]]]\xd3]]]\xd3]\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]]]]]' -'8\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16,Je\x83\xa6a\x80\xa4\x95\x95\x99]]]]]]]]]]::::::::::\xae\xaa\xaa\xd3\x16\x16\xc4\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\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\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\x16' -'\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xd3\x16\x95\x95\x95\x95\x95\x95\x95h\x8b\x95\x95\x95\x95\x99\x9588\x95\x954\x99\x95\x95\x99]]6666666666\x16\x16\x16\xc1\xc1]' -'\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3]m\x16\x0b\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\x16]]]\x95\x99\x95\x95\x99\x95\x95\x99\x99\x99\x95\x99\x99\x95\x99\x95' -'\x95\x95\x99\x95\x99\x95\x99\x95\x99\x95\x95]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\x16]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']\xc8\xc8S]99999999999999999999999999999999999999999999999999999]]\xc79SS' -'S\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8SSSS+]]9\x95\x99\x95\x95]]]9999999999\xc8\xc8\x97\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97]]]]]]]]]]]]]]]' -']\xc8SS]99999999]]99]]9999999999999999999999]9999999]9]]]9999]]\xc7]SS' -'S\xc8\xc8\xc8\xc8]]SS]]SS+]]]]]]]]]S]]]]99]999\xc8\xc8]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1599\x93\x93\xb0\xb0\xb0\xb0Y\xb0\x9d]]]]]' -']]\xc8]]999999]]]]99]]9999999999999999999999]9999999]99]99]99]]\xc7]SS' -'S\xc8\xc8]]]]\xc8\xc8]]\xc8\xc8+]]]]]]]]]]]9999]9]]]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc8\xc8999]]]]]]]]]]]' -']\xc8\xc8S]9999999]9]999]9999999999999999999999]9999999]99]99999]]\xc79SS' -'S\xc8\xc8\xc8\xc8\xc8]\xc8\xc8S]SS+]]9]]]]]]]]]]]]]]]9]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']\xc8SS]99999999]]99]]9999999999999999999999]9999999]99]]9999]]\xc79S\xc8' -'S\xc8\xc8\xc8]]]SS]]SS+]]]]]]]]\xc8S]]]]99]999]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x9d]]]]]]]]]]]]]]]' -']]\xc89]999999]]]999]9999]]]99]9]99]]]99]]]999]]]99999999]999]]]]SS' -'\xc8SS]]]SSS]SSS+]]]]]]]]]S]]]]]]]]]]]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0]]]]]]]]]]]]]' -']SSS]99999999]999]99999999999999999999999]9999999999]99999]]]]\xc8\xc8' -'\xc8SSSS]\xc8\xc8\xc8]\xc8\xc8\xc8+]]]]]]]\xd5E]]]]]]]]]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]99999999]999]99999999999999999999999]9999999999]99999]]]]S\xc8' -'SSSSS]\xc8SS]SS\xc8+]]]]]]]SS]]]]]]]9]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]99999999]999]99999999999999999999999]9999999999999999]]]]SS' -'S\xc8\xc8\xc8]]SSS]SSS+]]]]]]]]]S]]]]]]]]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]999999999999999999]]]999999999999999999999999]999999999]9]]' -'9999999]]]+]]]]SSS\xc8\xc8\xc8]\xc8]SSSSSSSS]]]]]]]]]]]]]]]]]]SS\x97]]]]]]]]]]]' -']999999999999999999999999999999999999999999999999\xc899\xc8\xc8\xc8\xc8\x12\x12+]]]]\x93' -'999999\x03\xc8""""\xc8\xc8\xc8\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97\x97]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']99]9]]99]9]]9]]]]]]9999]9999999]999]9]9]]99]9999\xc899\xc8\xc8\xc8\xc8%%]\xc8\xc89]]' -'99999]\x03]bbbb\xc8\xc8]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]99]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'9\x9d\x9d\x9d\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x9d\x9d\x9d\x9d\x9d\x99\x99\x9d\x9d\x9d\x9d\x9d\x9d\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x9d\x99\x9d\x99\x9d\x1d\xd0\xad\xd0\xadSS' -'99999999]9999999999999999999999999999999999]]]]]]@Z\xc8\x9e\xc8\xc8\xc8\xc8\xc8ZZZZ\xc8S' -'Z\xc8\x95\x95+\x97\x95\x959999]]]]\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8]\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8]\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x99\x9d\x9d\x9d\x9d\x9d\x9d]]\x9d]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'9999999999999999999999999999999999]99999]99]S\xc8\xc8\xc8\xc8S\xc8]]]\xc8\xc7S+]]]]]]' -'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97\x97\x97\x97\x97\x97999999SS\xc8\xc8]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02]]]]]]]]]]99999999999999999999999999999999999999999]]\x97]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]L99999999999999999999999999999999' -'99999999999999999999999999999999999]]]]]999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999]]]]]]' -'9999999]99999999999999999999999999999999999999999999999999999999' -'9999999]9]9999]]9999999]9]9999]]99999999999999999999999999999999' -'9999999]9]9999]]9999999999999999999999999999999]9]9999]]9999999]' -'9]9999]]9999999]9999999]99999999999999999999999]9999999999999999' -'999999999999999]9]9999]]9999999]99999999999999999999999999999999' -'9999999]9999999999999999999]]]]]]\x97\x97\x97\x97\x97\x97\x97\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]99999999999999999999999999999999' -'99999999999999999999999999999999999999999999999999999]]]]]]]]]]]' -']999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'999999999999999999999999999999999999999999999\x97\x9799999999]]]]]]]]]' -'\xaf99999999999999999999999999\xd0\xad]]]99999999999999999999999999999999' -'9999999999999999999999999999999999999999999\x97\x97\x97\xb4\xb4\xb4]]]]]]]]]]]]]]]' -'9999999999999]9999\xc8\xc8+]]]]]]]]]]]999999999999999999\xc8\xc8+\x97\x97]]]]]]]]]' -'999999999999999999\xc8\xc8]]]]]]]]]]]]9999999999999]999]\xc8\xc8]]]]]]]]]]]]' -'9999999999999999999999999999999999999999999999999999SSS\xc8\xc8\xc8\xc8\xc8\xc8\xc8SS' -'SSSSSS\xc8SS\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8+\xc8\x97\x97\x97\x03\x97\x97\x97\x939]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]]]]]]]' -'\xbd\xbd\xbd\xbd\xbd\xbd5\xbd\xbd\xbd\xbd\xc8\xc8\xc8m]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]99999999999999999999999999999999' -'999\x039999999999999999999999999999999999999999999999999999]]]]]]]]' -'99999999999999999999999999999999999999999V]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zzzzzzz]]]]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]' -'zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzz]]\x02\x02\x02\x02\x02\x02]]zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02' -'zzzzzz]]\x02\x02\x02\x02\x02\x02]]zzzzzzzz]\x02]\x02]\x02]\x02zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzz]]' -'zzzzzzzzkkkkkkkkzzzzzzzzkkkkkkkkzzzzzzzzkkkkkkkkzzzzz]zz\x02\x02\x02\x02kQzQ' -'QQzzz]zz\x02\x02\x02\x02kQQQzzzz]]zz\x02\x02\x02\x02]QQQzzzzzzzz\x02\x02\x02\x02\x02QQQ]]zzz]zz\x02\x02\x02\x02kQQ]' -'\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xa1mmu\x01\x8c55\x8c\x8c\x8cG\xbd\xbe0\xd0N\xbe0\xd0NGGG\xbdGGGGXo\x07\x94\x05\x98\xcf\xafT\xaeTT\xaeG\xbd\xbd\xbdRMG\xbd\xbdG\x18' -'\x18\xbd\xbd\xbdi\x91)\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbdi]]]]\xbd]]]]]]]\xafmmmm]]]]]]mmmmmm1z]]\x8e11111\x8a\x8ai\x91)\x8f' -'1\x8e\x8e\x8e\x8e11111\x8a\x8ai\x91)]]]]]]]]]]]]]]]]]\x93\x93\x93\x93\x93\x93\x93\x93\x93\x9a\x93\x93\x1c\x93\x93\x93\x93\x93]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]\x95\x95II\x95\x95\x95\x95III\x95\x95\x8b\x8b\x8b\x8b\x95\x8b\x8b\x8bII\x95\x99\x95I]]]]]]]]]]]]]]]]]]]]]' -'44\x02{4{4\x024{z\x02\x02\x02zz\x02\x02\x02\x8f4\x02{44\x02\x02\x02\x02\x02444{{4\x024q4\x024\x02q\x02\x02Bz\x02\x024\x02z9999z4]]z\x02\x02' -'^iiii\x02zzzz4i]]]]]]]\xac\xac\x9c\x9c\x9c\x9c\x9c\x9c\xac\xac\xac\xac\x9c\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xb4\xb4\xb4\xb4\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xb4\xb4\xb4\xb4\xb4\xb4' -'\xb4\xb4\xb4[]]]]]]]]]]]]\t\t\t\t\t{{{{{ii4444i44i44i4444444i444444444{{444444' -'44444444444444ii44\t4\t444444444444444444{444444444444iiiiiiiiiiii' -'\t^77^ii\t7^^7^^i\ti7\x8a\x8ai7^iii7^^7\t77^^\t^\t^\t\t\t\t77^7^^^^^\t\t\t\ti^i^77^^' -'^^^^^^^^7^^^7iiiii7^^^iiiiiiiii^7\t^i7777^^77ii77^^^^^^^^^^^^^^^^' -'^^77^^77^^^^^ii^^^^ii\tii^\tiiiiiiii^^i\t^^^^^^^^^^^^^^^^^^^iiiii^7' -'iiiiiiiii^^^^^ii^^iiii^^^^^^^^^^^^^^^^^^^^^^^^ii^^^^^^^^^^^^^^^^' -'44444444^^^^444444{4444444444444^^4444444pt44444444444\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d4i444' -'444444444444444444444\x9d44444iiiiiiiiiiiiiiiiiiiiiiiii\xd0\xad\xbd444444444' -'444444444444444]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'444444444444444444444444444444444444444]]]]]]]]]]]]]]]]]]]]]]]]]' -'44444444444]]]]]]]]]]]]]]]]]]]]]\n\n\n\n\n\n\n\n\nWWWWWWWWWWW\n\n\n\n\n\n\n\n\nWWW' -'WWWWWWWW\n\n\n\n\n\n\n\n\nWWWWWWWWWWW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' -'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x9b\xac\xac\xac\xac\xac\xac\xac\xac\xac\xacrrrrrrrrr\xac]' -'{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{' -'{{{{{{{{{{{{4444{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{444444444444' -'{{{{{{{{{{{{{{{{44{{{{4444444444{{4{{{{{{{44444444{{44{\t4444{{44' -'{\t4444{{{44{44{{{{4444444444444444{{{{444444444{44444444iiiiiiii' -'44444{{44{4444{{4444]]44]444{4{444444444444444444444444444444444' -'{4{44444444444444444444444444444{{4{{{4{{{{4{{4\t44444444444444]]' -'4444444444]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']4444]4444]]4444444444444444444444444444]44444444444444444444{44' -'444444444444]4]4444]]]4]4444444]]4444444\x91)\x91)\x91)\x91)\x91)\x91)\x91)rrrrrrrrr\xac' -'\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\x9c\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\x9c4]]]444444444444444444444444]44444444444444]' -']]]]]]]]]]]]]]]]iii^^^^iiiii^^^iii^^^^\x04\xda\x04\xda\x04\xda]]]]iiiiiiiiiiiiiiii' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' -'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' -'iii\x91)\x04\xda\x91)\x91)\x91)\x91)\x91)\x91)\x91)\x91)\x91)ii^^^^^^^^^^^^^^^^^^^^^iiiiiiii^iiiiiii' -'^^^^^^iii^iiii^^^^^i^^ii\x91)\x91)^iiii^i^^^ii^^iiiiiiiiii^^^^^^ii\x91)ii' -'iiiiiiiiii^^^^^^^^^^^^^^^^^^^i^^^^ii^i^ii^i^^^^iiiii^^iiiiii^^^i' -'iiiiiiiiiiiiiiiiiiiiiii^^iiiiiiiiiii^^iiii^^^^i^^ii^^iiii^^^^^^^' -'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ii^^^^^^^^i^^^^^^^^^^^^^^^^^' -'^^^^^^^^^^^^^^^^^^^^^^^iiiii^i^iii^^^^^iiiii^^^iiii^iii^^^^^i^ii' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]]]]]]]]]]]]]]]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]' -'&\x1f\x1f\x1f\xd8OLwptptptptpt\xd8\xd8ptptptpt\\2nn\xd8wwwwwwwww\xa0\xc3\x7f\x06``\\OOOOO\xd8\xd8wwwOL\x1f\xd84' -']LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLL]]>>\x89\x89OOL\\LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLPOOOL' -']]]]]LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]LLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLL]??ssss??????????LLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]LLLLLLLLLLLLLLLL' -'?????????????????????????????]]]ssssssssss??????????????????????' -'????]]]]]]]]]]]]]\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1????????????????????????????]]]?' -'ssssssssss???????????????????????????????????????\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1' -'????????????]]]]???????????????????????????????????????????????]' -'????????????????????????????????????????????????????????????????' -'???????????????????????????????????????????????????????]]]]?????' -'????????????????????????????????????????????????????????????????' -'??????????????????????????????]]???????????????????????????????]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLL]]]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]LLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'zzzzzzz]]]]]]]]]]]]zzzzz]]]]]\xbb\x0e\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\x8a\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb]\xbb\xbb\xbb\xbb\xbb]\xbb]' -'\xbb\xbb]\xbb\xbb]\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xd0\xad' -']]]]]]]]]]]]]]]]\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\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\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\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\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\xd6]]]' -'\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9]]]]]]]]]]]]]]]]\x95\x95\x95\x95]]]]]]]]]]]]\x1f\\\\PP2n2n2n2n2n2' -'n2n2n\x1f\x1f]]\x1f\x1f\x1f\x1fPPP\xcc\x1f\xcc]\x1f\xcc\x1f\x1f\\2n2n2n3\x1f\x1f\xb8_\xb5\xb5\xb5]\x1f\xd23\x1f]]]]\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16]]m' -']\x14\x14\x11\xab\x11\x14\x14\xbc/\x14(v\xb3v\xba\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92v\x14\xdb\xd4\xdb\x14\x14yyyyyyyyyyyyyyyyyyyyyyyyyy\xbc\x14/A\x08' -'A\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\xbc\xd4/\xd4\xbc/\xc2\xc0\x1a\xc2\x10DDDDDDDDDD\xd1DDDDDDDDDDDDDDD' -'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\xd1\xd1DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD]' -"]]DDDDDD]]DDDDDD]]DDDDDD]]DDD]]]\xab\xab\xd4A \xab\xab]'\xb7\xb7\xb7\xb7'']]]]]]]]]]mmm4{]]" -'9999999999999999999999999999999]\xb0\xb0\xb0\xb0]]]]]]]]]]]]9999999999999999' -'9999999999[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02]]zzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzzzzzzzz]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d~~III\x9d\x9d\x9d*~~~~~mmmmmmmm\x99\x99\x99\x99\x99' -'\x99\x99\x99\x9d\x9d\x95\x95\x95\x95\x95\x99\x99\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x95\x95\x95\x95\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzz]zzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02]\x02\x02]]\x02]]\x02\x02]]\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02\x02zzzz]z]zzz' -'z]zz]zzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzz' -'zzzz\x02\x02]\x02\x02\x02\x02]]\x02\x02\x02\x02\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02]\x02\x02\x02\x02]' -'\x02\x02\x02\x02\x02]\x02]]]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzz' -'zzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzz' -'zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02xzzzzzzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzz' -'zzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzz' -'zzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzz' -'zzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzzzzzzzz' -'zzzxzzzzzz]]]]66666666666666666666666666666666666666666666666666' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']m]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' -'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]]' +'\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' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\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' ) def _get_record(code): From cfbolz at codespeak.net Mon Jul 25 13:24:21 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 13:24:21 +0200 (CEST) Subject: [pypy-svn] r15008 - in pypy/dist/pypy: annotation rpython rpython/module rpython/test translator/c translator/c/src Message-ID: <20050725112421.EF19B27B55@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 13:24:20 2005 New Revision: 15008 Added: pypy/dist/pypy/rpython/module/ll_math.py pypy/dist/pypy/translator/c/src/ll_math.h Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/rarithmetic.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rarithmetic.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/g_include.h Log: (pedronis, cfbolz): started to clean up annotation/builtin.py and rpython/rbuiltin.py: all the math functions moved to extfunctable, added ll_math.py, ll_math.h. Still missing: more complicated C implementations. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Mon Jul 25 13:24:20 2005 @@ -220,21 +220,6 @@ def conf(): return SomeString() -def math_fmod(x, y): - return SomeFloat() - -def math_floor(x): - return SomeFloat() - -def math_frexp(x): - return SomeTuple((SomeFloat(), SomeInteger())) - -def math_modf(x): - return SomeTuple((SomeFloat(), SomeFloat())) - -def math_any(*args): - return SomeFloat() - def rarith_intmask(s_obj): return SomeInteger() @@ -293,12 +278,6 @@ # this one is needed otherwise when annotating assert in a test we may try to annotate # py.test AssertionError.__init__ . BUILTIN_ANALYZERS[AssertionError.__init__.im_func] = exception_init -BUILTIN_ANALYZERS[math.fmod] = math_fmod -BUILTIN_ANALYZERS[math.floor] = math_floor -BUILTIN_ANALYZERS[math.exp] = math_any -BUILTIN_ANALYZERS[math.ldexp] = math_any -BUILTIN_ANALYZERS[math.frexp] = math_frexp -BUILTIN_ANALYZERS[math.modf] = math_modf BUILTIN_ANALYZERS[sys.getrefcount] = count BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf import unicodedata Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Mon Jul 25 13:24:20 2005 @@ -5,7 +5,6 @@ import time import math import types -from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat class ExtFuncInfo: @@ -50,26 +49,44 @@ # _____________________________________________________________ -nonefactory = lambda *args: None -tuplefactory = lambda *args: SomeTuple((SomeInteger(),)*10) -frexpfactory = lambda *args: SomeTuple((SomeFloat(),SomeInteger())) + + +def noneannotation(*args): + return None + +def statannotation(*args): + from pypy.annotation.model import SomeInteger, SomeTuple + return SomeTuple((SomeInteger(),)*10) + +def frexpannotation(*args): + from pypy.annotation.model import SomeInteger, SomeTuple, SomeFloat + return SomeTuple((SomeFloat(), SomeInteger())) + +def modfannotation(*args): + from pypy.annotation.model import SomeTuple, SomeFloat + return SomeTuple((SomeFloat(), SomeFloat())) # external function declarations -declare(os.open , int , 'll_os/open') -declare(os.read , str , 'll_os/read') -declare(os.write , int , 'll_os/write') -declare(os.close , nonefactory, 'll_os/close') -declare(os.getcwd , str , 'll_os/getcwd') -declare(os.dup , int , 'll_os/dup') -declare(os.lseek , int , 'll_os/lseek') -declare(os.isatty , bool , 'll_os/isatty') -declare(os.ftruncate, nonefactory, 'll_os/ftruncate') -declare(os.fstat , tuplefactory, 'll_os/fstat') -declare(os.stat , tuplefactory, 'll_os/stat') -declare(time.time , float , 'll_time/time') -declare(time.clock , float , 'll_time/clock') -declare(time.sleep , nonefactory, 'll_time/sleep') -#declare(math.log10 , float , 'll_math/log10') -#declare(math.ceil , float , 'll_math/ceil') -#declare(math.frexp , frexpfactory, 'll_math/frexp') -#declare(math.atan2 , float , 'll_math/atan2') +declare(os.open , int , 'll_os/open') +declare(os.read , str , 'll_os/read') +declare(os.write , int , 'll_os/write') +declare(os.close , noneannotation, 'll_os/close') +declare(os.getcwd , str , 'll_os/getcwd') +declare(os.dup , int , 'll_os/dup') +declare(os.lseek , int , 'll_os/lseek') +declare(os.isatty , bool , 'll_os/isatty') +declare(os.ftruncate, noneannotation, 'll_os/ftruncate') +declare(os.fstat , statannotation, 'll_os/fstat') +declare(os.stat , statannotation, 'll_os/stat') +declare(time.time , float , 'll_time/time') +declare(time.clock , float , 'll_time/clock') +declare(time.sleep , noneannotation, 'll_time/sleep') +declare(math.log10 , float , 'll_math/log10') +declare(math.ceil , float , 'll_math/ceil') +declare(math.frexp , frexpannotation, 'll_math/frexp') +declare(math.atan2 , float , 'll_math/atan2') +declare(math.fmod , float , 'll_math/fmod') +declare(math.floor , float , 'll_math/floor') +declare(math.exp , float , 'll_math/exp') +declare(math.ldexp , float , 'll_math/ldexp') +declare(math.modf , modfannotation, 'll_math/modf') Added: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/ll_math.py Mon Jul 25 13:24:20 2005 @@ -0,0 +1,58 @@ +from pypy.rpython import lltype + +import math + +def ll_math_log10(x): + return math.log10(x) +ll_math_log10.suggested_primitive = True + +def ll_math_ceil(x): + return math.ceil(x) +ll_math_ceil.suggested_primitive = True + + +FREXP_RESULT = lltype.GcStruct('tuple2', ('item0', lltype.Float), + ('item1', lltype.Signed)) + +def ll_frexp_result(mantissa, exponent): + tup = lltype.malloc(FREXP_RESULT) + tup.item0 = mantissa + tup.item1 = exponent + return tup + +def ll_math_frexp(x): + mantissa, exponent = math.frexp(x) + return ll_frexp_result(mantissa, exponent) +ll_math_frexp.suggested_primitive = True + +def ll_math_atan2(x, y): + return math.atan2(x, y) +ll_math_atan2.suggested_primitive = True + +def ll_math_fmod(x, y): + return math.fmod(x, y) +ll_math_fmod.suggested_primitive = True + +def ll_math_floor(x): + return math.floor(x) +ll_math_floor.suggested_primitive = True + +def ll_math_exp(x): + return math.exp(x) + +def ll_math_ldexp(x, y): + return math.ldexp(x, y) + +MODF_RESULT = lltype.GcStruct('tuple2', ('item0', lltype.Float), + ('item1', lltype.Float)) + +def ll_modf_result(fracpart, intpart): + tup = lltype.malloc(MODF_RESULT) + tup.item0 = fracpart + tup.item1 = intpart + return tup + +def ll_math_modf(x): + fracpart, intpart = math.modf(x) + return ll_modf_result(fracpart, intpart) +ll_modf_result.suggested_primitive = True 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 Mon Jul 25 13:24:20 2005 @@ -93,31 +93,34 @@ fieldnames = ['item%d' % i for i in range(n)] lltypes = [Signed]*n fields = tuple(zip(fieldnames, lltypes)) -tup = malloc(GcStruct('tuple%d' % n, *fields)) +STAT_RESULT = GcStruct('tuple%d' % n, *fields) from pypy.rpython.rarithmetic import intmask -def stat_to_rtuple(stat): - #n = len(stat) - tup.item0 = intmask(stat[0]) - tup.item1 = intmask(stat[1]) - tup.item2 = intmask(stat[2]) - tup.item3 = intmask(stat[3]) - tup.item4 = intmask(stat[4]) - tup.item5 = intmask(stat[5]) - tup.item6 = intmask(stat[6]) - tup.item7 = intmask(stat[7]) - tup.item8 = intmask(stat[8]) - tup.item9 = intmask(stat[9]) +def ll_stat_result(stat0, stat1, stat2, stat3, stat4, + stat5, stat6, stat7, stat8, stat9): + tup = malloc(STAT_RESULT) + tup.item0 = intmask(stat0) + tup.item1 = intmask(stat1) + tup.item2 = intmask(stat2) + tup.item3 = intmask(stat3) + tup.item4 = intmask(stat4) + tup.item5 = intmask(stat5) + tup.item6 = intmask(stat6) + tup.item7 = intmask(stat7) + tup.item8 = intmask(stat8) + tup.item9 = intmask(stat9) def ll_os_fstat(fd): - stat = os.fstat(fd) - stat_to_rtuple(stat) - return tup + (stat0, stat1, stat2, stat3, stat4, + stat5, stat6, stat7, stat8, stat9) = os.fstat(fd) + return ll_stat_result(stat0, stat1, stat2, stat3, stat4, + stat5, stat6, stat7, stat8, stat9) ll_os_fstat.suggested_primitive = True def ll_os_stat(path): - stat = os.stat(from_rstr(path)) - stat_to_tuple(stat) - return tup -ll_os_stat.suggested_primitive = True \ No newline at end of file + (stat0, stat1, stat2, stat3, stat4, + stat5, stat6, stat7, stat8, stat9) = os.stat(from_rstr(path)) + return ll_stat_result(stat0, stat1, stat2, stat3, stat4, + stat5, stat6, stat7, stat8, stat9) +ll_os_fstat.suggested_primitive = True Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Mon Jul 25 13:24:20 2005 @@ -196,7 +196,7 @@ def ovfcheck_float_to_int(x): _, intp = math.modf(x) - if FL_MININT <= intp <= FL_MAXINT: + if FL_MININT < intp < FL_MAXINT: return int(intp) raise OverflowError Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 25 13:24:20 2005 @@ -191,14 +191,6 @@ v_errno = hop.inputarg(lltype.Signed, arg=1) r_self.setfield(v_self, 'errno', v_errno, hop.llops) -def rtype_math_floor(hop): - vlist = hop.inputargs(lltype.Float) - return hop.genop('float_floor', vlist, resulttype=lltype.Float) - -def rtype_math_fmod(hop): - vlist = hop.inputargs(lltype.Float, lltype.Float) - return hop.genop('float_fmod', vlist, resulttype=lltype.Float) - def ll_instantiate(typeptr, RESULT): my_instantiate = typeptr.instantiate return lltype.cast_pointer(RESULT, my_instantiate()) @@ -216,10 +208,6 @@ return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) -import math -##def ll_floor(f1): -## return float(int((f1) - # collect all functions import __builtin__ BUILTIN_TYPER = {} @@ -227,8 +215,6 @@ if name.startswith('rtype_builtin_'): original = getattr(__builtin__, name[14:]) BUILTIN_TYPER[original] = value -BUILTIN_TYPER[math.floor] = rtype_math_floor -BUILTIN_TYPER[math.fmod] = rtype_math_fmod BUILTIN_TYPER[Exception.__init__.im_func] = rtype_Exception__init__ BUILTIN_TYPER[AssertionError.__init__.im_func] = rtype_Exception__init__ BUILTIN_TYPER[OSError.__init__.im_func] = rtype_OSError__init__ @@ -291,14 +277,6 @@ import math -def rtype_math_exp(hop): - vlist = hop.inputargs(lltype.Float) - # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR - return hop.llops.gencapicall('exp', vlist, resulttype=lltype.Float, - includes=("math.h",)) # XXX clean up needed - -BUILTIN_TYPER[math.exp] = rtype_math_exp - from pypy.rpython import extfunctable def make_rtype_extfunc(extfuncinfo): 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 Mon Jul 25 13:24:20 2005 @@ -242,10 +242,12 @@ assert ovfcheck_float_to_int(13.0) == 13 assert ovfcheck_float_to_int(-1.0) == -1 assert ovfcheck_float_to_int(-13.0) == -13 - assert ovfcheck_float_to_int(float(sys.maxint-1)) == sys.maxint-1 - assert ovfcheck_float_to_int(float(sys.maxint)) == sys.maxint - assert ovfcheck_float_to_int(float(-sys.maxint)) == -sys.maxint - assert ovfcheck_float_to_int(float(-sys.maxint-1)) == -sys.maxint-1 + # strange things happening for float to int on 64 bit + maxint32 = 2 ** 31 - 1 + assert ovfcheck_float_to_int(float(maxint32-1)) == maxint32-1 + assert ovfcheck_float_to_int(float(maxint32)) == maxint32 + assert ovfcheck_float_to_int(float(-maxint32)) == -maxint32 + assert ovfcheck_float_to_int(float(-maxint32-1)) == -maxint32-1 try: ovfcheck_float_to_int(float(-sys.maxint-1)-1) Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Mon Jul 25 13:24:20 2005 @@ -3,7 +3,7 @@ from pypy.translator.c.support import cdecl from pypy.rpython.rmodel import getfunctionptr from pypy.rpython.rstr import STR -from pypy.rpython.module import ll_os, ll_time +from pypy.rpython.module import ll_os, ll_time, ll_math # table of functions hand-written in src/ll_*.h @@ -15,6 +15,15 @@ ll_os .ll_os_dup: 'LL_os_dup', ll_os .ll_os_getcwd: 'LL_os_getcwd', ll_time.ll_time_clock: 'LL_time_clock', + ll_math.ll_math_log10: 'LL_math_log10', + ll_math.ll_math_ceil: 'LL_math_ceil', + ll_math.ll_math_frexp: 'LL_math_frexp', + ll_math.ll_math_atan2: 'LL_math_atan2', + ll_math.ll_math_fmod : 'LL_math_fmod', + ll_math.ll_math_floor: 'LL_math_floor', + ll_math.ll_math_exp: 'LL_math_exp', + ll_math.ll_math_ldexp: 'LL_math_ldexp', + ll_math.ll_math_modf: 'LL_math_modf', } Modified: pypy/dist/pypy/translator/c/src/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/src/g_include.h (original) +++ pypy/dist/pypy/translator/c/src/g_include.h Mon Jul 25 13:24:20 2005 @@ -27,4 +27,5 @@ # include "src/rtyper.h" # include "src/ll_os.h" # include "src/ll_time.h" +# include "src/ll_math.h" #endif Added: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/ll_math.h Mon Jul 25 13:24:20 2005 @@ -0,0 +1,38 @@ +/************************************************************/ +/*** C header subsection: math module ***/ + +#include "math.h" + +/* The functions below are mapped to functions from pypy.rpython.module.* + by the pypy.translator.c.extfunc.EXTERNALS dictionary. + They should correspond to the functions with the suggested_primitive + flag set. +*/ + + +/* XXX completely ignoring exceptions/error checking for now */ +double LL_math_log10(double x) { + return log10(x); +} +double LL_math_ceil(double x) { + return ceil(x); +} +/* LL_math_frexp XXX strange stuff*/ +double LL_math_atan2(double x, double y) { + return atan2(x, y); +} +double LL_math_fmod(double x, double y) { + return fmod(x, y); +} +double LL_math_floor(double x) { + return floor(x); +} +double LL_math_exp(double x) { + return exp(x); +} +double LL_math_ldexp(double x, long y) { + return ldexp(x, (int) y); +} + +/* LL_math_modf XXXX strange stuff*/ + From cfbolz at codespeak.net Mon Jul 25 13:33:03 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 13:33:03 +0200 (CEST) Subject: [pypy-svn] r15009 - pypy/dist/pypy/rpython/module/test Message-ID: <20050725113303.F110A27B51@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 13:33:03 2005 New Revision: 15009 Added: pypy/dist/pypy/rpython/module/test/test_ll_math.py Log: (pedronis, cfbolz) added tests for ll_math Added: pypy/dist/pypy/rpython/module/test/test_ll_math.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/test/test_ll_math.py Mon Jul 25 13:33:03 2005 @@ -0,0 +1,19 @@ +import math +from pypy.rpython.module.ll_math import * + +def test_ll_math_atan2(): + for x in [0, 1, math.pi, 0.123]: + for y in [0, 1, math.pi, 0.123]: + assert math.atan2(x, y) == ll_math_atan2(x, y) + +def test_ll_modf(): + result = ll_math_modf(10.1) + assert result.item0 == math.modf(10.1)[0] + assert result.item1 == math.modf(10.1)[1] + +def test_ll_frexp(): + result = ll_math_frexp(10.1) + assert result.item0 == math.frexp(10.1)[0] + assert result.item1 == math.frexp(10.1)[1] + + From arigo at codespeak.net Mon Jul 25 13:39:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 13:39:31 +0200 (CEST) Subject: [pypy-svn] r15010 - pypy/dist/pypy/module/unicodedata Message-ID: <20050725113931.BA74E27B51@code1.codespeak.net> Author: arigo Date: Mon Jul 25 13:39:26 2005 New Revision: 15010 Modified: pypy/dist/pypy/module/unicodedata/function.py pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: Changed the _composition table: instead of (int, int) keys it now uses int keys only, which the rtyper can handle. Modified: pypy/dist/pypy/module/unicodedata/function.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/function.py (original) +++ pypy/dist/pypy/module/unicodedata/function.py Mon Jul 25 13:39:26 2005 @@ -209,11 +209,14 @@ # If LV, T -> LVT current = current + (next - TBase) continue - try: - current = unicodedb._composition[(current, next)] - continue - except KeyError: - pass + if (current <= unicodedb._composition_max and + next <= unicodedb._composition_max): + key = current << unicodedb._composition_shift | next + try: + current = unicodedb._composition[key] + continue + except KeyError: + pass if next_combining == 0: # New starter symbol 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 Mon Jul 25 13:39:26 2005 @@ -422,7 +422,8 @@ ''' # Collect the composition pairs. - compositions = {} + compositions = [] + composition_values = [] for code in range(len(table)): unichar = table[code] if (not unichar.decomposition or @@ -431,8 +432,22 @@ len(unichar.decomposition) != 2 or table[unichar.decomposition[0]].combining): continue - compositions[tuple(unichar.decomposition)] = code - writeDict(outfile, '_composition', compositions) + left, right = unichar.decomposition + compositions.append((left, right, code)) + composition_values.append(left) + composition_values.append(right) + composition_max = max(composition_values) + composition_shift = 1 + while (1 << composition_shift) <= composition_max: + composition_shift += 1 + print >> outfile, '_composition_max = %d' % composition_max + print >> outfile, '_composition_shift = %d' % composition_shift + print >> outfile, '_composition = {' + for left, right, code in compositions: + print >> outfile, '%5d << %d | %5d: %5d,' % ( + left, composition_shift, right, code) + print >> outfile, '}' + print >> outfile decomposition = {} for code in range(len(table)): Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Mon Jul 25 13:39:26 2005 @@ -23052,924 +23052,926 @@ return _raw_decomposition.get(code,'') +_composition_max = 12541 +_composition_shift = 14 _composition = { -(60, 824): 8814, -(61, 824): 8800, -(62, 824): 8815, -(65, 768): 192, -(65, 769): 193, -(65, 770): 194, -(65, 771): 195, -(65, 772): 256, -(65, 774): 258, -(65, 775): 550, -(65, 776): 196, -(65, 777): 7842, -(65, 778): 197, -(65, 780): 461, -(65, 783): 512, -(65, 785): 514, -(65, 803): 7840, -(65, 805): 7680, -(65, 808): 260, -(66, 775): 7682, -(66, 803): 7684, -(66, 817): 7686, -(67, 769): 262, -(67, 770): 264, -(67, 775): 266, -(67, 780): 268, -(67, 807): 199, -(68, 775): 7690, -(68, 780): 270, -(68, 803): 7692, -(68, 807): 7696, -(68, 813): 7698, -(68, 817): 7694, -(69, 768): 200, -(69, 769): 201, -(69, 770): 202, -(69, 771): 7868, -(69, 772): 274, -(69, 774): 276, -(69, 775): 278, -(69, 776): 203, -(69, 777): 7866, -(69, 780): 282, -(69, 783): 516, -(69, 785): 518, -(69, 803): 7864, -(69, 807): 552, -(69, 808): 280, -(69, 813): 7704, -(69, 816): 7706, -(70, 775): 7710, -(71, 769): 500, -(71, 770): 284, -(71, 772): 7712, -(71, 774): 286, -(71, 775): 288, -(71, 780): 486, -(71, 807): 290, -(72, 770): 292, -(72, 775): 7714, -(72, 776): 7718, -(72, 780): 542, -(72, 803): 7716, -(72, 807): 7720, -(72, 814): 7722, -(73, 768): 204, -(73, 769): 205, -(73, 770): 206, -(73, 771): 296, -(73, 772): 298, -(73, 774): 300, -(73, 775): 304, -(73, 776): 207, -(73, 777): 7880, -(73, 780): 463, -(73, 783): 520, -(73, 785): 522, -(73, 803): 7882, -(73, 808): 302, -(73, 816): 7724, -(74, 770): 308, -(75, 769): 7728, -(75, 780): 488, -(75, 803): 7730, -(75, 807): 310, -(75, 817): 7732, -(76, 769): 313, -(76, 780): 317, -(76, 803): 7734, -(76, 807): 315, -(76, 813): 7740, -(76, 817): 7738, -(77, 769): 7742, -(77, 775): 7744, -(77, 803): 7746, -(78, 768): 504, -(78, 769): 323, -(78, 771): 209, -(78, 775): 7748, -(78, 780): 327, -(78, 803): 7750, -(78, 807): 325, -(78, 813): 7754, -(78, 817): 7752, -(79, 768): 210, -(79, 769): 211, -(79, 770): 212, -(79, 771): 213, -(79, 772): 332, -(79, 774): 334, -(79, 775): 558, -(79, 776): 214, -(79, 777): 7886, -(79, 779): 336, -(79, 780): 465, -(79, 783): 524, -(79, 785): 526, -(79, 795): 416, -(79, 803): 7884, -(79, 808): 490, -(80, 769): 7764, -(80, 775): 7766, -(82, 769): 340, -(82, 775): 7768, -(82, 780): 344, -(82, 783): 528, -(82, 785): 530, -(82, 803): 7770, -(82, 807): 342, -(82, 817): 7774, -(83, 769): 346, -(83, 770): 348, -(83, 775): 7776, -(83, 780): 352, -(83, 803): 7778, -(83, 806): 536, -(83, 807): 350, -(84, 775): 7786, -(84, 780): 356, -(84, 803): 7788, -(84, 806): 538, -(84, 807): 354, -(84, 813): 7792, -(84, 817): 7790, -(85, 768): 217, -(85, 769): 218, -(85, 770): 219, -(85, 771): 360, -(85, 772): 362, -(85, 774): 364, -(85, 776): 220, -(85, 777): 7910, -(85, 778): 366, -(85, 779): 368, -(85, 780): 467, -(85, 783): 532, -(85, 785): 534, -(85, 795): 431, -(85, 803): 7908, -(85, 804): 7794, -(85, 808): 370, -(85, 813): 7798, -(85, 816): 7796, -(86, 771): 7804, -(86, 803): 7806, -(87, 768): 7808, -(87, 769): 7810, -(87, 770): 372, -(87, 775): 7814, -(87, 776): 7812, -(87, 803): 7816, -(88, 775): 7818, -(88, 776): 7820, -(89, 768): 7922, -(89, 769): 221, -(89, 770): 374, -(89, 771): 7928, -(89, 772): 562, -(89, 775): 7822, -(89, 776): 376, -(89, 777): 7926, -(89, 803): 7924, -(90, 769): 377, -(90, 770): 7824, -(90, 775): 379, -(90, 780): 381, -(90, 803): 7826, -(90, 817): 7828, -(97, 768): 224, -(97, 769): 225, -(97, 770): 226, -(97, 771): 227, -(97, 772): 257, -(97, 774): 259, -(97, 775): 551, -(97, 776): 228, -(97, 777): 7843, -(97, 778): 229, -(97, 780): 462, -(97, 783): 513, -(97, 785): 515, -(97, 803): 7841, -(97, 805): 7681, -(97, 808): 261, -(98, 775): 7683, -(98, 803): 7685, -(98, 817): 7687, -(99, 769): 263, -(99, 770): 265, -(99, 775): 267, -(99, 780): 269, -(99, 807): 231, -(100, 775): 7691, -(100, 780): 271, -(100, 803): 7693, -(100, 807): 7697, -(100, 813): 7699, -(100, 817): 7695, -(101, 768): 232, -(101, 769): 233, -(101, 770): 234, -(101, 771): 7869, -(101, 772): 275, -(101, 774): 277, -(101, 775): 279, -(101, 776): 235, -(101, 777): 7867, -(101, 780): 283, -(101, 783): 517, -(101, 785): 519, -(101, 803): 7865, -(101, 807): 553, -(101, 808): 281, -(101, 813): 7705, -(101, 816): 7707, -(102, 775): 7711, -(103, 769): 501, -(103, 770): 285, -(103, 772): 7713, -(103, 774): 287, -(103, 775): 289, -(103, 780): 487, -(103, 807): 291, -(104, 770): 293, -(104, 775): 7715, -(104, 776): 7719, -(104, 780): 543, -(104, 803): 7717, -(104, 807): 7721, -(104, 814): 7723, -(104, 817): 7830, -(105, 768): 236, -(105, 769): 237, -(105, 770): 238, -(105, 771): 297, -(105, 772): 299, -(105, 774): 301, -(105, 776): 239, -(105, 777): 7881, -(105, 780): 464, -(105, 783): 521, -(105, 785): 523, -(105, 803): 7883, -(105, 808): 303, -(105, 816): 7725, -(106, 770): 309, -(106, 780): 496, -(107, 769): 7729, -(107, 780): 489, -(107, 803): 7731, -(107, 807): 311, -(107, 817): 7733, -(108, 769): 314, -(108, 780): 318, -(108, 803): 7735, -(108, 807): 316, -(108, 813): 7741, -(108, 817): 7739, -(109, 769): 7743, -(109, 775): 7745, -(109, 803): 7747, -(110, 768): 505, -(110, 769): 324, -(110, 771): 241, -(110, 775): 7749, -(110, 780): 328, -(110, 803): 7751, -(110, 807): 326, -(110, 813): 7755, -(110, 817): 7753, -(111, 768): 242, -(111, 769): 243, -(111, 770): 244, -(111, 771): 245, -(111, 772): 333, -(111, 774): 335, -(111, 775): 559, -(111, 776): 246, -(111, 777): 7887, -(111, 779): 337, -(111, 780): 466, -(111, 783): 525, -(111, 785): 527, -(111, 795): 417, -(111, 803): 7885, -(111, 808): 491, -(112, 769): 7765, -(112, 775): 7767, -(114, 769): 341, -(114, 775): 7769, -(114, 780): 345, -(114, 783): 529, -(114, 785): 531, -(114, 803): 7771, -(114, 807): 343, -(114, 817): 7775, -(115, 769): 347, -(115, 770): 349, -(115, 775): 7777, -(115, 780): 353, -(115, 803): 7779, -(115, 806): 537, -(115, 807): 351, -(116, 775): 7787, -(116, 776): 7831, -(116, 780): 357, -(116, 803): 7789, -(116, 806): 539, -(116, 807): 355, -(116, 813): 7793, -(116, 817): 7791, -(117, 768): 249, -(117, 769): 250, -(117, 770): 251, -(117, 771): 361, -(117, 772): 363, -(117, 774): 365, -(117, 776): 252, -(117, 777): 7911, -(117, 778): 367, -(117, 779): 369, -(117, 780): 468, -(117, 783): 533, -(117, 785): 535, -(117, 795): 432, -(117, 803): 7909, -(117, 804): 7795, -(117, 808): 371, -(117, 813): 7799, -(117, 816): 7797, -(118, 771): 7805, -(118, 803): 7807, -(119, 768): 7809, -(119, 769): 7811, -(119, 770): 373, -(119, 775): 7815, -(119, 776): 7813, -(119, 778): 7832, -(119, 803): 7817, -(120, 775): 7819, -(120, 776): 7821, -(121, 768): 7923, -(121, 769): 253, -(121, 770): 375, -(121, 771): 7929, -(121, 772): 563, -(121, 775): 7823, -(121, 776): 255, -(121, 777): 7927, -(121, 778): 7833, -(121, 803): 7925, -(122, 769): 378, -(122, 770): 7825, -(122, 775): 380, -(122, 780): 382, -(122, 803): 7827, -(122, 817): 7829, -(168, 768): 8173, -(168, 769): 901, -(168, 834): 8129, -(194, 768): 7846, -(194, 769): 7844, -(194, 771): 7850, -(194, 777): 7848, -(196, 772): 478, -(197, 769): 506, -(198, 769): 508, -(198, 772): 482, -(199, 769): 7688, -(202, 768): 7872, -(202, 769): 7870, -(202, 771): 7876, -(202, 777): 7874, -(207, 769): 7726, -(212, 768): 7890, -(212, 769): 7888, -(212, 771): 7894, -(212, 777): 7892, -(213, 769): 7756, -(213, 772): 556, -(213, 776): 7758, -(214, 772): 554, -(216, 769): 510, -(220, 768): 475, -(220, 769): 471, -(220, 772): 469, -(220, 780): 473, -(226, 768): 7847, -(226, 769): 7845, -(226, 771): 7851, -(226, 777): 7849, -(228, 772): 479, -(229, 769): 507, -(230, 769): 509, -(230, 772): 483, -(231, 769): 7689, -(234, 768): 7873, -(234, 769): 7871, -(234, 771): 7877, -(234, 777): 7875, -(239, 769): 7727, -(244, 768): 7891, -(244, 769): 7889, -(244, 771): 7895, -(244, 777): 7893, -(245, 769): 7757, -(245, 772): 557, -(245, 776): 7759, -(246, 772): 555, -(248, 769): 511, -(252, 768): 476, -(252, 769): 472, -(252, 772): 470, -(252, 780): 474, -(258, 768): 7856, -(258, 769): 7854, -(258, 771): 7860, -(258, 777): 7858, -(259, 768): 7857, -(259, 769): 7855, -(259, 771): 7861, -(259, 777): 7859, -(274, 768): 7700, -(274, 769): 7702, -(275, 768): 7701, -(275, 769): 7703, -(332, 768): 7760, -(332, 769): 7762, -(333, 768): 7761, -(333, 769): 7763, -(346, 775): 7780, -(347, 775): 7781, -(352, 775): 7782, -(353, 775): 7783, -(360, 769): 7800, -(361, 769): 7801, -(362, 776): 7802, -(363, 776): 7803, -(383, 775): 7835, -(416, 768): 7900, -(416, 769): 7898, -(416, 771): 7904, -(416, 777): 7902, -(416, 803): 7906, -(417, 768): 7901, -(417, 769): 7899, -(417, 771): 7905, -(417, 777): 7903, -(417, 803): 7907, -(431, 768): 7914, -(431, 769): 7912, -(431, 771): 7918, -(431, 777): 7916, -(431, 803): 7920, -(432, 768): 7915, -(432, 769): 7913, -(432, 771): 7919, -(432, 777): 7917, -(432, 803): 7921, -(439, 780): 494, -(490, 772): 492, -(491, 772): 493, -(550, 772): 480, -(551, 772): 481, -(552, 774): 7708, -(553, 774): 7709, -(558, 772): 560, -(559, 772): 561, -(658, 780): 495, -(913, 768): 8122, -(913, 769): 902, -(913, 772): 8121, -(913, 774): 8120, -(913, 787): 7944, -(913, 788): 7945, -(913, 837): 8124, -(917, 768): 8136, -(917, 769): 904, -(917, 787): 7960, -(917, 788): 7961, -(919, 768): 8138, -(919, 769): 905, -(919, 787): 7976, -(919, 788): 7977, -(919, 837): 8140, -(921, 768): 8154, -(921, 769): 906, -(921, 772): 8153, -(921, 774): 8152, -(921, 776): 938, -(921, 787): 7992, -(921, 788): 7993, -(927, 768): 8184, -(927, 769): 908, -(927, 787): 8008, -(927, 788): 8009, -(929, 788): 8172, -(933, 768): 8170, -(933, 769): 910, -(933, 772): 8169, -(933, 774): 8168, -(933, 776): 939, -(933, 788): 8025, -(937, 768): 8186, -(937, 769): 911, -(937, 787): 8040, -(937, 788): 8041, -(937, 837): 8188, -(940, 837): 8116, -(942, 837): 8132, -(945, 768): 8048, -(945, 769): 940, -(945, 772): 8113, -(945, 774): 8112, -(945, 787): 7936, -(945, 788): 7937, -(945, 834): 8118, -(945, 837): 8115, -(949, 768): 8050, -(949, 769): 941, -(949, 787): 7952, -(949, 788): 7953, -(951, 768): 8052, -(951, 769): 942, -(951, 787): 7968, -(951, 788): 7969, -(951, 834): 8134, -(951, 837): 8131, -(953, 768): 8054, -(953, 769): 943, -(953, 772): 8145, -(953, 774): 8144, -(953, 776): 970, -(953, 787): 7984, -(953, 788): 7985, -(953, 834): 8150, -(959, 768): 8056, -(959, 769): 972, -(959, 787): 8000, -(959, 788): 8001, -(961, 787): 8164, -(961, 788): 8165, -(965, 768): 8058, -(965, 769): 973, -(965, 772): 8161, -(965, 774): 8160, -(965, 776): 971, -(965, 787): 8016, -(965, 788): 8017, -(965, 834): 8166, -(969, 768): 8060, -(969, 769): 974, -(969, 787): 8032, -(969, 788): 8033, -(969, 834): 8182, -(969, 837): 8179, -(970, 768): 8146, -(970, 769): 912, -(970, 834): 8151, -(971, 768): 8162, -(971, 769): 944, -(971, 834): 8167, -(974, 837): 8180, -(978, 769): 979, -(978, 776): 980, -(1030, 776): 1031, -(1040, 774): 1232, -(1040, 776): 1234, -(1043, 769): 1027, -(1045, 768): 1024, -(1045, 774): 1238, -(1045, 776): 1025, -(1046, 774): 1217, -(1046, 776): 1244, -(1047, 776): 1246, -(1048, 768): 1037, -(1048, 772): 1250, -(1048, 774): 1049, -(1048, 776): 1252, -(1050, 769): 1036, -(1054, 776): 1254, -(1059, 772): 1262, -(1059, 774): 1038, -(1059, 776): 1264, -(1059, 779): 1266, -(1063, 776): 1268, -(1067, 776): 1272, -(1069, 776): 1260, -(1072, 774): 1233, -(1072, 776): 1235, -(1075, 769): 1107, -(1077, 768): 1104, -(1077, 774): 1239, -(1077, 776): 1105, -(1078, 774): 1218, -(1078, 776): 1245, -(1079, 776): 1247, -(1080, 768): 1117, -(1080, 772): 1251, -(1080, 774): 1081, -(1080, 776): 1253, -(1082, 769): 1116, -(1086, 776): 1255, -(1091, 772): 1263, -(1091, 774): 1118, -(1091, 776): 1265, -(1091, 779): 1267, -(1095, 776): 1269, -(1099, 776): 1273, -(1101, 776): 1261, -(1110, 776): 1111, -(1140, 783): 1142, -(1141, 783): 1143, -(1240, 776): 1242, -(1241, 776): 1243, -(1256, 776): 1258, -(1257, 776): 1259, -(1575, 1619): 1570, -(1575, 1620): 1571, -(1575, 1621): 1573, -(1608, 1620): 1572, -(1610, 1620): 1574, -(1729, 1620): 1730, -(1746, 1620): 1747, -(1749, 1620): 1728, -(2344, 2364): 2345, -(2352, 2364): 2353, -(2355, 2364): 2356, -(2503, 2494): 2507, -(2503, 2519): 2508, -(2887, 2878): 2891, -(2887, 2902): 2888, -(2887, 2903): 2892, -(2962, 3031): 2964, -(3014, 3006): 3018, -(3014, 3031): 3020, -(3015, 3006): 3019, -(3142, 3158): 3144, -(3263, 3285): 3264, -(3270, 3266): 3274, -(3270, 3285): 3271, -(3270, 3286): 3272, -(3274, 3285): 3275, -(3398, 3390): 3402, -(3398, 3415): 3404, -(3399, 3390): 3403, -(3545, 3530): 3546, -(3545, 3535): 3548, -(3545, 3551): 3550, -(3548, 3530): 3549, -(4133, 4142): 4134, -(7734, 772): 7736, -(7735, 772): 7737, -(7770, 772): 7772, -(7771, 772): 7773, -(7778, 775): 7784, -(7779, 775): 7785, -(7840, 770): 7852, -(7840, 774): 7862, -(7841, 770): 7853, -(7841, 774): 7863, -(7864, 770): 7878, -(7865, 770): 7879, -(7884, 770): 7896, -(7885, 770): 7897, -(7936, 768): 7938, -(7936, 769): 7940, -(7936, 834): 7942, -(7936, 837): 8064, -(7937, 768): 7939, -(7937, 769): 7941, -(7937, 834): 7943, -(7937, 837): 8065, -(7938, 837): 8066, -(7939, 837): 8067, -(7940, 837): 8068, -(7941, 837): 8069, -(7942, 837): 8070, -(7943, 837): 8071, -(7944, 768): 7946, -(7944, 769): 7948, -(7944, 834): 7950, -(7944, 837): 8072, -(7945, 768): 7947, -(7945, 769): 7949, -(7945, 834): 7951, -(7945, 837): 8073, -(7946, 837): 8074, -(7947, 837): 8075, -(7948, 837): 8076, -(7949, 837): 8077, -(7950, 837): 8078, -(7951, 837): 8079, -(7952, 768): 7954, -(7952, 769): 7956, -(7953, 768): 7955, -(7953, 769): 7957, -(7960, 768): 7962, -(7960, 769): 7964, -(7961, 768): 7963, -(7961, 769): 7965, -(7968, 768): 7970, -(7968, 769): 7972, -(7968, 834): 7974, -(7968, 837): 8080, -(7969, 768): 7971, -(7969, 769): 7973, -(7969, 834): 7975, -(7969, 837): 8081, -(7970, 837): 8082, -(7971, 837): 8083, -(7972, 837): 8084, -(7973, 837): 8085, -(7974, 837): 8086, -(7975, 837): 8087, -(7976, 768): 7978, -(7976, 769): 7980, -(7976, 834): 7982, -(7976, 837): 8088, -(7977, 768): 7979, -(7977, 769): 7981, -(7977, 834): 7983, -(7977, 837): 8089, -(7978, 837): 8090, -(7979, 837): 8091, -(7980, 837): 8092, -(7981, 837): 8093, -(7982, 837): 8094, -(7983, 837): 8095, -(7984, 768): 7986, -(7984, 769): 7988, -(7984, 834): 7990, -(7985, 768): 7987, -(7985, 769): 7989, -(7985, 834): 7991, -(7992, 768): 7994, -(7992, 769): 7996, -(7992, 834): 7998, -(7993, 768): 7995, -(7993, 769): 7997, -(7993, 834): 7999, -(8000, 768): 8002, -(8000, 769): 8004, -(8001, 768): 8003, -(8001, 769): 8005, -(8008, 768): 8010, -(8008, 769): 8012, -(8009, 768): 8011, -(8009, 769): 8013, -(8016, 768): 8018, -(8016, 769): 8020, -(8016, 834): 8022, -(8017, 768): 8019, -(8017, 769): 8021, -(8017, 834): 8023, -(8025, 768): 8027, -(8025, 769): 8029, -(8025, 834): 8031, -(8032, 768): 8034, -(8032, 769): 8036, -(8032, 834): 8038, -(8032, 837): 8096, -(8033, 768): 8035, -(8033, 769): 8037, -(8033, 834): 8039, -(8033, 837): 8097, -(8034, 837): 8098, -(8035, 837): 8099, -(8036, 837): 8100, -(8037, 837): 8101, -(8038, 837): 8102, -(8039, 837): 8103, -(8040, 768): 8042, -(8040, 769): 8044, -(8040, 834): 8046, -(8040, 837): 8104, -(8041, 768): 8043, -(8041, 769): 8045, -(8041, 834): 8047, -(8041, 837): 8105, -(8042, 837): 8106, -(8043, 837): 8107, -(8044, 837): 8108, -(8045, 837): 8109, -(8046, 837): 8110, -(8047, 837): 8111, -(8048, 837): 8114, -(8052, 837): 8130, -(8060, 837): 8178, -(8118, 837): 8119, -(8127, 768): 8141, -(8127, 769): 8142, -(8127, 834): 8143, -(8134, 837): 8135, -(8182, 837): 8183, -(8190, 768): 8157, -(8190, 769): 8158, -(8190, 834): 8159, -(8592, 824): 8602, -(8594, 824): 8603, -(8596, 824): 8622, -(8656, 824): 8653, -(8658, 824): 8655, -(8660, 824): 8654, -(8707, 824): 8708, -(8712, 824): 8713, -(8715, 824): 8716, -(8739, 824): 8740, -(8741, 824): 8742, -(8764, 824): 8769, -(8771, 824): 8772, -(8773, 824): 8775, -(8776, 824): 8777, -(8781, 824): 8813, -(8801, 824): 8802, -(8804, 824): 8816, -(8805, 824): 8817, -(8818, 824): 8820, -(8819, 824): 8821, -(8822, 824): 8824, -(8823, 824): 8825, -(8826, 824): 8832, -(8827, 824): 8833, -(8828, 824): 8928, -(8829, 824): 8929, -(8834, 824): 8836, -(8835, 824): 8837, -(8838, 824): 8840, -(8839, 824): 8841, -(8849, 824): 8930, -(8850, 824): 8931, -(8866, 824): 8876, -(8872, 824): 8877, -(8873, 824): 8878, -(8875, 824): 8879, -(8882, 824): 8938, -(8883, 824): 8939, -(8884, 824): 8940, -(8885, 824): 8941, -(12358, 12441): 12436, -(12363, 12441): 12364, -(12365, 12441): 12366, -(12367, 12441): 12368, -(12369, 12441): 12370, -(12371, 12441): 12372, -(12373, 12441): 12374, -(12375, 12441): 12376, -(12377, 12441): 12378, -(12379, 12441): 12380, -(12381, 12441): 12382, -(12383, 12441): 12384, -(12385, 12441): 12386, -(12388, 12441): 12389, -(12390, 12441): 12391, -(12392, 12441): 12393, -(12399, 12441): 12400, -(12399, 12442): 12401, -(12402, 12441): 12403, -(12402, 12442): 12404, -(12405, 12441): 12406, -(12405, 12442): 12407, -(12408, 12441): 12409, -(12408, 12442): 12410, -(12411, 12441): 12412, -(12411, 12442): 12413, -(12445, 12441): 12446, -(12454, 12441): 12532, -(12459, 12441): 12460, -(12461, 12441): 12462, -(12463, 12441): 12464, -(12465, 12441): 12466, -(12467, 12441): 12468, -(12469, 12441): 12470, -(12471, 12441): 12472, -(12473, 12441): 12474, -(12475, 12441): 12476, -(12477, 12441): 12478, -(12479, 12441): 12480, -(12481, 12441): 12482, -(12484, 12441): 12485, -(12486, 12441): 12487, -(12488, 12441): 12489, -(12495, 12441): 12496, -(12495, 12442): 12497, -(12498, 12441): 12499, -(12498, 12442): 12500, -(12501, 12441): 12502, -(12501, 12442): 12503, -(12504, 12441): 12505, -(12504, 12442): 12506, -(12507, 12441): 12508, -(12507, 12442): 12509, -(12527, 12441): 12535, -(12528, 12441): 12536, -(12529, 12441): 12537, -(12530, 12441): 12538, -(12541, 12441): 12542, + 65 << 14 | 768: 192, + 65 << 14 | 769: 193, + 65 << 14 | 770: 194, + 65 << 14 | 771: 195, + 65 << 14 | 776: 196, + 65 << 14 | 778: 197, + 67 << 14 | 807: 199, + 69 << 14 | 768: 200, + 69 << 14 | 769: 201, + 69 << 14 | 770: 202, + 69 << 14 | 776: 203, + 73 << 14 | 768: 204, + 73 << 14 | 769: 205, + 73 << 14 | 770: 206, + 73 << 14 | 776: 207, + 78 << 14 | 771: 209, + 79 << 14 | 768: 210, + 79 << 14 | 769: 211, + 79 << 14 | 770: 212, + 79 << 14 | 771: 213, + 79 << 14 | 776: 214, + 85 << 14 | 768: 217, + 85 << 14 | 769: 218, + 85 << 14 | 770: 219, + 85 << 14 | 776: 220, + 89 << 14 | 769: 221, + 97 << 14 | 768: 224, + 97 << 14 | 769: 225, + 97 << 14 | 770: 226, + 97 << 14 | 771: 227, + 97 << 14 | 776: 228, + 97 << 14 | 778: 229, + 99 << 14 | 807: 231, + 101 << 14 | 768: 232, + 101 << 14 | 769: 233, + 101 << 14 | 770: 234, + 101 << 14 | 776: 235, + 105 << 14 | 768: 236, + 105 << 14 | 769: 237, + 105 << 14 | 770: 238, + 105 << 14 | 776: 239, + 110 << 14 | 771: 241, + 111 << 14 | 768: 242, + 111 << 14 | 769: 243, + 111 << 14 | 770: 244, + 111 << 14 | 771: 245, + 111 << 14 | 776: 246, + 117 << 14 | 768: 249, + 117 << 14 | 769: 250, + 117 << 14 | 770: 251, + 117 << 14 | 776: 252, + 121 << 14 | 769: 253, + 121 << 14 | 776: 255, + 65 << 14 | 772: 256, + 97 << 14 | 772: 257, + 65 << 14 | 774: 258, + 97 << 14 | 774: 259, + 65 << 14 | 808: 260, + 97 << 14 | 808: 261, + 67 << 14 | 769: 262, + 99 << 14 | 769: 263, + 67 << 14 | 770: 264, + 99 << 14 | 770: 265, + 67 << 14 | 775: 266, + 99 << 14 | 775: 267, + 67 << 14 | 780: 268, + 99 << 14 | 780: 269, + 68 << 14 | 780: 270, + 100 << 14 | 780: 271, + 69 << 14 | 772: 274, + 101 << 14 | 772: 275, + 69 << 14 | 774: 276, + 101 << 14 | 774: 277, + 69 << 14 | 775: 278, + 101 << 14 | 775: 279, + 69 << 14 | 808: 280, + 101 << 14 | 808: 281, + 69 << 14 | 780: 282, + 101 << 14 | 780: 283, + 71 << 14 | 770: 284, + 103 << 14 | 770: 285, + 71 << 14 | 774: 286, + 103 << 14 | 774: 287, + 71 << 14 | 775: 288, + 103 << 14 | 775: 289, + 71 << 14 | 807: 290, + 103 << 14 | 807: 291, + 72 << 14 | 770: 292, + 104 << 14 | 770: 293, + 73 << 14 | 771: 296, + 105 << 14 | 771: 297, + 73 << 14 | 772: 298, + 105 << 14 | 772: 299, + 73 << 14 | 774: 300, + 105 << 14 | 774: 301, + 73 << 14 | 808: 302, + 105 << 14 | 808: 303, + 73 << 14 | 775: 304, + 74 << 14 | 770: 308, + 106 << 14 | 770: 309, + 75 << 14 | 807: 310, + 107 << 14 | 807: 311, + 76 << 14 | 769: 313, + 108 << 14 | 769: 314, + 76 << 14 | 807: 315, + 108 << 14 | 807: 316, + 76 << 14 | 780: 317, + 108 << 14 | 780: 318, + 78 << 14 | 769: 323, + 110 << 14 | 769: 324, + 78 << 14 | 807: 325, + 110 << 14 | 807: 326, + 78 << 14 | 780: 327, + 110 << 14 | 780: 328, + 79 << 14 | 772: 332, + 111 << 14 | 772: 333, + 79 << 14 | 774: 334, + 111 << 14 | 774: 335, + 79 << 14 | 779: 336, + 111 << 14 | 779: 337, + 82 << 14 | 769: 340, + 114 << 14 | 769: 341, + 82 << 14 | 807: 342, + 114 << 14 | 807: 343, + 82 << 14 | 780: 344, + 114 << 14 | 780: 345, + 83 << 14 | 769: 346, + 115 << 14 | 769: 347, + 83 << 14 | 770: 348, + 115 << 14 | 770: 349, + 83 << 14 | 807: 350, + 115 << 14 | 807: 351, + 83 << 14 | 780: 352, + 115 << 14 | 780: 353, + 84 << 14 | 807: 354, + 116 << 14 | 807: 355, + 84 << 14 | 780: 356, + 116 << 14 | 780: 357, + 85 << 14 | 771: 360, + 117 << 14 | 771: 361, + 85 << 14 | 772: 362, + 117 << 14 | 772: 363, + 85 << 14 | 774: 364, + 117 << 14 | 774: 365, + 85 << 14 | 778: 366, + 117 << 14 | 778: 367, + 85 << 14 | 779: 368, + 117 << 14 | 779: 369, + 85 << 14 | 808: 370, + 117 << 14 | 808: 371, + 87 << 14 | 770: 372, + 119 << 14 | 770: 373, + 89 << 14 | 770: 374, + 121 << 14 | 770: 375, + 89 << 14 | 776: 376, + 90 << 14 | 769: 377, + 122 << 14 | 769: 378, + 90 << 14 | 775: 379, + 122 << 14 | 775: 380, + 90 << 14 | 780: 381, + 122 << 14 | 780: 382, + 79 << 14 | 795: 416, + 111 << 14 | 795: 417, + 85 << 14 | 795: 431, + 117 << 14 | 795: 432, + 65 << 14 | 780: 461, + 97 << 14 | 780: 462, + 73 << 14 | 780: 463, + 105 << 14 | 780: 464, + 79 << 14 | 780: 465, + 111 << 14 | 780: 466, + 85 << 14 | 780: 467, + 117 << 14 | 780: 468, + 220 << 14 | 772: 469, + 252 << 14 | 772: 470, + 220 << 14 | 769: 471, + 252 << 14 | 769: 472, + 220 << 14 | 780: 473, + 252 << 14 | 780: 474, + 220 << 14 | 768: 475, + 252 << 14 | 768: 476, + 196 << 14 | 772: 478, + 228 << 14 | 772: 479, + 550 << 14 | 772: 480, + 551 << 14 | 772: 481, + 198 << 14 | 772: 482, + 230 << 14 | 772: 483, + 71 << 14 | 780: 486, + 103 << 14 | 780: 487, + 75 << 14 | 780: 488, + 107 << 14 | 780: 489, + 79 << 14 | 808: 490, + 111 << 14 | 808: 491, + 490 << 14 | 772: 492, + 491 << 14 | 772: 493, + 439 << 14 | 780: 494, + 658 << 14 | 780: 495, + 106 << 14 | 780: 496, + 71 << 14 | 769: 500, + 103 << 14 | 769: 501, + 78 << 14 | 768: 504, + 110 << 14 | 768: 505, + 197 << 14 | 769: 506, + 229 << 14 | 769: 507, + 198 << 14 | 769: 508, + 230 << 14 | 769: 509, + 216 << 14 | 769: 510, + 248 << 14 | 769: 511, + 65 << 14 | 783: 512, + 97 << 14 | 783: 513, + 65 << 14 | 785: 514, + 97 << 14 | 785: 515, + 69 << 14 | 783: 516, + 101 << 14 | 783: 517, + 69 << 14 | 785: 518, + 101 << 14 | 785: 519, + 73 << 14 | 783: 520, + 105 << 14 | 783: 521, + 73 << 14 | 785: 522, + 105 << 14 | 785: 523, + 79 << 14 | 783: 524, + 111 << 14 | 783: 525, + 79 << 14 | 785: 526, + 111 << 14 | 785: 527, + 82 << 14 | 783: 528, + 114 << 14 | 783: 529, + 82 << 14 | 785: 530, + 114 << 14 | 785: 531, + 85 << 14 | 783: 532, + 117 << 14 | 783: 533, + 85 << 14 | 785: 534, + 117 << 14 | 785: 535, + 83 << 14 | 806: 536, + 115 << 14 | 806: 537, + 84 << 14 | 806: 538, + 116 << 14 | 806: 539, + 72 << 14 | 780: 542, + 104 << 14 | 780: 543, + 65 << 14 | 775: 550, + 97 << 14 | 775: 551, + 69 << 14 | 807: 552, + 101 << 14 | 807: 553, + 214 << 14 | 772: 554, + 246 << 14 | 772: 555, + 213 << 14 | 772: 556, + 245 << 14 | 772: 557, + 79 << 14 | 775: 558, + 111 << 14 | 775: 559, + 558 << 14 | 772: 560, + 559 << 14 | 772: 561, + 89 << 14 | 772: 562, + 121 << 14 | 772: 563, + 168 << 14 | 769: 901, + 913 << 14 | 769: 902, + 917 << 14 | 769: 904, + 919 << 14 | 769: 905, + 921 << 14 | 769: 906, + 927 << 14 | 769: 908, + 933 << 14 | 769: 910, + 937 << 14 | 769: 911, + 970 << 14 | 769: 912, + 921 << 14 | 776: 938, + 933 << 14 | 776: 939, + 945 << 14 | 769: 940, + 949 << 14 | 769: 941, + 951 << 14 | 769: 942, + 953 << 14 | 769: 943, + 971 << 14 | 769: 944, + 953 << 14 | 776: 970, + 965 << 14 | 776: 971, + 959 << 14 | 769: 972, + 965 << 14 | 769: 973, + 969 << 14 | 769: 974, + 978 << 14 | 769: 979, + 978 << 14 | 776: 980, + 1045 << 14 | 768: 1024, + 1045 << 14 | 776: 1025, + 1043 << 14 | 769: 1027, + 1030 << 14 | 776: 1031, + 1050 << 14 | 769: 1036, + 1048 << 14 | 768: 1037, + 1059 << 14 | 774: 1038, + 1048 << 14 | 774: 1049, + 1080 << 14 | 774: 1081, + 1077 << 14 | 768: 1104, + 1077 << 14 | 776: 1105, + 1075 << 14 | 769: 1107, + 1110 << 14 | 776: 1111, + 1082 << 14 | 769: 1116, + 1080 << 14 | 768: 1117, + 1091 << 14 | 774: 1118, + 1140 << 14 | 783: 1142, + 1141 << 14 | 783: 1143, + 1046 << 14 | 774: 1217, + 1078 << 14 | 774: 1218, + 1040 << 14 | 774: 1232, + 1072 << 14 | 774: 1233, + 1040 << 14 | 776: 1234, + 1072 << 14 | 776: 1235, + 1045 << 14 | 774: 1238, + 1077 << 14 | 774: 1239, + 1240 << 14 | 776: 1242, + 1241 << 14 | 776: 1243, + 1046 << 14 | 776: 1244, + 1078 << 14 | 776: 1245, + 1047 << 14 | 776: 1246, + 1079 << 14 | 776: 1247, + 1048 << 14 | 772: 1250, + 1080 << 14 | 772: 1251, + 1048 << 14 | 776: 1252, + 1080 << 14 | 776: 1253, + 1054 << 14 | 776: 1254, + 1086 << 14 | 776: 1255, + 1256 << 14 | 776: 1258, + 1257 << 14 | 776: 1259, + 1069 << 14 | 776: 1260, + 1101 << 14 | 776: 1261, + 1059 << 14 | 772: 1262, + 1091 << 14 | 772: 1263, + 1059 << 14 | 776: 1264, + 1091 << 14 | 776: 1265, + 1059 << 14 | 779: 1266, + 1091 << 14 | 779: 1267, + 1063 << 14 | 776: 1268, + 1095 << 14 | 776: 1269, + 1067 << 14 | 776: 1272, + 1099 << 14 | 776: 1273, + 1575 << 14 | 1619: 1570, + 1575 << 14 | 1620: 1571, + 1608 << 14 | 1620: 1572, + 1575 << 14 | 1621: 1573, + 1610 << 14 | 1620: 1574, + 1749 << 14 | 1620: 1728, + 1729 << 14 | 1620: 1730, + 1746 << 14 | 1620: 1747, + 2344 << 14 | 2364: 2345, + 2352 << 14 | 2364: 2353, + 2355 << 14 | 2364: 2356, + 2503 << 14 | 2494: 2507, + 2503 << 14 | 2519: 2508, + 2887 << 14 | 2902: 2888, + 2887 << 14 | 2878: 2891, + 2887 << 14 | 2903: 2892, + 2962 << 14 | 3031: 2964, + 3014 << 14 | 3006: 3018, + 3015 << 14 | 3006: 3019, + 3014 << 14 | 3031: 3020, + 3142 << 14 | 3158: 3144, + 3263 << 14 | 3285: 3264, + 3270 << 14 | 3285: 3271, + 3270 << 14 | 3286: 3272, + 3270 << 14 | 3266: 3274, + 3274 << 14 | 3285: 3275, + 3398 << 14 | 3390: 3402, + 3399 << 14 | 3390: 3403, + 3398 << 14 | 3415: 3404, + 3545 << 14 | 3530: 3546, + 3545 << 14 | 3535: 3548, + 3548 << 14 | 3530: 3549, + 3545 << 14 | 3551: 3550, + 4133 << 14 | 4142: 4134, + 65 << 14 | 805: 7680, + 97 << 14 | 805: 7681, + 66 << 14 | 775: 7682, + 98 << 14 | 775: 7683, + 66 << 14 | 803: 7684, + 98 << 14 | 803: 7685, + 66 << 14 | 817: 7686, + 98 << 14 | 817: 7687, + 199 << 14 | 769: 7688, + 231 << 14 | 769: 7689, + 68 << 14 | 775: 7690, + 100 << 14 | 775: 7691, + 68 << 14 | 803: 7692, + 100 << 14 | 803: 7693, + 68 << 14 | 817: 7694, + 100 << 14 | 817: 7695, + 68 << 14 | 807: 7696, + 100 << 14 | 807: 7697, + 68 << 14 | 813: 7698, + 100 << 14 | 813: 7699, + 274 << 14 | 768: 7700, + 275 << 14 | 768: 7701, + 274 << 14 | 769: 7702, + 275 << 14 | 769: 7703, + 69 << 14 | 813: 7704, + 101 << 14 | 813: 7705, + 69 << 14 | 816: 7706, + 101 << 14 | 816: 7707, + 552 << 14 | 774: 7708, + 553 << 14 | 774: 7709, + 70 << 14 | 775: 7710, + 102 << 14 | 775: 7711, + 71 << 14 | 772: 7712, + 103 << 14 | 772: 7713, + 72 << 14 | 775: 7714, + 104 << 14 | 775: 7715, + 72 << 14 | 803: 7716, + 104 << 14 | 803: 7717, + 72 << 14 | 776: 7718, + 104 << 14 | 776: 7719, + 72 << 14 | 807: 7720, + 104 << 14 | 807: 7721, + 72 << 14 | 814: 7722, + 104 << 14 | 814: 7723, + 73 << 14 | 816: 7724, + 105 << 14 | 816: 7725, + 207 << 14 | 769: 7726, + 239 << 14 | 769: 7727, + 75 << 14 | 769: 7728, + 107 << 14 | 769: 7729, + 75 << 14 | 803: 7730, + 107 << 14 | 803: 7731, + 75 << 14 | 817: 7732, + 107 << 14 | 817: 7733, + 76 << 14 | 803: 7734, + 108 << 14 | 803: 7735, + 7734 << 14 | 772: 7736, + 7735 << 14 | 772: 7737, + 76 << 14 | 817: 7738, + 108 << 14 | 817: 7739, + 76 << 14 | 813: 7740, + 108 << 14 | 813: 7741, + 77 << 14 | 769: 7742, + 109 << 14 | 769: 7743, + 77 << 14 | 775: 7744, + 109 << 14 | 775: 7745, + 77 << 14 | 803: 7746, + 109 << 14 | 803: 7747, + 78 << 14 | 775: 7748, + 110 << 14 | 775: 7749, + 78 << 14 | 803: 7750, + 110 << 14 | 803: 7751, + 78 << 14 | 817: 7752, + 110 << 14 | 817: 7753, + 78 << 14 | 813: 7754, + 110 << 14 | 813: 7755, + 213 << 14 | 769: 7756, + 245 << 14 | 769: 7757, + 213 << 14 | 776: 7758, + 245 << 14 | 776: 7759, + 332 << 14 | 768: 7760, + 333 << 14 | 768: 7761, + 332 << 14 | 769: 7762, + 333 << 14 | 769: 7763, + 80 << 14 | 769: 7764, + 112 << 14 | 769: 7765, + 80 << 14 | 775: 7766, + 112 << 14 | 775: 7767, + 82 << 14 | 775: 7768, + 114 << 14 | 775: 7769, + 82 << 14 | 803: 7770, + 114 << 14 | 803: 7771, + 7770 << 14 | 772: 7772, + 7771 << 14 | 772: 7773, + 82 << 14 | 817: 7774, + 114 << 14 | 817: 7775, + 83 << 14 | 775: 7776, + 115 << 14 | 775: 7777, + 83 << 14 | 803: 7778, + 115 << 14 | 803: 7779, + 346 << 14 | 775: 7780, + 347 << 14 | 775: 7781, + 352 << 14 | 775: 7782, + 353 << 14 | 775: 7783, + 7778 << 14 | 775: 7784, + 7779 << 14 | 775: 7785, + 84 << 14 | 775: 7786, + 116 << 14 | 775: 7787, + 84 << 14 | 803: 7788, + 116 << 14 | 803: 7789, + 84 << 14 | 817: 7790, + 116 << 14 | 817: 7791, + 84 << 14 | 813: 7792, + 116 << 14 | 813: 7793, + 85 << 14 | 804: 7794, + 117 << 14 | 804: 7795, + 85 << 14 | 816: 7796, + 117 << 14 | 816: 7797, + 85 << 14 | 813: 7798, + 117 << 14 | 813: 7799, + 360 << 14 | 769: 7800, + 361 << 14 | 769: 7801, + 362 << 14 | 776: 7802, + 363 << 14 | 776: 7803, + 86 << 14 | 771: 7804, + 118 << 14 | 771: 7805, + 86 << 14 | 803: 7806, + 118 << 14 | 803: 7807, + 87 << 14 | 768: 7808, + 119 << 14 | 768: 7809, + 87 << 14 | 769: 7810, + 119 << 14 | 769: 7811, + 87 << 14 | 776: 7812, + 119 << 14 | 776: 7813, + 87 << 14 | 775: 7814, + 119 << 14 | 775: 7815, + 87 << 14 | 803: 7816, + 119 << 14 | 803: 7817, + 88 << 14 | 775: 7818, + 120 << 14 | 775: 7819, + 88 << 14 | 776: 7820, + 120 << 14 | 776: 7821, + 89 << 14 | 775: 7822, + 121 << 14 | 775: 7823, + 90 << 14 | 770: 7824, + 122 << 14 | 770: 7825, + 90 << 14 | 803: 7826, + 122 << 14 | 803: 7827, + 90 << 14 | 817: 7828, + 122 << 14 | 817: 7829, + 104 << 14 | 817: 7830, + 116 << 14 | 776: 7831, + 119 << 14 | 778: 7832, + 121 << 14 | 778: 7833, + 383 << 14 | 775: 7835, + 65 << 14 | 803: 7840, + 97 << 14 | 803: 7841, + 65 << 14 | 777: 7842, + 97 << 14 | 777: 7843, + 194 << 14 | 769: 7844, + 226 << 14 | 769: 7845, + 194 << 14 | 768: 7846, + 226 << 14 | 768: 7847, + 194 << 14 | 777: 7848, + 226 << 14 | 777: 7849, + 194 << 14 | 771: 7850, + 226 << 14 | 771: 7851, + 7840 << 14 | 770: 7852, + 7841 << 14 | 770: 7853, + 258 << 14 | 769: 7854, + 259 << 14 | 769: 7855, + 258 << 14 | 768: 7856, + 259 << 14 | 768: 7857, + 258 << 14 | 777: 7858, + 259 << 14 | 777: 7859, + 258 << 14 | 771: 7860, + 259 << 14 | 771: 7861, + 7840 << 14 | 774: 7862, + 7841 << 14 | 774: 7863, + 69 << 14 | 803: 7864, + 101 << 14 | 803: 7865, + 69 << 14 | 777: 7866, + 101 << 14 | 777: 7867, + 69 << 14 | 771: 7868, + 101 << 14 | 771: 7869, + 202 << 14 | 769: 7870, + 234 << 14 | 769: 7871, + 202 << 14 | 768: 7872, + 234 << 14 | 768: 7873, + 202 << 14 | 777: 7874, + 234 << 14 | 777: 7875, + 202 << 14 | 771: 7876, + 234 << 14 | 771: 7877, + 7864 << 14 | 770: 7878, + 7865 << 14 | 770: 7879, + 73 << 14 | 777: 7880, + 105 << 14 | 777: 7881, + 73 << 14 | 803: 7882, + 105 << 14 | 803: 7883, + 79 << 14 | 803: 7884, + 111 << 14 | 803: 7885, + 79 << 14 | 777: 7886, + 111 << 14 | 777: 7887, + 212 << 14 | 769: 7888, + 244 << 14 | 769: 7889, + 212 << 14 | 768: 7890, + 244 << 14 | 768: 7891, + 212 << 14 | 777: 7892, + 244 << 14 | 777: 7893, + 212 << 14 | 771: 7894, + 244 << 14 | 771: 7895, + 7884 << 14 | 770: 7896, + 7885 << 14 | 770: 7897, + 416 << 14 | 769: 7898, + 417 << 14 | 769: 7899, + 416 << 14 | 768: 7900, + 417 << 14 | 768: 7901, + 416 << 14 | 777: 7902, + 417 << 14 | 777: 7903, + 416 << 14 | 771: 7904, + 417 << 14 | 771: 7905, + 416 << 14 | 803: 7906, + 417 << 14 | 803: 7907, + 85 << 14 | 803: 7908, + 117 << 14 | 803: 7909, + 85 << 14 | 777: 7910, + 117 << 14 | 777: 7911, + 431 << 14 | 769: 7912, + 432 << 14 | 769: 7913, + 431 << 14 | 768: 7914, + 432 << 14 | 768: 7915, + 431 << 14 | 777: 7916, + 432 << 14 | 777: 7917, + 431 << 14 | 771: 7918, + 432 << 14 | 771: 7919, + 431 << 14 | 803: 7920, + 432 << 14 | 803: 7921, + 89 << 14 | 768: 7922, + 121 << 14 | 768: 7923, + 89 << 14 | 803: 7924, + 121 << 14 | 803: 7925, + 89 << 14 | 777: 7926, + 121 << 14 | 777: 7927, + 89 << 14 | 771: 7928, + 121 << 14 | 771: 7929, + 945 << 14 | 787: 7936, + 945 << 14 | 788: 7937, + 7936 << 14 | 768: 7938, + 7937 << 14 | 768: 7939, + 7936 << 14 | 769: 7940, + 7937 << 14 | 769: 7941, + 7936 << 14 | 834: 7942, + 7937 << 14 | 834: 7943, + 913 << 14 | 787: 7944, + 913 << 14 | 788: 7945, + 7944 << 14 | 768: 7946, + 7945 << 14 | 768: 7947, + 7944 << 14 | 769: 7948, + 7945 << 14 | 769: 7949, + 7944 << 14 | 834: 7950, + 7945 << 14 | 834: 7951, + 949 << 14 | 787: 7952, + 949 << 14 | 788: 7953, + 7952 << 14 | 768: 7954, + 7953 << 14 | 768: 7955, + 7952 << 14 | 769: 7956, + 7953 << 14 | 769: 7957, + 917 << 14 | 787: 7960, + 917 << 14 | 788: 7961, + 7960 << 14 | 768: 7962, + 7961 << 14 | 768: 7963, + 7960 << 14 | 769: 7964, + 7961 << 14 | 769: 7965, + 951 << 14 | 787: 7968, + 951 << 14 | 788: 7969, + 7968 << 14 | 768: 7970, + 7969 << 14 | 768: 7971, + 7968 << 14 | 769: 7972, + 7969 << 14 | 769: 7973, + 7968 << 14 | 834: 7974, + 7969 << 14 | 834: 7975, + 919 << 14 | 787: 7976, + 919 << 14 | 788: 7977, + 7976 << 14 | 768: 7978, + 7977 << 14 | 768: 7979, + 7976 << 14 | 769: 7980, + 7977 << 14 | 769: 7981, + 7976 << 14 | 834: 7982, + 7977 << 14 | 834: 7983, + 953 << 14 | 787: 7984, + 953 << 14 | 788: 7985, + 7984 << 14 | 768: 7986, + 7985 << 14 | 768: 7987, + 7984 << 14 | 769: 7988, + 7985 << 14 | 769: 7989, + 7984 << 14 | 834: 7990, + 7985 << 14 | 834: 7991, + 921 << 14 | 787: 7992, + 921 << 14 | 788: 7993, + 7992 << 14 | 768: 7994, + 7993 << 14 | 768: 7995, + 7992 << 14 | 769: 7996, + 7993 << 14 | 769: 7997, + 7992 << 14 | 834: 7998, + 7993 << 14 | 834: 7999, + 959 << 14 | 787: 8000, + 959 << 14 | 788: 8001, + 8000 << 14 | 768: 8002, + 8001 << 14 | 768: 8003, + 8000 << 14 | 769: 8004, + 8001 << 14 | 769: 8005, + 927 << 14 | 787: 8008, + 927 << 14 | 788: 8009, + 8008 << 14 | 768: 8010, + 8009 << 14 | 768: 8011, + 8008 << 14 | 769: 8012, + 8009 << 14 | 769: 8013, + 965 << 14 | 787: 8016, + 965 << 14 | 788: 8017, + 8016 << 14 | 768: 8018, + 8017 << 14 | 768: 8019, + 8016 << 14 | 769: 8020, + 8017 << 14 | 769: 8021, + 8016 << 14 | 834: 8022, + 8017 << 14 | 834: 8023, + 933 << 14 | 788: 8025, + 8025 << 14 | 768: 8027, + 8025 << 14 | 769: 8029, + 8025 << 14 | 834: 8031, + 969 << 14 | 787: 8032, + 969 << 14 | 788: 8033, + 8032 << 14 | 768: 8034, + 8033 << 14 | 768: 8035, + 8032 << 14 | 769: 8036, + 8033 << 14 | 769: 8037, + 8032 << 14 | 834: 8038, + 8033 << 14 | 834: 8039, + 937 << 14 | 787: 8040, + 937 << 14 | 788: 8041, + 8040 << 14 | 768: 8042, + 8041 << 14 | 768: 8043, + 8040 << 14 | 769: 8044, + 8041 << 14 | 769: 8045, + 8040 << 14 | 834: 8046, + 8041 << 14 | 834: 8047, + 945 << 14 | 768: 8048, + 949 << 14 | 768: 8050, + 951 << 14 | 768: 8052, + 953 << 14 | 768: 8054, + 959 << 14 | 768: 8056, + 965 << 14 | 768: 8058, + 969 << 14 | 768: 8060, + 7936 << 14 | 837: 8064, + 7937 << 14 | 837: 8065, + 7938 << 14 | 837: 8066, + 7939 << 14 | 837: 8067, + 7940 << 14 | 837: 8068, + 7941 << 14 | 837: 8069, + 7942 << 14 | 837: 8070, + 7943 << 14 | 837: 8071, + 7944 << 14 | 837: 8072, + 7945 << 14 | 837: 8073, + 7946 << 14 | 837: 8074, + 7947 << 14 | 837: 8075, + 7948 << 14 | 837: 8076, + 7949 << 14 | 837: 8077, + 7950 << 14 | 837: 8078, + 7951 << 14 | 837: 8079, + 7968 << 14 | 837: 8080, + 7969 << 14 | 837: 8081, + 7970 << 14 | 837: 8082, + 7971 << 14 | 837: 8083, + 7972 << 14 | 837: 8084, + 7973 << 14 | 837: 8085, + 7974 << 14 | 837: 8086, + 7975 << 14 | 837: 8087, + 7976 << 14 | 837: 8088, + 7977 << 14 | 837: 8089, + 7978 << 14 | 837: 8090, + 7979 << 14 | 837: 8091, + 7980 << 14 | 837: 8092, + 7981 << 14 | 837: 8093, + 7982 << 14 | 837: 8094, + 7983 << 14 | 837: 8095, + 8032 << 14 | 837: 8096, + 8033 << 14 | 837: 8097, + 8034 << 14 | 837: 8098, + 8035 << 14 | 837: 8099, + 8036 << 14 | 837: 8100, + 8037 << 14 | 837: 8101, + 8038 << 14 | 837: 8102, + 8039 << 14 | 837: 8103, + 8040 << 14 | 837: 8104, + 8041 << 14 | 837: 8105, + 8042 << 14 | 837: 8106, + 8043 << 14 | 837: 8107, + 8044 << 14 | 837: 8108, + 8045 << 14 | 837: 8109, + 8046 << 14 | 837: 8110, + 8047 << 14 | 837: 8111, + 945 << 14 | 774: 8112, + 945 << 14 | 772: 8113, + 8048 << 14 | 837: 8114, + 945 << 14 | 837: 8115, + 940 << 14 | 837: 8116, + 945 << 14 | 834: 8118, + 8118 << 14 | 837: 8119, + 913 << 14 | 774: 8120, + 913 << 14 | 772: 8121, + 913 << 14 | 768: 8122, + 913 << 14 | 837: 8124, + 168 << 14 | 834: 8129, + 8052 << 14 | 837: 8130, + 951 << 14 | 837: 8131, + 942 << 14 | 837: 8132, + 951 << 14 | 834: 8134, + 8134 << 14 | 837: 8135, + 917 << 14 | 768: 8136, + 919 << 14 | 768: 8138, + 919 << 14 | 837: 8140, + 8127 << 14 | 768: 8141, + 8127 << 14 | 769: 8142, + 8127 << 14 | 834: 8143, + 953 << 14 | 774: 8144, + 953 << 14 | 772: 8145, + 970 << 14 | 768: 8146, + 953 << 14 | 834: 8150, + 970 << 14 | 834: 8151, + 921 << 14 | 774: 8152, + 921 << 14 | 772: 8153, + 921 << 14 | 768: 8154, + 8190 << 14 | 768: 8157, + 8190 << 14 | 769: 8158, + 8190 << 14 | 834: 8159, + 965 << 14 | 774: 8160, + 965 << 14 | 772: 8161, + 971 << 14 | 768: 8162, + 961 << 14 | 787: 8164, + 961 << 14 | 788: 8165, + 965 << 14 | 834: 8166, + 971 << 14 | 834: 8167, + 933 << 14 | 774: 8168, + 933 << 14 | 772: 8169, + 933 << 14 | 768: 8170, + 929 << 14 | 788: 8172, + 168 << 14 | 768: 8173, + 8060 << 14 | 837: 8178, + 969 << 14 | 837: 8179, + 974 << 14 | 837: 8180, + 969 << 14 | 834: 8182, + 8182 << 14 | 837: 8183, + 927 << 14 | 768: 8184, + 937 << 14 | 768: 8186, + 937 << 14 | 837: 8188, + 8592 << 14 | 824: 8602, + 8594 << 14 | 824: 8603, + 8596 << 14 | 824: 8622, + 8656 << 14 | 824: 8653, + 8660 << 14 | 824: 8654, + 8658 << 14 | 824: 8655, + 8707 << 14 | 824: 8708, + 8712 << 14 | 824: 8713, + 8715 << 14 | 824: 8716, + 8739 << 14 | 824: 8740, + 8741 << 14 | 824: 8742, + 8764 << 14 | 824: 8769, + 8771 << 14 | 824: 8772, + 8773 << 14 | 824: 8775, + 8776 << 14 | 824: 8777, + 61 << 14 | 824: 8800, + 8801 << 14 | 824: 8802, + 8781 << 14 | 824: 8813, + 60 << 14 | 824: 8814, + 62 << 14 | 824: 8815, + 8804 << 14 | 824: 8816, + 8805 << 14 | 824: 8817, + 8818 << 14 | 824: 8820, + 8819 << 14 | 824: 8821, + 8822 << 14 | 824: 8824, + 8823 << 14 | 824: 8825, + 8826 << 14 | 824: 8832, + 8827 << 14 | 824: 8833, + 8834 << 14 | 824: 8836, + 8835 << 14 | 824: 8837, + 8838 << 14 | 824: 8840, + 8839 << 14 | 824: 8841, + 8866 << 14 | 824: 8876, + 8872 << 14 | 824: 8877, + 8873 << 14 | 824: 8878, + 8875 << 14 | 824: 8879, + 8828 << 14 | 824: 8928, + 8829 << 14 | 824: 8929, + 8849 << 14 | 824: 8930, + 8850 << 14 | 824: 8931, + 8882 << 14 | 824: 8938, + 8883 << 14 | 824: 8939, + 8884 << 14 | 824: 8940, + 8885 << 14 | 824: 8941, +12363 << 14 | 12441: 12364, +12365 << 14 | 12441: 12366, +12367 << 14 | 12441: 12368, +12369 << 14 | 12441: 12370, +12371 << 14 | 12441: 12372, +12373 << 14 | 12441: 12374, +12375 << 14 | 12441: 12376, +12377 << 14 | 12441: 12378, +12379 << 14 | 12441: 12380, +12381 << 14 | 12441: 12382, +12383 << 14 | 12441: 12384, +12385 << 14 | 12441: 12386, +12388 << 14 | 12441: 12389, +12390 << 14 | 12441: 12391, +12392 << 14 | 12441: 12393, +12399 << 14 | 12441: 12400, +12399 << 14 | 12442: 12401, +12402 << 14 | 12441: 12403, +12402 << 14 | 12442: 12404, +12405 << 14 | 12441: 12406, +12405 << 14 | 12442: 12407, +12408 << 14 | 12441: 12409, +12408 << 14 | 12442: 12410, +12411 << 14 | 12441: 12412, +12411 << 14 | 12442: 12413, +12358 << 14 | 12441: 12436, +12445 << 14 | 12441: 12446, +12459 << 14 | 12441: 12460, +12461 << 14 | 12441: 12462, +12463 << 14 | 12441: 12464, +12465 << 14 | 12441: 12466, +12467 << 14 | 12441: 12468, +12469 << 14 | 12441: 12470, +12471 << 14 | 12441: 12472, +12473 << 14 | 12441: 12474, +12475 << 14 | 12441: 12476, +12477 << 14 | 12441: 12478, +12479 << 14 | 12441: 12480, +12481 << 14 | 12441: 12482, +12484 << 14 | 12441: 12485, +12486 << 14 | 12441: 12487, +12488 << 14 | 12441: 12489, +12495 << 14 | 12441: 12496, +12495 << 14 | 12442: 12497, +12498 << 14 | 12441: 12499, +12498 << 14 | 12442: 12500, +12501 << 14 | 12441: 12502, +12501 << 14 | 12442: 12503, +12504 << 14 | 12441: 12505, +12504 << 14 | 12442: 12506, +12507 << 14 | 12441: 12508, +12507 << 14 | 12442: 12509, +12454 << 14 | 12441: 12532, +12527 << 14 | 12441: 12535, +12528 << 14 | 12441: 12536, +12529 << 14 | 12441: 12537, +12530 << 14 | 12441: 12538, +12541 << 14 | 12441: 12542, } _canon_decomposition = { From tismer at codespeak.net Mon Jul 25 13:43:17 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 13:43:17 +0200 (CEST) Subject: [pypy-svn] r15011 - pypy/dist/pypy/module/unicodedata Message-ID: <20050725114317.5BF7327B51@code1.codespeak.net> Author: tismer Date: Mon Jul 25 13:43:16 2005 New Revision: 15011 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py Log: removed divmod 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 Mon Jul 25 13:43:16 2005 @@ -353,8 +353,12 @@ 0x20000 <= code <= 0x2A6D6): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: - vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) - l_code, v_code = divmod(vl_code, len(_hangul_V)) + # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) + vl_code = (code - 0xAC00) // len(_hangul_T) + t_code = (code - 0xAC00) % len(_hangul_T) + # l_code, v_code = divmod(vl_code, len(_hangul_V)) + l_code = vl_code // len(_hangul_V) + v_code = vl_code % len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) From arigo at codespeak.net Mon Jul 25 13:57:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 13:57:25 +0200 (CEST) Subject: [pypy-svn] r15013 - pypy/dist/pypy/translator Message-ID: <20050725115725.E1B5427B51@code1.codespeak.net> Author: arigo Date: Mon Jul 25 13:57:23 2005 New Revision: 15013 Modified: pypy/dist/pypy/translator/backendoptimization.py pypy/dist/pypy/translator/geninterplevel.py Log: Removed import dependencies (avoid having pypy.annotation imported when py.py starts). Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Mon Jul 25 13:57:23 2005 @@ -5,7 +5,6 @@ from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph from pypy.tool.unionfind import UnionFind from pypy.rpython.lltype import Void -from pypy.rpython.extfunctable import table as extfunctable def remove_same_as(graph): """Remove all 'same_as' operations. @@ -59,6 +58,7 @@ traverse(visit, graph) def rename_extfunc_calls(translator): + from pypy.rpython.extfunctable import table as extfunctable def visit(block): if isinstance(block, Block): for op in block.operations: Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Mon Jul 25 13:57:23 2005 @@ -52,7 +52,6 @@ from pypy.objspace.flow.model import last_exception from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS -from pypy.annotation import model as annmodel from types import FunctionType, CodeType, ModuleType from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments From tismer at codespeak.net Mon Jul 25 13:59:21 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 13:59:21 +0200 (CEST) Subject: [pypy-svn] r15014 - pypy/dist/pypy/module/unicodedata Message-ID: <20050725115921.C685D27B51@code1.codespeak.net> Author: tismer Date: Mon Jul 25 13:59:19 2005 New Revision: 15014 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: had to double "%" in code template. re-generated unicodedb.py 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 Mon Jul 25 13:59:19 2005 @@ -355,10 +355,10 @@ if 0xAC00 <= code <= 0xD7A3: # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) vl_code = (code - 0xAC00) // len(_hangul_T) - t_code = (code - 0xAC00) % len(_hangul_T) + t_code = (code - 0xAC00) %% len(_hangul_T) # l_code, v_code = divmod(vl_code, len(_hangul_V)) l_code = vl_code // len(_hangul_V) - v_code = vl_code % len(_hangul_V) + v_code = vl_code %% len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Mon Jul 25 13:59:19 2005 @@ -1,6 +1,6 @@ # UNICODE CHARACTER DATABASE # This file was generated with the command: -# ./generate_unicodedb.py -o unicodedb.py UnicodeData-3.2.0.txt CompositionExclusions-3.2.0.txt EastAsianWidth-3.2.0.txt +# 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 version = '3.2.0' @@ -13868,8 +13868,12 @@ 0x20000 <= code <= 0x2A6D6): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: - vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) - l_code, v_code = divmod(vl_code, len(_hangul_V)) + # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) + vl_code = (code - 0xAC00) // len(_hangul_T) + t_code = (code - 0xAC00) % len(_hangul_T) + # l_code, v_code = divmod(vl_code, len(_hangul_V)) + l_code = vl_code // len(_hangul_V) + v_code = vl_code % len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) From cfbolz at codespeak.net Mon Jul 25 14:05:11 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 14:05:11 +0200 (CEST) Subject: [pypy-svn] r15015 - in pypy/dist/pypy: rpython/module translator/c translator/c/src translator/c/test Message-ID: <20050725120511.F081A27B51@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 14:05:11 2005 New Revision: 15015 Modified: pypy/dist/pypy/rpython/module/ll_math.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/test/test_typed.py Log: (pedronis, cfbolz): added tests for frexp and modf plus their C implementation. Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Mon Jul 25 14:05:11 2005 @@ -55,4 +55,4 @@ def ll_math_modf(x): fracpart, intpart = math.modf(x) return ll_modf_result(fracpart, intpart) -ll_modf_result.suggested_primitive = True +ll_math_modf.suggested_primitive = True Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Mon Jul 25 14:05:11 2005 @@ -30,7 +30,8 @@ def predeclare_common_types(db, rtyper): # Common types yield ('RPyString', STR) - + yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT) + yield ('RPyMODF_RESULT', ll_math.MODF_RESULT) def predeclare_utility_functions(db, rtyper): # Common utility functions @@ -43,7 +44,14 @@ fptr = rtyper.annotate_helper(f, f.func_defaults) yield (fname, fptr) - +def predeclare_extfunc_helpers(db, rtyper): + def annotate(func, *argtypes): + fptr = rtyper.annotate_helper(func, argtypes) + return (func.__name__, fptr) + + yield annotate(ll_math.ll_frexp_result, lltype.Float, lltype.Signed) + yield annotate(ll_math.ll_modf_result, lltype.Float, lltype.Float) + def predeclare_extfuncs(db, rtyper): for func, funcobj in db.externalfuncs.items(): c_name = EXTERNALS[func] @@ -75,6 +83,7 @@ for fn in [predeclare_common_types, predeclare_utility_functions, predeclare_exception_data, + predeclare_extfunc_helpers, predeclare_extfuncs, ]: for t in fn(db, rtyper): Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Mon Jul 25 14:05:11 2005 @@ -17,7 +17,13 @@ double LL_math_ceil(double x) { return ceil(x); } -/* LL_math_frexp XXX strange stuff*/ + +struct RPyFREXP_RESULT* LL_math_frexp(double x) { + int expo; + double m = frexp(x, &expo); + return ll_frexp_result(m, expo); +} + double LL_math_atan2(double x, double y) { return atan2(x, y); } @@ -34,5 +40,9 @@ return ldexp(x, (int) y); } -/* LL_math_modf XXXX strange stuff*/ +struct RPyMODF_RESULT* LL_math_modf(double x) { + double intpart; + double fracpart = modf(x, &intpart); + return ll_modf_result(fracpart, intpart); +} 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 Jul 25 14:05:11 2005 @@ -282,6 +282,21 @@ f = self.getcompiled(fn) assert f(1.0) == exp(1.0) + def test_math_frexp(self): + from math import frexp + def fn(x=float): + return frexp(x) + f = self.getcompiled(fn) + assert f(10.123) == frexp(10.123) + + def test_math_modf(self): + from math import modf + def fn(x=float): + return modf(x) + f = self.getcompiled(fn) + assert f(10.123) == modf(10.123) + + def test_stringformatting(self): def fn(i=int): return "you said %d, you did"%i From hpk at codespeak.net Mon Jul 25 14:06:15 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 14:06:15 +0200 (CEST) Subject: [pypy-svn] r15016 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050725120615.241C927B51@code1.codespeak.net> Author: hpk Date: Mon Jul 25 14:06:14 2005 New Revision: 15016 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: (rxe,hpk) remove the implicit usage of file objects (through a call to the applevel "execfile") from the importing code. Instead we use os.* calls to get at the file content. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Mon Jul 25 14:06:14 2005 @@ -27,7 +27,7 @@ w_dict = space.getattr(w_mod, w('__dict__')) e = None try: - space.builtin.call('execfile', w(fn), w_dict, w_dict) + imp_execfile(space, fn, w_dict, w_dict) except OperationError, e: if e.match(space, space.w_SyntaxError): w_mods = space.sys.get('modules') @@ -198,3 +198,22 @@ w_failing = w_modulename w_exc = space.call_function(space.w_ImportError, w_failing) raise OperationError(space.w_ImportError, w_exc) + + +def imp_execfile(space, fn, w_globals, w_locals): + fd = os.open(fn, os.O_RDONLY) # XXX newlines? + try: + size = os.fstat(fd)[6] + source = os.read(fd, size) + finally: + os.close(fd) + w_source = space.wrap(source) + w_mode = space.wrap("exec") + w_fn = space.wrap(fn) + w_code = space.builtin.call('compile', w_source, w_fn, w_mode) + pycode = space.interpclass_w(w_code) + space.call_method(w_globals, 'setdefault', + space.wrap('__builtins__'), + space.wrap(space.builtin)) + pycode.exec_code(space, w_globals, w_locals) + From adim at codespeak.net Mon Jul 25 14:15:31 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 14:15:31 +0200 (CEST) Subject: [pypy-svn] r15017 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050725121531.7BB2A27B53@code1.codespeak.net> Author: adim Date: Mon Jul 25 14:15:29 2005 New Revision: 15017 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: - implemented listcomps (listmaker in general) - added a TempRuleObject class which represents a fake rule, built dynamically to keep track of how many elements the next reduce operation should pop Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 14:15:29 2005 @@ -77,7 +77,7 @@ """temporary implementation""" return eval(value) -def build_atom( builder, nb ): +def build_atom(builder, nb): L = get_atoms( builder, nb ) top = L[0] if isinstance(top, TokenObject): @@ -85,7 +85,15 @@ if top.name == tok.LPAR: builder.push( L[1] ) elif top.name == tok.LSQB: - builder.push( ast.List( L[1].nodes, top.line) ) + if len(L) == 2: + builder.push(ast.List([], top.line)) + else: + list_node = L[1] + # XXX lineno is not on *every* child class of ast.Node + # (will probably crash the annotator, but should be + # easily fixed) + list_node.lineno = top.line + builder.push(list_node) elif top.name == tok.LBRACE: builder.push( ast.Dict( L[1:-1], top.line) ) elif top.name == tok.NAME: @@ -321,7 +329,7 @@ else: # genfor assert False, "TODO" - builder.push( Tuple( items ) ) + builder.push(ast.Tuple(items)) return def build_varargslist(builder, nb): @@ -353,6 +361,58 @@ builder.push(ArglistObject('arglist', parse_argument(L), None)) +def build_list_for(builder, nb): + """ + list_iter: list_for | list_if + list_for: 'for' exprlist 'in' testlist_safe [list_iter] + list_if: 'if' test [list_iter] + /!\ list_for is (possibly) recursive + """ + L = get_atoms(builder, nb) + built_listfors = [] + ifs = [] + assign_token = L[1] + ass_node = to_lvalue(assign_token, consts.OP_ASSIGN) + end_index = len(L) - 1 + while isinstance(L[end_index], ast.ListCompFor): + # we need to insert in reverse order to build the AST + built_listfors.insert(0, L[end_index]) + end_index -= 1 + index = 4 + while index <= end_index: + ifs.append(L[index]) + index += 1 + builder.push(ast.ListCompFor(ass_node, L[3], ifs)) + for listfor in built_listfors: + builder.push(listfor) + builder.push(TempRuleObject(0, len(built_listfors) + 1, None)) + +def build_list_if(builder, nb): + """list_if: 'if' test [list_iter]""" + L = get_atoms(builder, nb) + builder.push(ast.ListCompIf(L[1])) + +def build_listmaker(builder, nb): + """listmaker: test ( list_for | (',' test)* [','] )""" + L = get_atoms(builder, nb) + if len(L) >= 2 and isinstance(L[1], ast.ListCompFor): + # list comp + index = 1 + listfors = [] + while index < len(L): + listfors.append(L[index]) + index += 1 + builder.push(ast.ListComp(L[0], listfors)) + else: + # regular list building (like in [1, 2, 3,]) + index = 0 + nodes = [] + while index < len(L): + nodes.append(L[index]) + index += 2 # skip comas + builder.push(ast.List(nodes)) + + def parse_argument(tokens): """parses function call arguments""" l = len(tokens) @@ -393,6 +453,7 @@ break return arguments, stararg_token, dstararg_token + def parse_arglist(tokens): """returns names, defaults, flags""" l = len(tokens) @@ -468,6 +529,9 @@ sym.varargslist : build_varargslist, sym.trailer : build_trailer, sym.arglist : build_arglist, + sym.list_for : build_list_for, + sym.list_if : build_list_if, + sym.listmaker : build_listmaker, } class RuleObject(ast.Node): @@ -484,6 +548,16 @@ def __repr__(self): return "" % (sym.sym_name[self.name], self.count) + +class TempRuleObject(RuleObject): + """used to keep track of how many items get_atom() should pop""" + def __str__(self): + return "" % (self.name, self.count) + + def __repr__(self): + return "" % (self.name, self.count) + + class TokenObject(ast.Node): """A simple object used to wrap a rule or token""" def __init__(self, name, value, src ): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 14:15:29 2005 @@ -30,9 +30,17 @@ "l = func(10, 12, a, b=c, **kwargs)", "l = func(10, 12, a, b=c, *args, **kwargs)", "l = func(10, 12, a, b=c)", - # "l = [i for i in range(10)]", - # "l = [i for i in range(10) if i%2 == 0]", - # "l = [1, 2, 3]", + "l = []", + "l = [1, 2, 3]", + "l = [i for i in range(10)]", + "l = [i for i in range(10) if i%2 == 0]", + "l = [i for i in range(10) if i%2 == 0 or i%2 == 1]", + "l = [i for i in range(10) if i%2 == 0 and i%2 == 1]", + "l = [i for j in range(10) for i in range(j)]", + "l = [i for j in range(10) for i in range(j) if j%2 == 0]", + "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 ==0]", + "l = [(a, b) for (a,b,c) in l2]", + # "l = [{a : b} for (a,b,c) in l2]", ] expression_tests = range(len(expressions)) # expression_tests = [-1] @@ -69,7 +77,7 @@ multiexpr = [ 'a = b; c = d;', 'a = b = c = d', - 'a = b\nc = d', + # 'a = b\nc = d', ] def ast_parse_expr(expr): @@ -84,8 +92,11 @@ def check_expression(expr): r1 = ast_parse_expr(expr) ast = tuple_parse_expr(expr) + print "-" * 30 print "ORIG :", ast + print print "BUILT:", r1.rule_stack[-1] + print "-" * 30 assert ast == r1.rule_stack[-1], 'failed on %r' % (expr) @@ -132,7 +143,7 @@ # 'snippet_whitespaces.py', ] -def test_snippets(): +def skippedtest_snippets(): py.test.skip('Not ready to test on real snippet files') for snippet_name in SNIPPETS: filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name) From adim at codespeak.net Mon Jul 25 14:38:22 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 14:38:22 +0200 (CEST) Subject: [pypy-svn] r15018 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050725123822.56DF127B53@code1.codespeak.net> Author: adim Date: Mon Jul 25 14:38:20 2005 New Revision: 15018 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: handle dict construction Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 14:38:20 2005 @@ -95,7 +95,12 @@ list_node.lineno = top.line builder.push(list_node) elif top.name == tok.LBRACE: - builder.push( ast.Dict( L[1:-1], top.line) ) + items = [] + for index in range(1, len(L)-1, 4): + # a : b , c : d + # ^ +1 +2 +3 +4 + items.append((L[index], L[index+2])) + builder.push(ast.Dict(items, top.line)) elif top.name == tok.NAME: builder.push( ast.Name(top.value) ) elif top.name == tok.NUMBER: Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 14:38:20 2005 @@ -24,12 +24,18 @@ "x = a * (1 + c)", "x, y, z = 1, 2, 3", "x = 'a' 'b' 'c'", +] + +funccalls = [ "l = func()", "l = func(10)", "l = func(10, 12, a, b=c, *args)", "l = func(10, 12, a, b=c, **kwargs)", "l = func(10, 12, a, b=c, *args, **kwargs)", "l = func(10, 12, a, b=c)", + ] + +listmakers = [ "l = []", "l = [1, 2, 3]", "l = [i for i in range(10)]", @@ -40,10 +46,13 @@ "l = [i for j in range(10) for i in range(j) if j%2 == 0]", "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 ==0]", "l = [(a, b) for (a,b,c) in l2]", - # "l = [{a : b} for (a,b,c) in l2]", -] -expression_tests = range(len(expressions)) -# expression_tests = [-1] + "l = [{a:b} for (a,b,c) in l2]", + ] + + +dictmakers = [ + "l = {a : b, 'c' : 0}", + ] backtrackings = [ "f = lambda x: x+1", @@ -56,7 +65,6 @@ "f = lambda *args: 1", "f = lambda **kwargs: 1", ] -backtracking_tests = range(len(backtrackings)) comparisons = [ "a < b", @@ -71,13 +79,20 @@ "(a < b) < (c < d)", "a < (b < c) < d", ] -comparison_tests = range(len(comparisons)) -# comparison_tests = [7] multiexpr = [ 'a = b; c = d;', 'a = b = c = d', - # 'a = b\nc = d', + ] + +TESTS = [ + expressions, + comparisons, + funccalls, + backtrackings, + listmakers, + dictmakers, + multiexpr, ] def ast_parse_expr(expr): @@ -100,22 +115,11 @@ assert ast == r1.rule_stack[-1], 'failed on %r' % (expr) -def test_multiexpr(): - for expr in multiexpr: - yield check_expression, expr - -def test_backtracking_expressions(): - """tests for expressions that need backtracking""" - for i in backtracking_tests: - yield check_expression, backtrackings[i] - -def test_expressions(): - for i in expression_tests: - yield check_expression, expressions[i] - -def test_comparisons(): - for i in comparison_tests: - yield check_expression, comparisons[i] +def test_basic_astgen(): + for family in TESTS: + for expr in family: + yield check_expression, expr + SNIPPETS = [ # 'snippet_1.py', From arigo at codespeak.net Mon Jul 25 15:11:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 15:11:24 +0200 (CEST) Subject: [pypy-svn] r15019 - pypy/branch/pypy-translation-snapshot/module/unicodedata Message-ID: <20050725131124.5D6EB27B53@code1.codespeak.net> Author: arigo Date: Mon Jul 25 15:11:22 2005 New Revision: 15019 Modified: pypy/branch/pypy-translation-snapshot/module/unicodedata/function.py pypy/branch/pypy-translation-snapshot/module/unicodedata/generate_unicodedb.py pypy/branch/pypy-translation-snapshot/module/unicodedata/unicodedb.py Log: Merging unicodedata revs 15007-15014 from trunk. Modified: pypy/branch/pypy-translation-snapshot/module/unicodedata/function.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/unicodedata/function.py (original) +++ pypy/branch/pypy-translation-snapshot/module/unicodedata/function.py Mon Jul 25 15:11:22 2005 @@ -209,11 +209,14 @@ # If LV, T -> LVT current = current + (next - TBase) continue - try: - current = unicodedb._composition[(current, next)] - continue - except KeyError: - pass + if (current <= unicodedb._composition_max and + next <= unicodedb._composition_max): + key = current << unicodedb._composition_shift | next + try: + current = unicodedb._composition[key] + continue + except KeyError: + pass if next_combining == 0: # New starter symbol Modified: pypy/branch/pypy-translation-snapshot/module/unicodedata/generate_unicodedb.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/unicodedata/generate_unicodedb.py (original) +++ pypy/branch/pypy-translation-snapshot/module/unicodedata/generate_unicodedb.py Mon Jul 25 15:11:22 2005 @@ -1,5 +1,6 @@ #!/usr/bin/env python -import sys + +MAXUNICODE = 0x10FFFF # the value of sys.maxunicode of wide Python builds class Unicodechar: def __init__(self, data): @@ -76,7 +77,7 @@ def read_unicodedata(unicodedata_file, exclusions_file, east_asian_width_file): rangeFirst = {} rangeLast = {} - table = [None] * (sys.maxunicode + 1) + table = [None] * (MAXUNICODE + 1) for line in unicodedata_file: line = line.split('#', 1)[0].strip() if not line: @@ -211,6 +212,7 @@ char.db_record = (char.category, char.bidirectional, char.east_asian_width, flags, char.combining) db_records[char.db_record] = 1 db_records = db_records.keys() + db_records.sort() print >> outfile, '_db_records = [' for record in db_records: print >> outfile, '%r,'%(record,) @@ -351,8 +353,12 @@ 0x20000 <= code <= 0x2A6D6): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: - vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) - l_code, v_code = divmod(vl_code, len(_hangul_V)) + # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) + vl_code = (code - 0xAC00) // len(_hangul_T) + t_code = (code - 0xAC00) %% len(_hangul_T) + # l_code, v_code = divmod(vl_code, len(_hangul_V)) + l_code = vl_code // len(_hangul_V) + v_code = vl_code %% len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) @@ -420,7 +426,8 @@ ''' # Collect the composition pairs. - compositions = {} + compositions = [] + composition_values = [] for code in range(len(table)): unichar = table[code] if (not unichar.decomposition or @@ -429,8 +436,22 @@ len(unichar.decomposition) != 2 or table[unichar.decomposition[0]].combining): continue - compositions[tuple(unichar.decomposition)] = code - writeDict(outfile, '_composition', compositions) + left, right = unichar.decomposition + compositions.append((left, right, code)) + composition_values.append(left) + composition_values.append(right) + composition_max = max(composition_values) + composition_shift = 1 + while (1 << composition_shift) <= composition_max: + composition_shift += 1 + print >> outfile, '_composition_max = %d' % composition_max + print >> outfile, '_composition_shift = %d' % composition_shift + print >> outfile, '_composition = {' + for left, right, code in compositions: + print >> outfile, '%5d << %d | %5d: %5d,' % ( + left, composition_shift, right, code) + print >> outfile, '}' + print >> outfile decomposition = {} for code in range(len(table)): @@ -446,7 +467,7 @@ if __name__ == '__main__': - import getopt, re + import getopt, re, sys infile = None outfile = sys.stdout unidata_version = None Modified: pypy/branch/pypy-translation-snapshot/module/unicodedata/unicodedb.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/unicodedata/unicodedb.py (original) +++ pypy/branch/pypy-translation-snapshot/module/unicodedata/unicodedb.py Mon Jul 25 15:11:22 2005 @@ -1,6 +1,6 @@ # UNICODE CHARACTER DATABASE # This file was generated with the command: -# ./generate_unicodedb.py -o unicodedb.py UnicodeData-3.2.0.txt CompositionExclusions-3.2.0.txt EastAsianWidth-3.2.0.txt +# 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 version = '3.2.0' @@ -13868,234 +13868,238 @@ 0x20000 <= code <= 0x2A6D6): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: - vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) - l_code, v_code = divmod(vl_code, len(_hangul_V)) + # vl_code, t_code = divmod(code - 0xAC00, len(_hangul_T)) + vl_code = (code - 0xAC00) // len(_hangul_T) + t_code = (code - 0xAC00) % len(_hangul_T) + # l_code, v_code = divmod(vl_code, len(_hangul_V)) + l_code = vl_code // len(_hangul_V) + v_code = vl_code % len(_hangul_V) return ("HANGUL SYLLABLE " + _hangul_L[l_code] + _hangul_V[v_code] + _hangul_T[t_code]) return _charnames[code] _db_records = [ -('Mn', 'NSM', 'N', 0, 222), +('Cc', 'B', 'N', 5, 0), +('Cc', 'BN', 'N', 0, 0), +('Cc', 'S', 'N', 1, 0), +('Cc', 'WS', 'N', 1, 0), +('Cf', 'AL', 'N', 0, 0), +('Cf', 'BN', 'N', 0, 0), +('Cf', 'L', 'N', 0, 0), +('Cf', 'LRE', 'N', 0, 0), +('Cf', 'LRO', 'N', 0, 0), +('Cf', 'PDF', 'N', 0, 0), ('Cf', 'R', 'N', 0, 0), -('Lu', 'L', 'N', 10, 0), +('Cf', 'RLE', 'N', 0, 0), +('Cf', 'RLO', 'N', 0, 0), +('Cn', '', 'N', 0, 0), +('Co', 'L', 'A', 0, 0), +('Cs', 'L', 'N', 0, 0), +('Ll', 'L', 'A', 34, 0), +('Ll', 'L', 'F', 34, 0), +('Ll', 'L', 'N', 34, 0), +('Ll', 'L', 'Na', 34, 0), +('Lm', 'AL', 'N', 2, 0), +('Lm', 'L', 'A', 2, 0), +('Lm', 'L', 'H', 2, 0), ('Lm', 'L', 'N', 2, 0), -('Ps', 'ON', 'Na', 512, 0), -('Cf', 'PDF', 'N', 0, 0), -('Mn', 'NSM', 'W', 0, 222), -('Cf', 'LRE', 'N', 0, 0), -('Pc', 'ON', 'F', 0, 0), -('Sm', 'ON', 'A', 0, 0), -('No', 'EN', 'A', 192, 0), -('Mn', 'NSM', 'N', 0, 36), -('Mn', 'NSM', 'N', 0, 15), -('So', 'ON', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 26), -('Mn', 'NSM', 'N', 0, 19), -('Pc', 'ON', 'H', 0, 0), -('Po', 'ET', 'F', 0, 0), -('Mn', 'NSM', 'N', 0, 103), -('Pd', 'ET', 'Na', 0, 0), -('Po', 'ON', 'F', 0, 0), -('Nd', 'L', 'N', 448, 0), +('Lm', 'L', 'W', 2, 0), ('Lo', 'AL', 'N', 2, 0), -('Sm', 'ON', 'Na', 0, 0), -('Pc', 'ON', 'N', 0, 0), -('Nd', 'EN', 'Na', 448, 0), -('Pe', 'ON', 'H', 512, 0), -('Cc', 'B', 'N', 5, 0), -('Sc', 'ET', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 216), -('Zs', 'CS', 'N', 1, 0), -('Po', 'ON', 'W', 0, 0), -('So', 'ON', 'F', 0, 0), -('So', 'L', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 107), -('Pc', 'ON', 'Na', 0, 0), -('Po', 'ET', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 118), -('Zs', 'WS', 'F', 1, 0), -('So', 'ON', 'H', 0, 0), -('Sm', 'ET', 'F', 0, 0), -('Pe', 'ON', 'N', 512, 0), -('Mc', 'L', 'N', 0, 226), -('Mn', 'NSM', 'N', 0, 9), -('Mn', 'NSM', 'N', 0, 27), -('Mn', 'NSM', 'N', 0, 20), -('Mn', 'NSM', 'A', 0, 230), -('Pe', 'ON', 'F', 512, 0), -('Pf', 'ON', 'A', 0, 0), -('No', 'EN', 'N', 448, 0), -('Ps', 'ON', 'W', 0, 0), -('Po', 'ET', 'W', 0, 0), -('So', 'ON', 'N', 0, 0), -('Pd', 'ON', 'N', 0, 0), -('Nd', 'EN', 'N', 448, 0), -('Sm', 'ON', 'A', 512, 0), -('Lm', 'AL', 'N', 2, 0), -('Lo', 'L', 'N', 2, 0), -('Nd', 'AN', 'N', 448, 0), -('Sk', 'ON', 'Na', 0, 0), -('Cs', 'L', 'N', 0, 0), -('Po', 'R', 'N', 0, 0), -('Mn', 'NSM', 'W', 0, 8), -('So', 'L', 'W', 0, 0), -('Mn', 'NSM', 'N', 0, 129), -('Sk', 'ON', 'F', 0, 0), -('So', 'ET', 'N', 0, 0), -('Co', 'L', 'A', 0, 0), ('Lo', 'L', 'H', 2, 0), -('Mn', 'NSM', 'N', 0, 91), -('So', 'ET', 'A', 0, 0), -('Po', 'ON', 'A', 0, 0), -('Mn', 'NSM', 'N', 0, 10), -('Mn', 'NSM', 'N', 0, 1), -('Mn', 'NSM', 'N', 0, 28), -('Mn', 'NSM', 'N', 0, 21), +('Lo', 'L', 'N', 2, 0), ('Lo', 'L', 'W', 2, 0), -('Pf', 'ON', 'N', 512, 0), -('Pi', 'ON', 'N', 0, 0), -('Lm', 'L', 'W', 2, 0), -('Pc', 'ON', 'W', 0, 0), -('Sk', 'ON', 'N', 0, 0), -('Pi', 'ON', 'N', 512, 0), -('Mc', 'L', 'N', 0, 0), -('Po', 'ET', 'A', 0, 0), -('Cc', 'BN', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 228), -('No', 'EN', 'A', 64, 0), -('Zl', 'WS', 'N', 5, 0), -('No', 'L', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 130), -('Nl', 'L', 'N', 0, 0), -('Pd', 'ON', 'W', 0, 0), -('Cn', '', 'N', 0, 0), -('Sm', 'ON', 'N', 512, 0), -('Pd', 'ET', 'W', 0, 0), -('Mn', 'NSM', 'W', 0, 224), -('Mn', 'NSM', 'N', 0, 32), -('Mn', 'NSM', 'N', 0, 122), -('Mn', 'NSM', 'N', 0, 11), -('Lu', 'L', 'Na', 10, 0), -('Mn', 'NSM', 'N', 0, 29), -('Mn', 'NSM', 'N', 0, 22), -('Mn', 'NSM', 'A', 0, 234), -('Cf', 'AL', 'N', 0, 0), -('Sm', 'ON', 'N', 0, 0), -('Mn', 'NSM', 'A', 0, 220), +('Lo', 'R', 'N', 2, 0), ('Lt', 'L', 'N', 18, 0), -('Po', 'CS', 'N', 0, 0), -('Cf', 'BN', 'N', 0, 0), -('Pe', 'ON', 'W', 0, 0), -('Zp', 'B', 'N', 5, 0), -('Ps', 'ON', 'W', 512, 0), ('Lu', 'L', 'A', 10, 0), -('No', 'ON', 'A', 192, 0), -('No', 'L', 'W', 64, 0), -('Pe', 'ON', 'W', 512, 0), -('Cf', 'L', 'N', 0, 0), -('Po', 'CS', 'F', 0, 0), -('Nl', 'L', 'W', 64, 0), -('Sm', 'L', 'N', 0, 0), ('Lu', 'L', 'F', 10, 0), -('Ll', 'L', 'N', 34, 0), -('So', 'ON', 'A', 0, 0), -('Sc', 'ET', 'Na', 0, 0), -('Sm', 'ON', 'Na', 512, 0), +('Lu', 'L', 'N', 10, 0), +('Lu', 'L', 'Na', 10, 0), +('Mc', 'L', 'N', 0, 0), ('Mc', 'L', 'N', 0, 216), -('Mn', 'NSM', 'W', 0, 232), -('Mn', 'NSM', 'N', 0, 33), -('Po', 'CS', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 12), -('Mn', 'NSM', 'N', 0, 30), -('Mn', 'NSM', 'N', 0, 23), -('Mn', 'NSM', 'N', 0, 16), +('Mc', 'L', 'N', 0, 226), +('Me', 'NSM', 'N', 0, 0), +('Mn', 'NSM', 'A', 0, 0), +('Mn', 'NSM', 'A', 0, 1), +('Mn', 'NSM', 'A', 0, 202), +('Mn', 'NSM', 'A', 0, 216), +('Mn', 'NSM', 'A', 0, 220), +('Mn', 'NSM', 'A', 0, 230), +('Mn', 'NSM', 'A', 0, 232), ('Mn', 'NSM', 'A', 0, 233), +('Mn', 'NSM', 'A', 0, 234), ('Mn', 'NSM', 'A', 0, 240), +('Mn', 'NSM', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 1), +('Mn', 'NSM', 'N', 0, 7), +('Mn', 'NSM', 'N', 0, 9), +('Mn', 'NSM', 'N', 0, 10), +('Mn', 'NSM', 'N', 0, 11), +('Mn', 'NSM', 'N', 0, 12), +('Mn', 'NSM', 'N', 0, 13), +('Mn', 'NSM', 'N', 0, 14), +('Mn', 'NSM', 'N', 0, 15), +('Mn', 'NSM', 'N', 0, 16), +('Mn', 'NSM', 'N', 0, 17), +('Mn', 'NSM', 'N', 0, 18), +('Mn', 'NSM', 'N', 0, 19), +('Mn', 'NSM', 'N', 0, 20), +('Mn', 'NSM', 'N', 0, 21), +('Mn', 'NSM', 'N', 0, 22), +('Mn', 'NSM', 'N', 0, 23), ('Mn', 'NSM', 'N', 0, 24), -('Sk', 'ON', 'W', 0, 0), -('Sm', 'ET', 'N', 0, 0), -('Me', 'NSM', 'N', 0, 0), -('Pd', 'ON', 'A', 0, 0), -('Ll', 'L', 'F', 34, 0), -('No', 'EN', 'A', 448, 0), -('Ll', 'L', 'A', 34, 0), -('Zs', 'WS', 'Na', 1, 0), -('Ps', 'ON', 'N', 512, 0), -('Nd', 'EN', 'F', 448, 0), -('Sc', 'ET', 'N', 0, 0), -('Cf', 'RLE', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 230), -('Sm', 'ET', 'Na', 0, 0), -('Po', 'L', 'N', 0, 0), -('Cf', 'LRO', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 220), -('Sc', 'ET', 'H', 0, 0), -('No', 'EN', 'N', 192, 0), -('No', 'ON', 'N', 64, 0), -('So', 'L', 'N', 0, 0), +('Mn', 'NSM', 'N', 0, 25), +('Mn', 'NSM', 'N', 0, 26), +('Mn', 'NSM', 'N', 0, 27), +('Mn', 'NSM', 'N', 0, 28), +('Mn', 'NSM', 'N', 0, 29), +('Mn', 'NSM', 'N', 0, 30), +('Mn', 'NSM', 'N', 0, 31), +('Mn', 'NSM', 'N', 0, 32), +('Mn', 'NSM', 'N', 0, 33), +('Mn', 'NSM', 'N', 0, 34), +('Mn', 'NSM', 'N', 0, 35), +('Mn', 'NSM', 'N', 0, 36), +('Mn', 'NSM', 'N', 0, 84), +('Mn', 'NSM', 'N', 0, 91), +('Mn', 'NSM', 'N', 0, 103), +('Mn', 'NSM', 'N', 0, 107), +('Mn', 'NSM', 'N', 0, 118), +('Mn', 'NSM', 'N', 0, 122), +('Mn', 'NSM', 'N', 0, 129), +('Mn', 'NSM', 'N', 0, 130), ('Mn', 'NSM', 'N', 0, 132), -('Ll', 'L', 'Na', 34, 0), +('Mn', 'NSM', 'N', 0, 216), +('Mn', 'NSM', 'N', 0, 220), +('Mn', 'NSM', 'N', 0, 222), +('Mn', 'NSM', 'N', 0, 228), +('Mn', 'NSM', 'N', 0, 230), +('Mn', 'NSM', 'W', 0, 8), ('Mn', 'NSM', 'W', 0, 218), -('Zs', 'BN', 'N', 1, 0), -('Sm', 'ET', 'A', 0, 0), +('Mn', 'NSM', 'W', 0, 222), +('Mn', 'NSM', 'W', 0, 224), +('Mn', 'NSM', 'W', 0, 228), +('Mn', 'NSM', 'W', 0, 232), +('Nd', 'AN', 'N', 448, 0), +('Nd', 'EN', 'F', 448, 0), +('Nd', 'EN', 'N', 448, 0), +('Nd', 'EN', 'Na', 448, 0), +('Nd', 'L', 'N', 448, 0), ('Nl', 'L', 'A', 64, 0), -('Mn', 'NSM', 'N', 0, 34), -('Mn', 'NSM', 'N', 0, 13), -('Mn', 'NSM', 'N', 0, 31), -('Po', 'ON', 'Na', 0, 0), -('Mn', 'NSM', 'N', 0, 17), -('Mn', 'NSM', 'A', 0, 232), -('Po', 'AN', 'N', 0, 0), -('Sc', 'ET', 'F', 0, 0), -('No', 'ON', 'A', 64, 0), -('Pe', 'ON', 'N', 0, 0), -('Po', 'ET', 'N', 0, 0), -('Zs', 'WS', 'N', 1, 0), +('Nl', 'L', 'N', 0, 0), +('Nl', 'L', 'N', 64, 0), +('Nl', 'L', 'W', 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', '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), -('Sk', 'ON', 'A', 0, 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), -('Nl', 'L', 'N', 64, 0), -('Sm', 'ON', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 1), -('Sm', 'ON', 'H', 0, 0), -('Sm', 'ET', 'W', 0, 0), -('Cc', 'S', 'N', 1, 0), +('Pd', 'ET', 'Na', 0, 0), +('Pd', 'ET', 'W', 0, 0), +('Pd', 'ON', 'A', 0, 0), +('Pd', 'ON', 'N', 0, 0), +('Pd', 'ON', 'W', 0, 0), +('Pe', 'ON', 'F', 512, 0), +('Pe', 'ON', 'H', 512, 0), +('Pe', 'ON', 'N', 0, 0), +('Pe', 'ON', 'N', 512, 0), +('Pe', 'ON', 'Na', 512, 0), +('Pe', 'ON', 'W', 0, 0), +('Pe', 'ON', 'W', 512, 0), +('Pf', 'ON', 'A', 0, 0), +('Pf', 'ON', 'N', 512, 0), +('Pi', 'ON', 'A', 0, 0), +('Pi', 'ON', 'N', 0, 0), +('Pi', 'ON', 'N', 512, 0), +('Po', 'AL', 'N', 0, 0), +('Po', 'AN', 'N', 0, 0), +('Po', 'CS', 'F', 0, 0), +('Po', 'CS', 'N', 0, 0), +('Po', 'CS', 'Na', 0, 0), +('Po', 'CS', 'W', 0, 0), ('Po', 'ES', 'F', 0, 0), -('Lo', 'R', 'N', 2, 0), -('Ps', 'ON', 'F', 512, 0), +('Po', 'ES', 'Na', 0, 0), +('Po', 'ET', 'A', 0, 0), +('Po', 'ET', 'F', 0, 0), +('Po', 'ET', 'N', 0, 0), +('Po', 'ET', 'Na', 0, 0), +('Po', 'ET', 'W', 0, 0), +('Po', 'L', 'N', 0, 0), +('Po', 'ON', 'A', 0, 0), +('Po', 'ON', 'F', 0, 0), +('Po', 'ON', 'H', 0, 0), ('Po', 'ON', 'N', 0, 0), -('Pi', 'ON', 'A', 0, 0), -('Lm', 'L', 'A', 2, 0), +('Po', 'ON', 'Na', 0, 0), +('Po', 'ON', 'W', 0, 0), +('Po', 'R', 'N', 0, 0), +('Ps', 'ON', 'F', 512, 0), ('Ps', 'ON', 'H', 512, 0), -('So', 'AL', 'N', 0, 0), -('Po', 'ON', 'H', 0, 0), -('Mn', 'NSM', 'W', 0, 228), -('Mn', 'NSM', 'N', 0, 35), -('Cc', 'WS', 'N', 1, 0), -('Mn', 'NSM', 'N', 0, 14), -('Mn', 'NSM', 'N', 0, 7), -('Mn', 'NSM', 'N', 0, 0), -('Mn', 'NSM', 'N', 0, 25), -('Mn', 'NSM', 'N', 0, 18), -('Po', 'ES', 'Na', 0, 0), -('Po', 'CS', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 202), -('Mn', 'NSM', 'A', 0, 216), -('Cf', 'RLO', 'N', 0, 0), ('Ps', 'ON', 'N', 0, 0), -('Lm', 'L', 'H', 2, 0), +('Ps', 'ON', 'N', 512, 0), +('Ps', 'ON', 'Na', 512, 0), +('Ps', 'ON', 'W', 0, 0), +('Ps', 'ON', 'W', 512, 0), +('Sc', 'AL', 'N', 0, 0), +('Sc', 'ET', 'A', 0, 0), +('Sc', 'ET', 'F', 0, 0), +('Sc', 'ET', 'H', 0, 0), +('Sc', 'ET', 'N', 0, 0), +('Sc', 'ET', 'Na', 0, 0), ('Sc', 'ET', 'W', 0, 0), -('Po', 'AL', 'N', 0, 0), +('Sk', 'ON', 'A', 0, 0), +('Sk', 'ON', 'F', 0, 0), +('Sk', 'ON', 'N', 0, 0), +('Sk', 'ON', 'Na', 0, 0), +('Sk', 'ON', '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), ('Sm', 'ON', 'F', 0, 0), -('Mn', 'NSM', 'N', 0, 84), -('Sc', 'AL', 'N', 0, 0), -('No', 'ON', 'N', 192, 0), -('So', 'ON', 'W', 0, 0), -('Mn', 'NSM', 'A', 0, 0), -('Pe', 'ON', 'Na', 512, 0), ('Sm', 'ON', 'F', 512, 0), +('Sm', 'ON', 'H', 0, 0), +('Sm', 'ON', 'N', 0, 0), +('Sm', 'ON', 'N', 512, 0), +('Sm', 'ON', 'Na', 0, 0), +('Sm', 'ON', 'Na', 512, 0), +('Sm', 'ON', 'W', 0, 0), +('So', 'AL', 'N', 0, 0), +('So', 'ET', 'A', 0, 0), +('So', 'ET', 'N', 0, 0), +('So', 'L', 'A', 0, 0), +('So', 'L', 'N', 0, 0), +('So', 'L', 'W', 0, 0), +('So', 'ON', 'A', 0, 0), +('So', 'ON', 'F', 0, 0), +('So', 'ON', 'H', 0, 0), +('So', 'ON', 'N', 0, 0), +('So', 'ON', 'Na', 0, 0), +('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&\'()*+,,,,,,,,,,,,' @@ -14168,282 +14172,282 @@ '222222222222222222222222222222222222222222222222222222222222222D' ) _db_pages = ( -'UUUUUUUUU\xb9\x1b\xb9\xc5\x1bUUUUUUUUUUUUUU\x1b\x1b\x1b\xb9\x90\xa7\xa7$|$\xa7\xa7\x04\xda\xa7\x96\x81\x13\x81\xcb\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x81\xa7}\x17}\xa7' -'\xa7dddddddddddddddddddddddddd\x04\xa7\xda;#;\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x04\x17\xda\x17U' -'UUUUU\x1bUUUUUUUUUUUUUUUUUUUUUUUUUU\x1eG||\x1c|\r{\xb24\x8fR\x17\x8c{;F\xa2\x8e\x8e\xb2z{G\xb2\x8e\x8fM\xac\xac\xacG' -'\x02\x02\x02\x02\x02\x02q\x02\x02\x02\x02\x02\x02\x02\x02\x02q\x02\x02\x02\x02\x02\x02\tq\x02\x02\x02\x02\x02q\x8f\x8f\x8fzzzz\x8fz\x8f\x8f\x8fz\x8f\x8fzz\x8fz\x8f\x8fzzz\t\x8f\x8f\x8fz\x8fz\x8fz' -'\x02\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02\x8f\x02\x8f\x02z\x02z\x02z\x02\x8f\x02z\x02z\x02z\x02z\x02zq\x8f\x02z\x02\x8f\x02z\x02z\x02\x8fq\x8f\x02z\x02z\x8f\x02z\x02z\x02zq' -'\x8fq\x8f\x02\x8f\x02z\x02\x8f\x8fq\x8f\x02\x8f\x02z\x02zq\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zq\x8f\x02z\x02\x8f\x02z\x02z\x02z\x02z\x02z\x02z\x02\x02z\x02z\x02zz' -'z\x02\x02z\x02z\x02\x02z\x02\x02\x02zz\x02\x02\x02\x02z\x02\x02z\x02\x02\x02zzz\x02\x02z\x02\x02z\x02z\x02z\x02\x02z\x02zz\x02z\x02\x02z\x02\x02\x02z\x02z\x02\x02zz9\x02zzz' -'9999\x02kz\x02kz\x02kz\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8f\x02\x8fz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zz\x02kz\x02z\x02\x02\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]z\x8fzzzzzzzzzzzzzzz\x8fzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz]]\x03\x03\x03\x03\x03\x03\x03\x03\x03QQ\x03\x03\x03\x03\x03' -'\x03\x03QQ\xb2QQ\xb2Q\xb2\xb2\xb2Q\xb2QQ\xbf\x03QQQQQQ\xb2\xb2\xb2\xb2Q\xb2Q\xb2\x03\x03\x03\x03\x03QQQQQQQQQ\x03]]]]]]]]]]]]]]]]]' -'.....................\xa9jjjj\xa9\xcejjjjj\xcd\xcdjjjj\xcd\xcdjjjjjjjjjjj\xb6\xb6\xb6\xb6\xb6jjjj...' -'.....\x87.jjj...jj\xd9]]]]]]]]]]]]]]]]gg\x86.............]]]]QQ]]]]\x03]]]\xbd]' -']]]]QQ\x02\xbd\x02\x02\x02]\x02]\x02\x02zqqqqqqqqqqqqqqqqq]qqqqqqq\x02\x02zzzzz\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f' -'\x8f\x8fz\x8f\x8f\x8f\x8f\x8f\x8f\x8fzzzzz]zz\x02\x02\x02zzz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zzzzz\x02zi]]]]]]]]]' -'\x02q\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f' -'\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8fz\x8fzzzzzzzzzzzzzz\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x9d\x95\x95\x95\x95]\x8b\x8b\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02\x02z\x02z\x02z\x02z\x02z\x02z\x02z]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]\x02z]]]]]]' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02]]\x03\x97\x97\x97\x97\x97\x97]zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzz]\x975]]]]]]\x99\x95\x95\x95\x95\x99\x95\x95\x95\x00\x99\x95\x95\x95\x95\x95\x95]\x99\x99\x99\x99\x99\x95\x95\x99\x95\x95\x00V\x95Hc\x82\xa5\xc6\x0c\x85\xa8\xca\x0f]-Kf=\x84' -'=\x88\xc9=\x95]]]]]]]]]]]\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb]]]]]\xbb\xbb\xbb==]]]]]]]]]]]' -']]]]]]]]]]]]l]]]]]]]]]]]]]]\xd3]]]\xd3]\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]]]]]' -'8\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16,Je\x83\xa6a\x80\xa4\x95\x95\x99]]]]]]]]]]::::::::::\xae\xaa\xaa\xd3\x16\x16\xc4\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\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\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\x16' -'\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xd3\x16\x95\x95\x95\x95\x95\x95\x95h\x8b\x95\x95\x95\x95\x99\x9588\x95\x954\x99\x95\x95\x99]]6666666666\x16\x16\x16\xc1\xc1]' -'\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3]m\x16\x0b\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\x16]]]\x95\x99\x95\x95\x99\x95\x95\x99\x99\x99\x95\x99\x99\x95\x99\x95' -'\x95\x95\x99\x95\x99\x95\x99\x95\x99\x95\x95]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\x16]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']\xc8\xc8S]99999999999999999999999999999999999999999999999999999]]\xc79SS' -'S\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8SSSS+]]9\x95\x99\x95\x95]]]9999999999\xc8\xc8\x97\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97]]]]]]]]]]]]]]]' -']\xc8SS]99999999]]99]]9999999999999999999999]9999999]9]]]9999]]\xc7]SS' -'S\xc8\xc8\xc8\xc8]]SS]]SS+]]]]]]]]]S]]]]99]999\xc8\xc8]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1599\x93\x93\xb0\xb0\xb0\xb0Y\xb0\x9d]]]]]' -']]\xc8]]999999]]]]99]]9999999999999999999999]9999999]99]99]99]]\xc7]SS' -'S\xc8\xc8]]]]\xc8\xc8]]\xc8\xc8+]]]]]]]]]]]9999]9]]]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc8\xc8999]]]]]]]]]]]' -']\xc8\xc8S]9999999]9]999]9999999999999999999999]9999999]99]99999]]\xc79SS' -'S\xc8\xc8\xc8\xc8\xc8]\xc8\xc8S]SS+]]9]]]]]]]]]]]]]]]9]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']\xc8SS]99999999]]99]]9999999999999999999999]9999999]99]]9999]]\xc79S\xc8' -'S\xc8\xc8\xc8]]]SS]]SS+]]]]]]]]\xc8S]]]]99]999]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x9d]]]]]]]]]]]]]]]' -']]\xc89]999999]]]999]9999]]]99]9]99]]]99]]]999]]]99999999]999]]]]SS' -'\xc8SS]]]SSS]SSS+]]]]]]]]]S]]]]]]]]]]]]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0]]]]]]]]]]]]]' -']SSS]99999999]999]99999999999999999999999]9999999999]99999]]]]\xc8\xc8' -'\xc8SSSS]\xc8\xc8\xc8]\xc8\xc8\xc8+]]]]]]]\xd5E]]]]]]]]]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]99999999]999]99999999999999999999999]9999999999]99999]]]]S\xc8' -'SSSSS]\xc8SS]SS\xc8+]]]]]]]SS]]]]]]]9]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]99999999]999]99999999999999999999999]9999999999999999]]]]SS' -'S\xc8\xc8\xc8]]SSS]SSS+]]]]]]]]]S]]]]]]]]99]]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]' -']]SS]999999999999999999]]]999999999999999999999999]999999999]9]]' -'9999999]]]+]]]]SSS\xc8\xc8\xc8]\xc8]SSSSSSSS]]]]]]]]]]]]]]]]]]SS\x97]]]]]]]]]]]' -']999999999999999999999999999999999999999999999999\xc899\xc8\xc8\xc8\xc8\x12\x12+]]]]\x93' -'999999\x03\xc8""""\xc8\xc8\xc8\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97\x97]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']99]9]]99]9]]9]]]]]]9999]9999999]999]9]9]]99]9999\xc899\xc8\xc8\xc8\xc8%%]\xc8\xc89]]' -'99999]\x03]bbbb\xc8\xc8]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]99]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'9\x9d\x9d\x9d\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x9d\x9d\x9d\x9d\x9d\x99\x99\x9d\x9d\x9d\x9d\x9d\x9d\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\x9d\x99\x9d\x99\x9d\x1d\xd0\xad\xd0\xadSS' -'99999999]9999999999999999999999999999999999]]]]]]@Z\xc8\x9e\xc8\xc8\xc8\xc8\xc8ZZZZ\xc8S' -'Z\xc8\x95\x95+\x97\x95\x959999]]]]\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8]\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8]\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x99\x9d\x9d\x9d\x9d\x9d\x9d]]\x9d]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'9999999999999999999999999999999999]99999]99]S\xc8\xc8\xc8\xc8S\xc8]]]\xc8\xc7S+]]]]]]' -'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x97\x97\x97\x97\x97\x97999999SS\xc8\xc8]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02]]]]]]]]]]99999999999999999999999999999999999999999]]\x97]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]L99999999999999999999999999999999' -'99999999999999999999999999999999999]]]]]999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999]]]]]]' -'9999999]99999999999999999999999999999999999999999999999999999999' -'9999999]9]9999]]9999999]9]9999]]99999999999999999999999999999999' -'9999999]9]9999]]9999999999999999999999999999999]9]9999]]9999999]' -'9]9999]]9999999]9999999]99999999999999999999999]9999999999999999' -'999999999999999]9]9999]]9999999]99999999999999999999999999999999' -'9999999]9999999999999999999]]]]]]\x97\x97\x97\x97\x97\x97\x97\x97\x15\x15\x15\x15\x15\x15\x15\x15\x15\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]99999999999999999999999999999999' -'99999999999999999999999999999999999999999999999999999]]]]]]]]]]]' -']999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'9999999999999999999999999999999999999999999999999999999999999999' -'999999999999999999999999999999999999999999999\x97\x9799999999]]]]]]]]]' -'\xaf99999999999999999999999999\xd0\xad]]]99999999999999999999999999999999' -'9999999999999999999999999999999999999999999\x97\x97\x97\xb4\xb4\xb4]]]]]]]]]]]]]]]' -'9999999999999]9999\xc8\xc8+]]]]]]]]]]]999999999999999999\xc8\xc8+\x97\x97]]]]]]]]]' -'999999999999999999\xc8\xc8]]]]]]]]]]]]9999999999999]999]\xc8\xc8]]]]]]]]]]]]' -'9999999999999999999999999999999999999999999999999999SSS\xc8\xc8\xc8\xc8\xc8\xc8\xc8SS' -'SSSSSS\xc8SS\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8+\xc8\x97\x97\x97\x03\x97\x97\x97\x939]]]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]]]]]]]]]]]]]]]]]' -'\xbd\xbd\xbd\xbd\xbd\xbd5\xbd\xbd\xbd\xbd\xc8\xc8\xc8m]\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15]]]]]]99999999999999999999999999999999' -'999\x039999999999999999999999999999999999999999999999999999]]]]]]]]' -'99999999999999999999999999999999999999999V]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02zzzzzzz]]]]\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z' -'\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z\x02z]]]]]]' -'zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzz]]\x02\x02\x02\x02\x02\x02]]zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02' -'zzzzzz]]\x02\x02\x02\x02\x02\x02]]zzzzzzzz]\x02]\x02]\x02]\x02zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzz]]' -'zzzzzzzzkkkkkkkkzzzzzzzzkkkkkkkkzzzzzzzzkkkkkkkkzzzzz]zz\x02\x02\x02\x02kQzQ' -'QQzzz]zz\x02\x02\x02\x02kQQQzzzz]]zz\x02\x02\x02\x02]QQQzzzzzzzz\x02\x02\x02\x02\x02QQQ]]zzz]zz\x02\x02\x02\x02kQQ]' -'\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xa1mmu\x01\x8c55\x8c\x8c\x8cG\xbd\xbe0\xd0N\xbe0\xd0NGGG\xbdGGGGXo\x07\x94\x05\x98\xcf\xafT\xaeTT\xaeG\xbd\xbd\xbdRMG\xbd\xbdG\x18' -'\x18\xbd\xbd\xbdi\x91)\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbdi]]]]\xbd]]]]]]]\xafmmmm]]]]]]mmmmmm1z]]\x8e11111\x8a\x8ai\x91)\x8f' -'1\x8e\x8e\x8e\x8e11111\x8a\x8ai\x91)]]]]]]]]]]]]]]]]]\x93\x93\x93\x93\x93\x93\x93\x93\x93\x9a\x93\x93\x1c\x93\x93\x93\x93\x93]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]\x95\x95II\x95\x95\x95\x95III\x95\x95\x8b\x8b\x8b\x8b\x95\x8b\x8b\x8bII\x95\x99\x95I]]]]]]]]]]]]]]]]]]]]]' -'44\x02{4{4\x024{z\x02\x02\x02zz\x02\x02\x02\x8f4\x02{44\x02\x02\x02\x02\x02444{{4\x024q4\x024\x02q\x02\x02Bz\x02\x024\x02z9999z4]]z\x02\x02' -'^iiii\x02zzzz4i]]]]]]]\xac\xac\x9c\x9c\x9c\x9c\x9c\x9c\xac\xac\xac\xac\x9c\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xb4\xb4\xb4\xb4\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xb4\xb4\xb4\xb4\xb4\xb4' -'\xb4\xb4\xb4[]]]]]]]]]]]]\t\t\t\t\t{{{{{ii4444i44i44i4444444i444444444{{444444' -'44444444444444ii44\t4\t444444444444444444{444444444444iiiiiiiiiiii' -'\t^77^ii\t7^^7^^i\ti7\x8a\x8ai7^iii7^^7\t77^^\t^\t^\t\t\t\t77^7^^^^^\t\t\t\ti^i^77^^' -'^^^^^^^^7^^^7iiiii7^^^iiiiiiiii^7\t^i7777^^77ii77^^^^^^^^^^^^^^^^' -'^^77^^77^^^^^ii^^^^ii\tii^\tiiiiiiii^^i\t^^^^^^^^^^^^^^^^^^^iiiii^7' -'iiiiiiiii^^^^^ii^^iiii^^^^^^^^^^^^^^^^^^^^^^^^ii^^^^^^^^^^^^^^^^' -'44444444^^^^444444{4444444444444^^4444444pt44444444444\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d4i444' -'444444444444444444444\x9d44444iiiiiiiiiiiiiiiiiiiiiiiii\xd0\xad\xbd444444444' -'444444444444444]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'444444444444444444444444444444444444444]]]]]]]]]]]]]]]]]]]]]]]]]' -'44444444444]]]]]]]]]]]]]]]]]]]]]\n\n\n\n\n\n\n\n\nWWWWWWWWWWW\n\n\n\n\n\n\n\n\nWWW' -'WWWWWWWW\n\n\n\n\n\n\n\n\nWWWWWWWWWWW!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' -'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x9b\xac\xac\xac\xac\xac\xac\xac\xac\xac\xacrrrrrrrrr\xac]' -'{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{' -'{{{{{{{{{{{{4444{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{444444444444' -'{{{{{{{{{{{{{{{{44{{{{4444444444{{4{{{{{{{44444444{{44{\t4444{{44' -'{\t4444{{{44{44{{{{4444444444444444{{{{444444444{44444444iiiiiiii' -'44444{{44{4444{{4444]]44]444{4{444444444444444444444444444444444' -'{4{44444444444444444444444444444{{4{{{4{{{{4{{4\t44444444444444]]' -'4444444444]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']4444]4444]]4444444444444444444444444444]44444444444444444444{44' -'444444444444]4]4444]]]4]4444444]]4444444\x91)\x91)\x91)\x91)\x91)\x91)\x91)rrrrrrrrr\xac' -'\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\x9c\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\x9c4]]]444444444444444444444444]44444444444444]' -']]]]]]]]]]]]]]]]iii^^^^iiiii^^^iii^^^^\x04\xda\x04\xda\x04\xda]]]]iiiiiiiiiiiiiiii' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'4444444444444444444444444444444444444444444444444444444444444444' -'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' -'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii' -'iii\x91)\x04\xda\x91)\x91)\x91)\x91)\x91)\x91)\x91)\x91)\x91)ii^^^^^^^^^^^^^^^^^^^^^iiiiiiii^iiiiiii' -'^^^^^^iii^iiii^^^^^i^^ii\x91)\x91)^iiii^i^^^ii^^iiiiiiiiii^^^^^^ii\x91)ii' -'iiiiiiiiii^^^^^^^^^^^^^^^^^^^i^^^^ii^i^ii^i^^^^iiiii^^iiiiii^^^i' -'iiiiiiiiiiiiiiiiiiiiiii^^iiiiiiiiiii^^iiii^^^^i^^ii^^iiii^^^^^^^' -'^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ii^^^^^^^^i^^^^^^^^^^^^^^^^^' -'^^^^^^^^^^^^^^^^^^^^^^^iiiii^i^iii^^^^^iiiii^^^iiii^iii^^^^^i^ii' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]]]]]]]]]]]]]]]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]' -'&\x1f\x1f\x1f\xd8OLwptptptptpt\xd8\xd8ptptptpt\\2nn\xd8wwwwwwwww\xa0\xc3\x7f\x06``\\OOOOO\xd8\xd8wwwOL\x1f\xd84' -']LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLL]]>>\x89\x89OOL\\LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLPOOOL' -']]]]]LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]LLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLL]??ssss??????????LLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]LLLLLLLLLLLLLLLL' -'?????????????????????????????]]]ssssssssss??????????????????????' -'????]]]]]]]]]]]]]\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1????????????????????????????]]]?' -'ssssssssss???????????????????????????????????????\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1' -'????????????]]]]???????????????????????????????????????????????]' -'????????????????????????????????????????????????????????????????' -'???????????????????????????????????????????????????????]]]]?????' -'????????????????????????????????????????????????????????????????' -'??????????????????????????????]]???????????????????????????????]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLL]]]\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8' -'\xd8\xd8\xd8\xd8\xd8\xd8\xd8]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]LLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'zzzzzzz]]]]]]]]]]]]zzzzz]]]]]\xbb\x0e\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\x8a\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb]\xbb\xbb\xbb\xbb\xbb]\xbb]' -'\xbb\xbb]\xbb\xbb]\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xd0\xad' -']]]]]]]]]]]]]]]]\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\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\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\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\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\xd6]]]' -'\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9]]]]]]]]]]]]]]]]\x95\x95\x95\x95]]]]]]]]]]]]\x1f\\\\PP2n2n2n2n2n2' -'n2n2n\x1f\x1f]]\x1f\x1f\x1f\x1fPPP\xcc\x1f\xcc]\x1f\xcc\x1f\x1f\\2n2n2n3\x1f\x1f\xb8_\xb5\xb5\xb5]\x1f\xd23\x1f]]]]\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\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\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\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\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\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16]]m' -']\x14\x14\x11\xab\x11\x14\x14\xbc/\x14(v\xb3v\xba\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92v\x14\xdb\xd4\xdb\x14\x14yyyyyyyyyyyyyyyyyyyyyyyyyy\xbc\x14/A\x08' -'A\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\xbc\xd4/\xd4\xbc/\xc2\xc0\x1a\xc2\x10DDDDDDDDDD\xd1DDDDDDDDDDDDDDD' -'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD\xd1\xd1DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD]' -"]]DDDDDD]]DDDDDD]]DDDDDD]]DDD]]]\xab\xab\xd4A \xab\xab]'\xb7\xb7\xb7\xb7'']]]]]]]]]]mmm4{]]" -'9999999999999999999999999999999]\xb0\xb0\xb0\xb0]]]]]]]]]]]]9999999999999999' -'9999999999[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02]]zzzzzzzzzzzzzzzzzzzzzzzz' -'zzzzzzzzzzzzzz]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d~~III\x9d\x9d\x9d*~~~~~mmmmmmmm\x99\x99\x99\x99\x99' -'\x99\x99\x99\x9d\x9d\x95\x95\x95\x95\x95\x99\x99\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x95\x95\x95\x95\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d' -'\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzz]zzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02]\x02\x02]]\x02]]\x02\x02]]\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02\x02zzzz]z]zzz' -'z]zz]zzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzz' -'zzzz\x02\x02]\x02\x02\x02\x02]]\x02\x02\x02\x02\x02\x02\x02\x02]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02]\x02\x02\x02\x02]' -'\x02\x02\x02\x02\x02]\x02]]]\x02\x02\x02\x02\x02\x02\x02]zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzz' -'zzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzz' -'zzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02zzzzzzzzzzzzzzzzzzzzzzzzzz]]]]\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02' -'\x02xzzzzzzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzz' -'zzzzzzzzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzz' -'zzzzzzzzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzz' -'zzzzzzzzzxzzzzzz\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02xzzzzzzzzzzzzzzzzzzzzzz' -'zzzxzzzzzz]]]]66666666666666666666666666666666666666666666666666' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' -'LLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'LLLLLLLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']m]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' -'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -']]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' -'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC]]' +'\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' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\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' ) def _get_record(code): @@ -23052,924 +23056,926 @@ return _raw_decomposition.get(code,'') +_composition_max = 12541 +_composition_shift = 14 _composition = { -(60, 824): 8814, -(61, 824): 8800, -(62, 824): 8815, -(65, 768): 192, -(65, 769): 193, -(65, 770): 194, -(65, 771): 195, -(65, 772): 256, -(65, 774): 258, -(65, 775): 550, -(65, 776): 196, -(65, 777): 7842, -(65, 778): 197, -(65, 780): 461, -(65, 783): 512, -(65, 785): 514, -(65, 803): 7840, -(65, 805): 7680, -(65, 808): 260, -(66, 775): 7682, -(66, 803): 7684, -(66, 817): 7686, -(67, 769): 262, -(67, 770): 264, -(67, 775): 266, -(67, 780): 268, -(67, 807): 199, -(68, 775): 7690, -(68, 780): 270, -(68, 803): 7692, -(68, 807): 7696, -(68, 813): 7698, -(68, 817): 7694, -(69, 768): 200, -(69, 769): 201, -(69, 770): 202, -(69, 771): 7868, -(69, 772): 274, -(69, 774): 276, -(69, 775): 278, -(69, 776): 203, -(69, 777): 7866, -(69, 780): 282, -(69, 783): 516, -(69, 785): 518, -(69, 803): 7864, -(69, 807): 552, -(69, 808): 280, -(69, 813): 7704, -(69, 816): 7706, -(70, 775): 7710, -(71, 769): 500, -(71, 770): 284, -(71, 772): 7712, -(71, 774): 286, -(71, 775): 288, -(71, 780): 486, -(71, 807): 290, -(72, 770): 292, -(72, 775): 7714, -(72, 776): 7718, -(72, 780): 542, -(72, 803): 7716, -(72, 807): 7720, -(72, 814): 7722, -(73, 768): 204, -(73, 769): 205, -(73, 770): 206, -(73, 771): 296, -(73, 772): 298, -(73, 774): 300, -(73, 775): 304, -(73, 776): 207, -(73, 777): 7880, -(73, 780): 463, -(73, 783): 520, -(73, 785): 522, -(73, 803): 7882, -(73, 808): 302, -(73, 816): 7724, -(74, 770): 308, -(75, 769): 7728, -(75, 780): 488, -(75, 803): 7730, -(75, 807): 310, -(75, 817): 7732, -(76, 769): 313, -(76, 780): 317, -(76, 803): 7734, -(76, 807): 315, -(76, 813): 7740, -(76, 817): 7738, -(77, 769): 7742, -(77, 775): 7744, -(77, 803): 7746, -(78, 768): 504, -(78, 769): 323, -(78, 771): 209, -(78, 775): 7748, -(78, 780): 327, -(78, 803): 7750, -(78, 807): 325, -(78, 813): 7754, -(78, 817): 7752, -(79, 768): 210, -(79, 769): 211, -(79, 770): 212, -(79, 771): 213, -(79, 772): 332, -(79, 774): 334, -(79, 775): 558, -(79, 776): 214, -(79, 777): 7886, -(79, 779): 336, -(79, 780): 465, -(79, 783): 524, -(79, 785): 526, -(79, 795): 416, -(79, 803): 7884, -(79, 808): 490, -(80, 769): 7764, -(80, 775): 7766, -(82, 769): 340, -(82, 775): 7768, -(82, 780): 344, -(82, 783): 528, -(82, 785): 530, -(82, 803): 7770, -(82, 807): 342, -(82, 817): 7774, -(83, 769): 346, -(83, 770): 348, -(83, 775): 7776, -(83, 780): 352, -(83, 803): 7778, -(83, 806): 536, -(83, 807): 350, -(84, 775): 7786, -(84, 780): 356, -(84, 803): 7788, -(84, 806): 538, -(84, 807): 354, -(84, 813): 7792, -(84, 817): 7790, -(85, 768): 217, -(85, 769): 218, -(85, 770): 219, -(85, 771): 360, -(85, 772): 362, -(85, 774): 364, -(85, 776): 220, -(85, 777): 7910, -(85, 778): 366, -(85, 779): 368, -(85, 780): 467, -(85, 783): 532, -(85, 785): 534, -(85, 795): 431, -(85, 803): 7908, -(85, 804): 7794, -(85, 808): 370, -(85, 813): 7798, -(85, 816): 7796, -(86, 771): 7804, -(86, 803): 7806, -(87, 768): 7808, -(87, 769): 7810, -(87, 770): 372, -(87, 775): 7814, -(87, 776): 7812, -(87, 803): 7816, -(88, 775): 7818, -(88, 776): 7820, -(89, 768): 7922, -(89, 769): 221, -(89, 770): 374, -(89, 771): 7928, -(89, 772): 562, -(89, 775): 7822, -(89, 776): 376, -(89, 777): 7926, -(89, 803): 7924, -(90, 769): 377, -(90, 770): 7824, -(90, 775): 379, -(90, 780): 381, -(90, 803): 7826, -(90, 817): 7828, -(97, 768): 224, -(97, 769): 225, -(97, 770): 226, -(97, 771): 227, -(97, 772): 257, -(97, 774): 259, -(97, 775): 551, -(97, 776): 228, -(97, 777): 7843, -(97, 778): 229, -(97, 780): 462, -(97, 783): 513, -(97, 785): 515, -(97, 803): 7841, -(97, 805): 7681, -(97, 808): 261, -(98, 775): 7683, -(98, 803): 7685, -(98, 817): 7687, -(99, 769): 263, -(99, 770): 265, -(99, 775): 267, -(99, 780): 269, -(99, 807): 231, -(100, 775): 7691, -(100, 780): 271, -(100, 803): 7693, -(100, 807): 7697, -(100, 813): 7699, -(100, 817): 7695, -(101, 768): 232, -(101, 769): 233, -(101, 770): 234, -(101, 771): 7869, -(101, 772): 275, -(101, 774): 277, -(101, 775): 279, -(101, 776): 235, -(101, 777): 7867, -(101, 780): 283, -(101, 783): 517, -(101, 785): 519, -(101, 803): 7865, -(101, 807): 553, -(101, 808): 281, -(101, 813): 7705, -(101, 816): 7707, -(102, 775): 7711, -(103, 769): 501, -(103, 770): 285, -(103, 772): 7713, -(103, 774): 287, -(103, 775): 289, -(103, 780): 487, -(103, 807): 291, -(104, 770): 293, -(104, 775): 7715, -(104, 776): 7719, -(104, 780): 543, -(104, 803): 7717, -(104, 807): 7721, -(104, 814): 7723, -(104, 817): 7830, -(105, 768): 236, -(105, 769): 237, -(105, 770): 238, -(105, 771): 297, -(105, 772): 299, -(105, 774): 301, -(105, 776): 239, -(105, 777): 7881, -(105, 780): 464, -(105, 783): 521, -(105, 785): 523, -(105, 803): 7883, -(105, 808): 303, -(105, 816): 7725, -(106, 770): 309, -(106, 780): 496, -(107, 769): 7729, -(107, 780): 489, -(107, 803): 7731, -(107, 807): 311, -(107, 817): 7733, -(108, 769): 314, -(108, 780): 318, -(108, 803): 7735, -(108, 807): 316, -(108, 813): 7741, -(108, 817): 7739, -(109, 769): 7743, -(109, 775): 7745, -(109, 803): 7747, -(110, 768): 505, -(110, 769): 324, -(110, 771): 241, -(110, 775): 7749, -(110, 780): 328, -(110, 803): 7751, -(110, 807): 326, -(110, 813): 7755, -(110, 817): 7753, -(111, 768): 242, -(111, 769): 243, -(111, 770): 244, -(111, 771): 245, -(111, 772): 333, -(111, 774): 335, -(111, 775): 559, -(111, 776): 246, -(111, 777): 7887, -(111, 779): 337, -(111, 780): 466, -(111, 783): 525, -(111, 785): 527, -(111, 795): 417, -(111, 803): 7885, -(111, 808): 491, -(112, 769): 7765, -(112, 775): 7767, -(114, 769): 341, -(114, 775): 7769, -(114, 780): 345, -(114, 783): 529, -(114, 785): 531, -(114, 803): 7771, -(114, 807): 343, -(114, 817): 7775, -(115, 769): 347, -(115, 770): 349, -(115, 775): 7777, -(115, 780): 353, -(115, 803): 7779, -(115, 806): 537, -(115, 807): 351, -(116, 775): 7787, -(116, 776): 7831, -(116, 780): 357, -(116, 803): 7789, -(116, 806): 539, -(116, 807): 355, -(116, 813): 7793, -(116, 817): 7791, -(117, 768): 249, -(117, 769): 250, -(117, 770): 251, -(117, 771): 361, -(117, 772): 363, -(117, 774): 365, -(117, 776): 252, -(117, 777): 7911, -(117, 778): 367, -(117, 779): 369, -(117, 780): 468, -(117, 783): 533, -(117, 785): 535, -(117, 795): 432, -(117, 803): 7909, -(117, 804): 7795, -(117, 808): 371, -(117, 813): 7799, -(117, 816): 7797, -(118, 771): 7805, -(118, 803): 7807, -(119, 768): 7809, -(119, 769): 7811, -(119, 770): 373, -(119, 775): 7815, -(119, 776): 7813, -(119, 778): 7832, -(119, 803): 7817, -(120, 775): 7819, -(120, 776): 7821, -(121, 768): 7923, -(121, 769): 253, -(121, 770): 375, -(121, 771): 7929, -(121, 772): 563, -(121, 775): 7823, -(121, 776): 255, -(121, 777): 7927, -(121, 778): 7833, -(121, 803): 7925, -(122, 769): 378, -(122, 770): 7825, -(122, 775): 380, -(122, 780): 382, -(122, 803): 7827, -(122, 817): 7829, -(168, 768): 8173, -(168, 769): 901, -(168, 834): 8129, -(194, 768): 7846, -(194, 769): 7844, -(194, 771): 7850, -(194, 777): 7848, -(196, 772): 478, -(197, 769): 506, -(198, 769): 508, -(198, 772): 482, -(199, 769): 7688, -(202, 768): 7872, -(202, 769): 7870, -(202, 771): 7876, -(202, 777): 7874, -(207, 769): 7726, -(212, 768): 7890, -(212, 769): 7888, -(212, 771): 7894, -(212, 777): 7892, -(213, 769): 7756, -(213, 772): 556, -(213, 776): 7758, -(214, 772): 554, -(216, 769): 510, -(220, 768): 475, -(220, 769): 471, -(220, 772): 469, -(220, 780): 473, -(226, 768): 7847, -(226, 769): 7845, -(226, 771): 7851, -(226, 777): 7849, -(228, 772): 479, -(229, 769): 507, -(230, 769): 509, -(230, 772): 483, -(231, 769): 7689, -(234, 768): 7873, -(234, 769): 7871, -(234, 771): 7877, -(234, 777): 7875, -(239, 769): 7727, -(244, 768): 7891, -(244, 769): 7889, -(244, 771): 7895, -(244, 777): 7893, -(245, 769): 7757, -(245, 772): 557, -(245, 776): 7759, -(246, 772): 555, -(248, 769): 511, -(252, 768): 476, -(252, 769): 472, -(252, 772): 470, -(252, 780): 474, -(258, 768): 7856, -(258, 769): 7854, -(258, 771): 7860, -(258, 777): 7858, -(259, 768): 7857, -(259, 769): 7855, -(259, 771): 7861, -(259, 777): 7859, -(274, 768): 7700, -(274, 769): 7702, -(275, 768): 7701, -(275, 769): 7703, -(332, 768): 7760, -(332, 769): 7762, -(333, 768): 7761, -(333, 769): 7763, -(346, 775): 7780, -(347, 775): 7781, -(352, 775): 7782, -(353, 775): 7783, -(360, 769): 7800, -(361, 769): 7801, -(362, 776): 7802, -(363, 776): 7803, -(383, 775): 7835, -(416, 768): 7900, -(416, 769): 7898, -(416, 771): 7904, -(416, 777): 7902, -(416, 803): 7906, -(417, 768): 7901, -(417, 769): 7899, -(417, 771): 7905, -(417, 777): 7903, -(417, 803): 7907, -(431, 768): 7914, -(431, 769): 7912, -(431, 771): 7918, -(431, 777): 7916, -(431, 803): 7920, -(432, 768): 7915, -(432, 769): 7913, -(432, 771): 7919, -(432, 777): 7917, -(432, 803): 7921, -(439, 780): 494, -(490, 772): 492, -(491, 772): 493, -(550, 772): 480, -(551, 772): 481, -(552, 774): 7708, -(553, 774): 7709, -(558, 772): 560, -(559, 772): 561, -(658, 780): 495, -(913, 768): 8122, -(913, 769): 902, -(913, 772): 8121, -(913, 774): 8120, -(913, 787): 7944, -(913, 788): 7945, -(913, 837): 8124, -(917, 768): 8136, -(917, 769): 904, -(917, 787): 7960, -(917, 788): 7961, -(919, 768): 8138, -(919, 769): 905, -(919, 787): 7976, -(919, 788): 7977, -(919, 837): 8140, -(921, 768): 8154, -(921, 769): 906, -(921, 772): 8153, -(921, 774): 8152, -(921, 776): 938, -(921, 787): 7992, -(921, 788): 7993, -(927, 768): 8184, -(927, 769): 908, -(927, 787): 8008, -(927, 788): 8009, -(929, 788): 8172, -(933, 768): 8170, -(933, 769): 910, -(933, 772): 8169, -(933, 774): 8168, -(933, 776): 939, -(933, 788): 8025, -(937, 768): 8186, -(937, 769): 911, -(937, 787): 8040, -(937, 788): 8041, -(937, 837): 8188, -(940, 837): 8116, -(942, 837): 8132, -(945, 768): 8048, -(945, 769): 940, -(945, 772): 8113, -(945, 774): 8112, -(945, 787): 7936, -(945, 788): 7937, -(945, 834): 8118, -(945, 837): 8115, -(949, 768): 8050, -(949, 769): 941, -(949, 787): 7952, -(949, 788): 7953, -(951, 768): 8052, -(951, 769): 942, -(951, 787): 7968, -(951, 788): 7969, -(951, 834): 8134, -(951, 837): 8131, -(953, 768): 8054, -(953, 769): 943, -(953, 772): 8145, -(953, 774): 8144, -(953, 776): 970, -(953, 787): 7984, -(953, 788): 7985, -(953, 834): 8150, -(959, 768): 8056, -(959, 769): 972, -(959, 787): 8000, -(959, 788): 8001, -(961, 787): 8164, -(961, 788): 8165, -(965, 768): 8058, -(965, 769): 973, -(965, 772): 8161, -(965, 774): 8160, -(965, 776): 971, -(965, 787): 8016, -(965, 788): 8017, -(965, 834): 8166, -(969, 768): 8060, -(969, 769): 974, -(969, 787): 8032, -(969, 788): 8033, -(969, 834): 8182, -(969, 837): 8179, -(970, 768): 8146, -(970, 769): 912, -(970, 834): 8151, -(971, 768): 8162, -(971, 769): 944, -(971, 834): 8167, -(974, 837): 8180, -(978, 769): 979, -(978, 776): 980, -(1030, 776): 1031, -(1040, 774): 1232, -(1040, 776): 1234, -(1043, 769): 1027, -(1045, 768): 1024, -(1045, 774): 1238, -(1045, 776): 1025, -(1046, 774): 1217, -(1046, 776): 1244, -(1047, 776): 1246, -(1048, 768): 1037, -(1048, 772): 1250, -(1048, 774): 1049, -(1048, 776): 1252, -(1050, 769): 1036, -(1054, 776): 1254, -(1059, 772): 1262, -(1059, 774): 1038, -(1059, 776): 1264, -(1059, 779): 1266, -(1063, 776): 1268, -(1067, 776): 1272, -(1069, 776): 1260, -(1072, 774): 1233, -(1072, 776): 1235, -(1075, 769): 1107, -(1077, 768): 1104, -(1077, 774): 1239, -(1077, 776): 1105, -(1078, 774): 1218, -(1078, 776): 1245, -(1079, 776): 1247, -(1080, 768): 1117, -(1080, 772): 1251, -(1080, 774): 1081, -(1080, 776): 1253, -(1082, 769): 1116, -(1086, 776): 1255, -(1091, 772): 1263, -(1091, 774): 1118, -(1091, 776): 1265, -(1091, 779): 1267, -(1095, 776): 1269, -(1099, 776): 1273, -(1101, 776): 1261, -(1110, 776): 1111, -(1140, 783): 1142, -(1141, 783): 1143, -(1240, 776): 1242, -(1241, 776): 1243, -(1256, 776): 1258, -(1257, 776): 1259, -(1575, 1619): 1570, -(1575, 1620): 1571, -(1575, 1621): 1573, -(1608, 1620): 1572, -(1610, 1620): 1574, -(1729, 1620): 1730, -(1746, 1620): 1747, -(1749, 1620): 1728, -(2344, 2364): 2345, -(2352, 2364): 2353, -(2355, 2364): 2356, -(2503, 2494): 2507, -(2503, 2519): 2508, -(2887, 2878): 2891, -(2887, 2902): 2888, -(2887, 2903): 2892, -(2962, 3031): 2964, -(3014, 3006): 3018, -(3014, 3031): 3020, -(3015, 3006): 3019, -(3142, 3158): 3144, -(3263, 3285): 3264, -(3270, 3266): 3274, -(3270, 3285): 3271, -(3270, 3286): 3272, -(3274, 3285): 3275, -(3398, 3390): 3402, -(3398, 3415): 3404, -(3399, 3390): 3403, -(3545, 3530): 3546, -(3545, 3535): 3548, -(3545, 3551): 3550, -(3548, 3530): 3549, -(4133, 4142): 4134, -(7734, 772): 7736, -(7735, 772): 7737, -(7770, 772): 7772, -(7771, 772): 7773, -(7778, 775): 7784, -(7779, 775): 7785, -(7840, 770): 7852, -(7840, 774): 7862, -(7841, 770): 7853, -(7841, 774): 7863, -(7864, 770): 7878, -(7865, 770): 7879, -(7884, 770): 7896, -(7885, 770): 7897, -(7936, 768): 7938, -(7936, 769): 7940, -(7936, 834): 7942, -(7936, 837): 8064, -(7937, 768): 7939, -(7937, 769): 7941, -(7937, 834): 7943, -(7937, 837): 8065, -(7938, 837): 8066, -(7939, 837): 8067, -(7940, 837): 8068, -(7941, 837): 8069, -(7942, 837): 8070, -(7943, 837): 8071, -(7944, 768): 7946, -(7944, 769): 7948, -(7944, 834): 7950, -(7944, 837): 8072, -(7945, 768): 7947, -(7945, 769): 7949, -(7945, 834): 7951, -(7945, 837): 8073, -(7946, 837): 8074, -(7947, 837): 8075, -(7948, 837): 8076, -(7949, 837): 8077, -(7950, 837): 8078, -(7951, 837): 8079, -(7952, 768): 7954, -(7952, 769): 7956, -(7953, 768): 7955, -(7953, 769): 7957, -(7960, 768): 7962, -(7960, 769): 7964, -(7961, 768): 7963, -(7961, 769): 7965, -(7968, 768): 7970, -(7968, 769): 7972, -(7968, 834): 7974, -(7968, 837): 8080, -(7969, 768): 7971, -(7969, 769): 7973, -(7969, 834): 7975, -(7969, 837): 8081, -(7970, 837): 8082, -(7971, 837): 8083, -(7972, 837): 8084, -(7973, 837): 8085, -(7974, 837): 8086, -(7975, 837): 8087, -(7976, 768): 7978, -(7976, 769): 7980, -(7976, 834): 7982, -(7976, 837): 8088, -(7977, 768): 7979, -(7977, 769): 7981, -(7977, 834): 7983, -(7977, 837): 8089, -(7978, 837): 8090, -(7979, 837): 8091, -(7980, 837): 8092, -(7981, 837): 8093, -(7982, 837): 8094, -(7983, 837): 8095, -(7984, 768): 7986, -(7984, 769): 7988, -(7984, 834): 7990, -(7985, 768): 7987, -(7985, 769): 7989, -(7985, 834): 7991, -(7992, 768): 7994, -(7992, 769): 7996, -(7992, 834): 7998, -(7993, 768): 7995, -(7993, 769): 7997, -(7993, 834): 7999, -(8000, 768): 8002, -(8000, 769): 8004, -(8001, 768): 8003, -(8001, 769): 8005, -(8008, 768): 8010, -(8008, 769): 8012, -(8009, 768): 8011, -(8009, 769): 8013, -(8016, 768): 8018, -(8016, 769): 8020, -(8016, 834): 8022, -(8017, 768): 8019, -(8017, 769): 8021, -(8017, 834): 8023, -(8025, 768): 8027, -(8025, 769): 8029, -(8025, 834): 8031, -(8032, 768): 8034, -(8032, 769): 8036, -(8032, 834): 8038, -(8032, 837): 8096, -(8033, 768): 8035, -(8033, 769): 8037, -(8033, 834): 8039, -(8033, 837): 8097, -(8034, 837): 8098, -(8035, 837): 8099, -(8036, 837): 8100, -(8037, 837): 8101, -(8038, 837): 8102, -(8039, 837): 8103, -(8040, 768): 8042, -(8040, 769): 8044, -(8040, 834): 8046, -(8040, 837): 8104, -(8041, 768): 8043, -(8041, 769): 8045, -(8041, 834): 8047, -(8041, 837): 8105, -(8042, 837): 8106, -(8043, 837): 8107, -(8044, 837): 8108, -(8045, 837): 8109, -(8046, 837): 8110, -(8047, 837): 8111, -(8048, 837): 8114, -(8052, 837): 8130, -(8060, 837): 8178, -(8118, 837): 8119, -(8127, 768): 8141, -(8127, 769): 8142, -(8127, 834): 8143, -(8134, 837): 8135, -(8182, 837): 8183, -(8190, 768): 8157, -(8190, 769): 8158, -(8190, 834): 8159, -(8592, 824): 8602, -(8594, 824): 8603, -(8596, 824): 8622, -(8656, 824): 8653, -(8658, 824): 8655, -(8660, 824): 8654, -(8707, 824): 8708, -(8712, 824): 8713, -(8715, 824): 8716, -(8739, 824): 8740, -(8741, 824): 8742, -(8764, 824): 8769, -(8771, 824): 8772, -(8773, 824): 8775, -(8776, 824): 8777, -(8781, 824): 8813, -(8801, 824): 8802, -(8804, 824): 8816, -(8805, 824): 8817, -(8818, 824): 8820, -(8819, 824): 8821, -(8822, 824): 8824, -(8823, 824): 8825, -(8826, 824): 8832, -(8827, 824): 8833, -(8828, 824): 8928, -(8829, 824): 8929, -(8834, 824): 8836, -(8835, 824): 8837, -(8838, 824): 8840, -(8839, 824): 8841, -(8849, 824): 8930, -(8850, 824): 8931, -(8866, 824): 8876, -(8872, 824): 8877, -(8873, 824): 8878, -(8875, 824): 8879, -(8882, 824): 8938, -(8883, 824): 8939, -(8884, 824): 8940, -(8885, 824): 8941, -(12358, 12441): 12436, -(12363, 12441): 12364, -(12365, 12441): 12366, -(12367, 12441): 12368, -(12369, 12441): 12370, -(12371, 12441): 12372, -(12373, 12441): 12374, -(12375, 12441): 12376, -(12377, 12441): 12378, -(12379, 12441): 12380, -(12381, 12441): 12382, -(12383, 12441): 12384, -(12385, 12441): 12386, -(12388, 12441): 12389, -(12390, 12441): 12391, -(12392, 12441): 12393, -(12399, 12441): 12400, -(12399, 12442): 12401, -(12402, 12441): 12403, -(12402, 12442): 12404, -(12405, 12441): 12406, -(12405, 12442): 12407, -(12408, 12441): 12409, -(12408, 12442): 12410, -(12411, 12441): 12412, -(12411, 12442): 12413, -(12445, 12441): 12446, -(12454, 12441): 12532, -(12459, 12441): 12460, -(12461, 12441): 12462, -(12463, 12441): 12464, -(12465, 12441): 12466, -(12467, 12441): 12468, -(12469, 12441): 12470, -(12471, 12441): 12472, -(12473, 12441): 12474, -(12475, 12441): 12476, -(12477, 12441): 12478, -(12479, 12441): 12480, -(12481, 12441): 12482, -(12484, 12441): 12485, -(12486, 12441): 12487, -(12488, 12441): 12489, -(12495, 12441): 12496, -(12495, 12442): 12497, -(12498, 12441): 12499, -(12498, 12442): 12500, -(12501, 12441): 12502, -(12501, 12442): 12503, -(12504, 12441): 12505, -(12504, 12442): 12506, -(12507, 12441): 12508, -(12507, 12442): 12509, -(12527, 12441): 12535, -(12528, 12441): 12536, -(12529, 12441): 12537, -(12530, 12441): 12538, -(12541, 12441): 12542, + 65 << 14 | 768: 192, + 65 << 14 | 769: 193, + 65 << 14 | 770: 194, + 65 << 14 | 771: 195, + 65 << 14 | 776: 196, + 65 << 14 | 778: 197, + 67 << 14 | 807: 199, + 69 << 14 | 768: 200, + 69 << 14 | 769: 201, + 69 << 14 | 770: 202, + 69 << 14 | 776: 203, + 73 << 14 | 768: 204, + 73 << 14 | 769: 205, + 73 << 14 | 770: 206, + 73 << 14 | 776: 207, + 78 << 14 | 771: 209, + 79 << 14 | 768: 210, + 79 << 14 | 769: 211, + 79 << 14 | 770: 212, + 79 << 14 | 771: 213, + 79 << 14 | 776: 214, + 85 << 14 | 768: 217, + 85 << 14 | 769: 218, + 85 << 14 | 770: 219, + 85 << 14 | 776: 220, + 89 << 14 | 769: 221, + 97 << 14 | 768: 224, + 97 << 14 | 769: 225, + 97 << 14 | 770: 226, + 97 << 14 | 771: 227, + 97 << 14 | 776: 228, + 97 << 14 | 778: 229, + 99 << 14 | 807: 231, + 101 << 14 | 768: 232, + 101 << 14 | 769: 233, + 101 << 14 | 770: 234, + 101 << 14 | 776: 235, + 105 << 14 | 768: 236, + 105 << 14 | 769: 237, + 105 << 14 | 770: 238, + 105 << 14 | 776: 239, + 110 << 14 | 771: 241, + 111 << 14 | 768: 242, + 111 << 14 | 769: 243, + 111 << 14 | 770: 244, + 111 << 14 | 771: 245, + 111 << 14 | 776: 246, + 117 << 14 | 768: 249, + 117 << 14 | 769: 250, + 117 << 14 | 770: 251, + 117 << 14 | 776: 252, + 121 << 14 | 769: 253, + 121 << 14 | 776: 255, + 65 << 14 | 772: 256, + 97 << 14 | 772: 257, + 65 << 14 | 774: 258, + 97 << 14 | 774: 259, + 65 << 14 | 808: 260, + 97 << 14 | 808: 261, + 67 << 14 | 769: 262, + 99 << 14 | 769: 263, + 67 << 14 | 770: 264, + 99 << 14 | 770: 265, + 67 << 14 | 775: 266, + 99 << 14 | 775: 267, + 67 << 14 | 780: 268, + 99 << 14 | 780: 269, + 68 << 14 | 780: 270, + 100 << 14 | 780: 271, + 69 << 14 | 772: 274, + 101 << 14 | 772: 275, + 69 << 14 | 774: 276, + 101 << 14 | 774: 277, + 69 << 14 | 775: 278, + 101 << 14 | 775: 279, + 69 << 14 | 808: 280, + 101 << 14 | 808: 281, + 69 << 14 | 780: 282, + 101 << 14 | 780: 283, + 71 << 14 | 770: 284, + 103 << 14 | 770: 285, + 71 << 14 | 774: 286, + 103 << 14 | 774: 287, + 71 << 14 | 775: 288, + 103 << 14 | 775: 289, + 71 << 14 | 807: 290, + 103 << 14 | 807: 291, + 72 << 14 | 770: 292, + 104 << 14 | 770: 293, + 73 << 14 | 771: 296, + 105 << 14 | 771: 297, + 73 << 14 | 772: 298, + 105 << 14 | 772: 299, + 73 << 14 | 774: 300, + 105 << 14 | 774: 301, + 73 << 14 | 808: 302, + 105 << 14 | 808: 303, + 73 << 14 | 775: 304, + 74 << 14 | 770: 308, + 106 << 14 | 770: 309, + 75 << 14 | 807: 310, + 107 << 14 | 807: 311, + 76 << 14 | 769: 313, + 108 << 14 | 769: 314, + 76 << 14 | 807: 315, + 108 << 14 | 807: 316, + 76 << 14 | 780: 317, + 108 << 14 | 780: 318, + 78 << 14 | 769: 323, + 110 << 14 | 769: 324, + 78 << 14 | 807: 325, + 110 << 14 | 807: 326, + 78 << 14 | 780: 327, + 110 << 14 | 780: 328, + 79 << 14 | 772: 332, + 111 << 14 | 772: 333, + 79 << 14 | 774: 334, + 111 << 14 | 774: 335, + 79 << 14 | 779: 336, + 111 << 14 | 779: 337, + 82 << 14 | 769: 340, + 114 << 14 | 769: 341, + 82 << 14 | 807: 342, + 114 << 14 | 807: 343, + 82 << 14 | 780: 344, + 114 << 14 | 780: 345, + 83 << 14 | 769: 346, + 115 << 14 | 769: 347, + 83 << 14 | 770: 348, + 115 << 14 | 770: 349, + 83 << 14 | 807: 350, + 115 << 14 | 807: 351, + 83 << 14 | 780: 352, + 115 << 14 | 780: 353, + 84 << 14 | 807: 354, + 116 << 14 | 807: 355, + 84 << 14 | 780: 356, + 116 << 14 | 780: 357, + 85 << 14 | 771: 360, + 117 << 14 | 771: 361, + 85 << 14 | 772: 362, + 117 << 14 | 772: 363, + 85 << 14 | 774: 364, + 117 << 14 | 774: 365, + 85 << 14 | 778: 366, + 117 << 14 | 778: 367, + 85 << 14 | 779: 368, + 117 << 14 | 779: 369, + 85 << 14 | 808: 370, + 117 << 14 | 808: 371, + 87 << 14 | 770: 372, + 119 << 14 | 770: 373, + 89 << 14 | 770: 374, + 121 << 14 | 770: 375, + 89 << 14 | 776: 376, + 90 << 14 | 769: 377, + 122 << 14 | 769: 378, + 90 << 14 | 775: 379, + 122 << 14 | 775: 380, + 90 << 14 | 780: 381, + 122 << 14 | 780: 382, + 79 << 14 | 795: 416, + 111 << 14 | 795: 417, + 85 << 14 | 795: 431, + 117 << 14 | 795: 432, + 65 << 14 | 780: 461, + 97 << 14 | 780: 462, + 73 << 14 | 780: 463, + 105 << 14 | 780: 464, + 79 << 14 | 780: 465, + 111 << 14 | 780: 466, + 85 << 14 | 780: 467, + 117 << 14 | 780: 468, + 220 << 14 | 772: 469, + 252 << 14 | 772: 470, + 220 << 14 | 769: 471, + 252 << 14 | 769: 472, + 220 << 14 | 780: 473, + 252 << 14 | 780: 474, + 220 << 14 | 768: 475, + 252 << 14 | 768: 476, + 196 << 14 | 772: 478, + 228 << 14 | 772: 479, + 550 << 14 | 772: 480, + 551 << 14 | 772: 481, + 198 << 14 | 772: 482, + 230 << 14 | 772: 483, + 71 << 14 | 780: 486, + 103 << 14 | 780: 487, + 75 << 14 | 780: 488, + 107 << 14 | 780: 489, + 79 << 14 | 808: 490, + 111 << 14 | 808: 491, + 490 << 14 | 772: 492, + 491 << 14 | 772: 493, + 439 << 14 | 780: 494, + 658 << 14 | 780: 495, + 106 << 14 | 780: 496, + 71 << 14 | 769: 500, + 103 << 14 | 769: 501, + 78 << 14 | 768: 504, + 110 << 14 | 768: 505, + 197 << 14 | 769: 506, + 229 << 14 | 769: 507, + 198 << 14 | 769: 508, + 230 << 14 | 769: 509, + 216 << 14 | 769: 510, + 248 << 14 | 769: 511, + 65 << 14 | 783: 512, + 97 << 14 | 783: 513, + 65 << 14 | 785: 514, + 97 << 14 | 785: 515, + 69 << 14 | 783: 516, + 101 << 14 | 783: 517, + 69 << 14 | 785: 518, + 101 << 14 | 785: 519, + 73 << 14 | 783: 520, + 105 << 14 | 783: 521, + 73 << 14 | 785: 522, + 105 << 14 | 785: 523, + 79 << 14 | 783: 524, + 111 << 14 | 783: 525, + 79 << 14 | 785: 526, + 111 << 14 | 785: 527, + 82 << 14 | 783: 528, + 114 << 14 | 783: 529, + 82 << 14 | 785: 530, + 114 << 14 | 785: 531, + 85 << 14 | 783: 532, + 117 << 14 | 783: 533, + 85 << 14 | 785: 534, + 117 << 14 | 785: 535, + 83 << 14 | 806: 536, + 115 << 14 | 806: 537, + 84 << 14 | 806: 538, + 116 << 14 | 806: 539, + 72 << 14 | 780: 542, + 104 << 14 | 780: 543, + 65 << 14 | 775: 550, + 97 << 14 | 775: 551, + 69 << 14 | 807: 552, + 101 << 14 | 807: 553, + 214 << 14 | 772: 554, + 246 << 14 | 772: 555, + 213 << 14 | 772: 556, + 245 << 14 | 772: 557, + 79 << 14 | 775: 558, + 111 << 14 | 775: 559, + 558 << 14 | 772: 560, + 559 << 14 | 772: 561, + 89 << 14 | 772: 562, + 121 << 14 | 772: 563, + 168 << 14 | 769: 901, + 913 << 14 | 769: 902, + 917 << 14 | 769: 904, + 919 << 14 | 769: 905, + 921 << 14 | 769: 906, + 927 << 14 | 769: 908, + 933 << 14 | 769: 910, + 937 << 14 | 769: 911, + 970 << 14 | 769: 912, + 921 << 14 | 776: 938, + 933 << 14 | 776: 939, + 945 << 14 | 769: 940, + 949 << 14 | 769: 941, + 951 << 14 | 769: 942, + 953 << 14 | 769: 943, + 971 << 14 | 769: 944, + 953 << 14 | 776: 970, + 965 << 14 | 776: 971, + 959 << 14 | 769: 972, + 965 << 14 | 769: 973, + 969 << 14 | 769: 974, + 978 << 14 | 769: 979, + 978 << 14 | 776: 980, + 1045 << 14 | 768: 1024, + 1045 << 14 | 776: 1025, + 1043 << 14 | 769: 1027, + 1030 << 14 | 776: 1031, + 1050 << 14 | 769: 1036, + 1048 << 14 | 768: 1037, + 1059 << 14 | 774: 1038, + 1048 << 14 | 774: 1049, + 1080 << 14 | 774: 1081, + 1077 << 14 | 768: 1104, + 1077 << 14 | 776: 1105, + 1075 << 14 | 769: 1107, + 1110 << 14 | 776: 1111, + 1082 << 14 | 769: 1116, + 1080 << 14 | 768: 1117, + 1091 << 14 | 774: 1118, + 1140 << 14 | 783: 1142, + 1141 << 14 | 783: 1143, + 1046 << 14 | 774: 1217, + 1078 << 14 | 774: 1218, + 1040 << 14 | 774: 1232, + 1072 << 14 | 774: 1233, + 1040 << 14 | 776: 1234, + 1072 << 14 | 776: 1235, + 1045 << 14 | 774: 1238, + 1077 << 14 | 774: 1239, + 1240 << 14 | 776: 1242, + 1241 << 14 | 776: 1243, + 1046 << 14 | 776: 1244, + 1078 << 14 | 776: 1245, + 1047 << 14 | 776: 1246, + 1079 << 14 | 776: 1247, + 1048 << 14 | 772: 1250, + 1080 << 14 | 772: 1251, + 1048 << 14 | 776: 1252, + 1080 << 14 | 776: 1253, + 1054 << 14 | 776: 1254, + 1086 << 14 | 776: 1255, + 1256 << 14 | 776: 1258, + 1257 << 14 | 776: 1259, + 1069 << 14 | 776: 1260, + 1101 << 14 | 776: 1261, + 1059 << 14 | 772: 1262, + 1091 << 14 | 772: 1263, + 1059 << 14 | 776: 1264, + 1091 << 14 | 776: 1265, + 1059 << 14 | 779: 1266, + 1091 << 14 | 779: 1267, + 1063 << 14 | 776: 1268, + 1095 << 14 | 776: 1269, + 1067 << 14 | 776: 1272, + 1099 << 14 | 776: 1273, + 1575 << 14 | 1619: 1570, + 1575 << 14 | 1620: 1571, + 1608 << 14 | 1620: 1572, + 1575 << 14 | 1621: 1573, + 1610 << 14 | 1620: 1574, + 1749 << 14 | 1620: 1728, + 1729 << 14 | 1620: 1730, + 1746 << 14 | 1620: 1747, + 2344 << 14 | 2364: 2345, + 2352 << 14 | 2364: 2353, + 2355 << 14 | 2364: 2356, + 2503 << 14 | 2494: 2507, + 2503 << 14 | 2519: 2508, + 2887 << 14 | 2902: 2888, + 2887 << 14 | 2878: 2891, + 2887 << 14 | 2903: 2892, + 2962 << 14 | 3031: 2964, + 3014 << 14 | 3006: 3018, + 3015 << 14 | 3006: 3019, + 3014 << 14 | 3031: 3020, + 3142 << 14 | 3158: 3144, + 3263 << 14 | 3285: 3264, + 3270 << 14 | 3285: 3271, + 3270 << 14 | 3286: 3272, + 3270 << 14 | 3266: 3274, + 3274 << 14 | 3285: 3275, + 3398 << 14 | 3390: 3402, + 3399 << 14 | 3390: 3403, + 3398 << 14 | 3415: 3404, + 3545 << 14 | 3530: 3546, + 3545 << 14 | 3535: 3548, + 3548 << 14 | 3530: 3549, + 3545 << 14 | 3551: 3550, + 4133 << 14 | 4142: 4134, + 65 << 14 | 805: 7680, + 97 << 14 | 805: 7681, + 66 << 14 | 775: 7682, + 98 << 14 | 775: 7683, + 66 << 14 | 803: 7684, + 98 << 14 | 803: 7685, + 66 << 14 | 817: 7686, + 98 << 14 | 817: 7687, + 199 << 14 | 769: 7688, + 231 << 14 | 769: 7689, + 68 << 14 | 775: 7690, + 100 << 14 | 775: 7691, + 68 << 14 | 803: 7692, + 100 << 14 | 803: 7693, + 68 << 14 | 817: 7694, + 100 << 14 | 817: 7695, + 68 << 14 | 807: 7696, + 100 << 14 | 807: 7697, + 68 << 14 | 813: 7698, + 100 << 14 | 813: 7699, + 274 << 14 | 768: 7700, + 275 << 14 | 768: 7701, + 274 << 14 | 769: 7702, + 275 << 14 | 769: 7703, + 69 << 14 | 813: 7704, + 101 << 14 | 813: 7705, + 69 << 14 | 816: 7706, + 101 << 14 | 816: 7707, + 552 << 14 | 774: 7708, + 553 << 14 | 774: 7709, + 70 << 14 | 775: 7710, + 102 << 14 | 775: 7711, + 71 << 14 | 772: 7712, + 103 << 14 | 772: 7713, + 72 << 14 | 775: 7714, + 104 << 14 | 775: 7715, + 72 << 14 | 803: 7716, + 104 << 14 | 803: 7717, + 72 << 14 | 776: 7718, + 104 << 14 | 776: 7719, + 72 << 14 | 807: 7720, + 104 << 14 | 807: 7721, + 72 << 14 | 814: 7722, + 104 << 14 | 814: 7723, + 73 << 14 | 816: 7724, + 105 << 14 | 816: 7725, + 207 << 14 | 769: 7726, + 239 << 14 | 769: 7727, + 75 << 14 | 769: 7728, + 107 << 14 | 769: 7729, + 75 << 14 | 803: 7730, + 107 << 14 | 803: 7731, + 75 << 14 | 817: 7732, + 107 << 14 | 817: 7733, + 76 << 14 | 803: 7734, + 108 << 14 | 803: 7735, + 7734 << 14 | 772: 7736, + 7735 << 14 | 772: 7737, + 76 << 14 | 817: 7738, + 108 << 14 | 817: 7739, + 76 << 14 | 813: 7740, + 108 << 14 | 813: 7741, + 77 << 14 | 769: 7742, + 109 << 14 | 769: 7743, + 77 << 14 | 775: 7744, + 109 << 14 | 775: 7745, + 77 << 14 | 803: 7746, + 109 << 14 | 803: 7747, + 78 << 14 | 775: 7748, + 110 << 14 | 775: 7749, + 78 << 14 | 803: 7750, + 110 << 14 | 803: 7751, + 78 << 14 | 817: 7752, + 110 << 14 | 817: 7753, + 78 << 14 | 813: 7754, + 110 << 14 | 813: 7755, + 213 << 14 | 769: 7756, + 245 << 14 | 769: 7757, + 213 << 14 | 776: 7758, + 245 << 14 | 776: 7759, + 332 << 14 | 768: 7760, + 333 << 14 | 768: 7761, + 332 << 14 | 769: 7762, + 333 << 14 | 769: 7763, + 80 << 14 | 769: 7764, + 112 << 14 | 769: 7765, + 80 << 14 | 775: 7766, + 112 << 14 | 775: 7767, + 82 << 14 | 775: 7768, + 114 << 14 | 775: 7769, + 82 << 14 | 803: 7770, + 114 << 14 | 803: 7771, + 7770 << 14 | 772: 7772, + 7771 << 14 | 772: 7773, + 82 << 14 | 817: 7774, + 114 << 14 | 817: 7775, + 83 << 14 | 775: 7776, + 115 << 14 | 775: 7777, + 83 << 14 | 803: 7778, + 115 << 14 | 803: 7779, + 346 << 14 | 775: 7780, + 347 << 14 | 775: 7781, + 352 << 14 | 775: 7782, + 353 << 14 | 775: 7783, + 7778 << 14 | 775: 7784, + 7779 << 14 | 775: 7785, + 84 << 14 | 775: 7786, + 116 << 14 | 775: 7787, + 84 << 14 | 803: 7788, + 116 << 14 | 803: 7789, + 84 << 14 | 817: 7790, + 116 << 14 | 817: 7791, + 84 << 14 | 813: 7792, + 116 << 14 | 813: 7793, + 85 << 14 | 804: 7794, + 117 << 14 | 804: 7795, + 85 << 14 | 816: 7796, + 117 << 14 | 816: 7797, + 85 << 14 | 813: 7798, + 117 << 14 | 813: 7799, + 360 << 14 | 769: 7800, + 361 << 14 | 769: 7801, + 362 << 14 | 776: 7802, + 363 << 14 | 776: 7803, + 86 << 14 | 771: 7804, + 118 << 14 | 771: 7805, + 86 << 14 | 803: 7806, + 118 << 14 | 803: 7807, + 87 << 14 | 768: 7808, + 119 << 14 | 768: 7809, + 87 << 14 | 769: 7810, + 119 << 14 | 769: 7811, + 87 << 14 | 776: 7812, + 119 << 14 | 776: 7813, + 87 << 14 | 775: 7814, + 119 << 14 | 775: 7815, + 87 << 14 | 803: 7816, + 119 << 14 | 803: 7817, + 88 << 14 | 775: 7818, + 120 << 14 | 775: 7819, + 88 << 14 | 776: 7820, + 120 << 14 | 776: 7821, + 89 << 14 | 775: 7822, + 121 << 14 | 775: 7823, + 90 << 14 | 770: 7824, + 122 << 14 | 770: 7825, + 90 << 14 | 803: 7826, + 122 << 14 | 803: 7827, + 90 << 14 | 817: 7828, + 122 << 14 | 817: 7829, + 104 << 14 | 817: 7830, + 116 << 14 | 776: 7831, + 119 << 14 | 778: 7832, + 121 << 14 | 778: 7833, + 383 << 14 | 775: 7835, + 65 << 14 | 803: 7840, + 97 << 14 | 803: 7841, + 65 << 14 | 777: 7842, + 97 << 14 | 777: 7843, + 194 << 14 | 769: 7844, + 226 << 14 | 769: 7845, + 194 << 14 | 768: 7846, + 226 << 14 | 768: 7847, + 194 << 14 | 777: 7848, + 226 << 14 | 777: 7849, + 194 << 14 | 771: 7850, + 226 << 14 | 771: 7851, + 7840 << 14 | 770: 7852, + 7841 << 14 | 770: 7853, + 258 << 14 | 769: 7854, + 259 << 14 | 769: 7855, + 258 << 14 | 768: 7856, + 259 << 14 | 768: 7857, + 258 << 14 | 777: 7858, + 259 << 14 | 777: 7859, + 258 << 14 | 771: 7860, + 259 << 14 | 771: 7861, + 7840 << 14 | 774: 7862, + 7841 << 14 | 774: 7863, + 69 << 14 | 803: 7864, + 101 << 14 | 803: 7865, + 69 << 14 | 777: 7866, + 101 << 14 | 777: 7867, + 69 << 14 | 771: 7868, + 101 << 14 | 771: 7869, + 202 << 14 | 769: 7870, + 234 << 14 | 769: 7871, + 202 << 14 | 768: 7872, + 234 << 14 | 768: 7873, + 202 << 14 | 777: 7874, + 234 << 14 | 777: 7875, + 202 << 14 | 771: 7876, + 234 << 14 | 771: 7877, + 7864 << 14 | 770: 7878, + 7865 << 14 | 770: 7879, + 73 << 14 | 777: 7880, + 105 << 14 | 777: 7881, + 73 << 14 | 803: 7882, + 105 << 14 | 803: 7883, + 79 << 14 | 803: 7884, + 111 << 14 | 803: 7885, + 79 << 14 | 777: 7886, + 111 << 14 | 777: 7887, + 212 << 14 | 769: 7888, + 244 << 14 | 769: 7889, + 212 << 14 | 768: 7890, + 244 << 14 | 768: 7891, + 212 << 14 | 777: 7892, + 244 << 14 | 777: 7893, + 212 << 14 | 771: 7894, + 244 << 14 | 771: 7895, + 7884 << 14 | 770: 7896, + 7885 << 14 | 770: 7897, + 416 << 14 | 769: 7898, + 417 << 14 | 769: 7899, + 416 << 14 | 768: 7900, + 417 << 14 | 768: 7901, + 416 << 14 | 777: 7902, + 417 << 14 | 777: 7903, + 416 << 14 | 771: 7904, + 417 << 14 | 771: 7905, + 416 << 14 | 803: 7906, + 417 << 14 | 803: 7907, + 85 << 14 | 803: 7908, + 117 << 14 | 803: 7909, + 85 << 14 | 777: 7910, + 117 << 14 | 777: 7911, + 431 << 14 | 769: 7912, + 432 << 14 | 769: 7913, + 431 << 14 | 768: 7914, + 432 << 14 | 768: 7915, + 431 << 14 | 777: 7916, + 432 << 14 | 777: 7917, + 431 << 14 | 771: 7918, + 432 << 14 | 771: 7919, + 431 << 14 | 803: 7920, + 432 << 14 | 803: 7921, + 89 << 14 | 768: 7922, + 121 << 14 | 768: 7923, + 89 << 14 | 803: 7924, + 121 << 14 | 803: 7925, + 89 << 14 | 777: 7926, + 121 << 14 | 777: 7927, + 89 << 14 | 771: 7928, + 121 << 14 | 771: 7929, + 945 << 14 | 787: 7936, + 945 << 14 | 788: 7937, + 7936 << 14 | 768: 7938, + 7937 << 14 | 768: 7939, + 7936 << 14 | 769: 7940, + 7937 << 14 | 769: 7941, + 7936 << 14 | 834: 7942, + 7937 << 14 | 834: 7943, + 913 << 14 | 787: 7944, + 913 << 14 | 788: 7945, + 7944 << 14 | 768: 7946, + 7945 << 14 | 768: 7947, + 7944 << 14 | 769: 7948, + 7945 << 14 | 769: 7949, + 7944 << 14 | 834: 7950, + 7945 << 14 | 834: 7951, + 949 << 14 | 787: 7952, + 949 << 14 | 788: 7953, + 7952 << 14 | 768: 7954, + 7953 << 14 | 768: 7955, + 7952 << 14 | 769: 7956, + 7953 << 14 | 769: 7957, + 917 << 14 | 787: 7960, + 917 << 14 | 788: 7961, + 7960 << 14 | 768: 7962, + 7961 << 14 | 768: 7963, + 7960 << 14 | 769: 7964, + 7961 << 14 | 769: 7965, + 951 << 14 | 787: 7968, + 951 << 14 | 788: 7969, + 7968 << 14 | 768: 7970, + 7969 << 14 | 768: 7971, + 7968 << 14 | 769: 7972, + 7969 << 14 | 769: 7973, + 7968 << 14 | 834: 7974, + 7969 << 14 | 834: 7975, + 919 << 14 | 787: 7976, + 919 << 14 | 788: 7977, + 7976 << 14 | 768: 7978, + 7977 << 14 | 768: 7979, + 7976 << 14 | 769: 7980, + 7977 << 14 | 769: 7981, + 7976 << 14 | 834: 7982, + 7977 << 14 | 834: 7983, + 953 << 14 | 787: 7984, + 953 << 14 | 788: 7985, + 7984 << 14 | 768: 7986, + 7985 << 14 | 768: 7987, + 7984 << 14 | 769: 7988, + 7985 << 14 | 769: 7989, + 7984 << 14 | 834: 7990, + 7985 << 14 | 834: 7991, + 921 << 14 | 787: 7992, + 921 << 14 | 788: 7993, + 7992 << 14 | 768: 7994, + 7993 << 14 | 768: 7995, + 7992 << 14 | 769: 7996, + 7993 << 14 | 769: 7997, + 7992 << 14 | 834: 7998, + 7993 << 14 | 834: 7999, + 959 << 14 | 787: 8000, + 959 << 14 | 788: 8001, + 8000 << 14 | 768: 8002, + 8001 << 14 | 768: 8003, + 8000 << 14 | 769: 8004, + 8001 << 14 | 769: 8005, + 927 << 14 | 787: 8008, + 927 << 14 | 788: 8009, + 8008 << 14 | 768: 8010, + 8009 << 14 | 768: 8011, + 8008 << 14 | 769: 8012, + 8009 << 14 | 769: 8013, + 965 << 14 | 787: 8016, + 965 << 14 | 788: 8017, + 8016 << 14 | 768: 8018, + 8017 << 14 | 768: 8019, + 8016 << 14 | 769: 8020, + 8017 << 14 | 769: 8021, + 8016 << 14 | 834: 8022, + 8017 << 14 | 834: 8023, + 933 << 14 | 788: 8025, + 8025 << 14 | 768: 8027, + 8025 << 14 | 769: 8029, + 8025 << 14 | 834: 8031, + 969 << 14 | 787: 8032, + 969 << 14 | 788: 8033, + 8032 << 14 | 768: 8034, + 8033 << 14 | 768: 8035, + 8032 << 14 | 769: 8036, + 8033 << 14 | 769: 8037, + 8032 << 14 | 834: 8038, + 8033 << 14 | 834: 8039, + 937 << 14 | 787: 8040, + 937 << 14 | 788: 8041, + 8040 << 14 | 768: 8042, + 8041 << 14 | 768: 8043, + 8040 << 14 | 769: 8044, + 8041 << 14 | 769: 8045, + 8040 << 14 | 834: 8046, + 8041 << 14 | 834: 8047, + 945 << 14 | 768: 8048, + 949 << 14 | 768: 8050, + 951 << 14 | 768: 8052, + 953 << 14 | 768: 8054, + 959 << 14 | 768: 8056, + 965 << 14 | 768: 8058, + 969 << 14 | 768: 8060, + 7936 << 14 | 837: 8064, + 7937 << 14 | 837: 8065, + 7938 << 14 | 837: 8066, + 7939 << 14 | 837: 8067, + 7940 << 14 | 837: 8068, + 7941 << 14 | 837: 8069, + 7942 << 14 | 837: 8070, + 7943 << 14 | 837: 8071, + 7944 << 14 | 837: 8072, + 7945 << 14 | 837: 8073, + 7946 << 14 | 837: 8074, + 7947 << 14 | 837: 8075, + 7948 << 14 | 837: 8076, + 7949 << 14 | 837: 8077, + 7950 << 14 | 837: 8078, + 7951 << 14 | 837: 8079, + 7968 << 14 | 837: 8080, + 7969 << 14 | 837: 8081, + 7970 << 14 | 837: 8082, + 7971 << 14 | 837: 8083, + 7972 << 14 | 837: 8084, + 7973 << 14 | 837: 8085, + 7974 << 14 | 837: 8086, + 7975 << 14 | 837: 8087, + 7976 << 14 | 837: 8088, + 7977 << 14 | 837: 8089, + 7978 << 14 | 837: 8090, + 7979 << 14 | 837: 8091, + 7980 << 14 | 837: 8092, + 7981 << 14 | 837: 8093, + 7982 << 14 | 837: 8094, + 7983 << 14 | 837: 8095, + 8032 << 14 | 837: 8096, + 8033 << 14 | 837: 8097, + 8034 << 14 | 837: 8098, + 8035 << 14 | 837: 8099, + 8036 << 14 | 837: 8100, + 8037 << 14 | 837: 8101, + 8038 << 14 | 837: 8102, + 8039 << 14 | 837: 8103, + 8040 << 14 | 837: 8104, + 8041 << 14 | 837: 8105, + 8042 << 14 | 837: 8106, + 8043 << 14 | 837: 8107, + 8044 << 14 | 837: 8108, + 8045 << 14 | 837: 8109, + 8046 << 14 | 837: 8110, + 8047 << 14 | 837: 8111, + 945 << 14 | 774: 8112, + 945 << 14 | 772: 8113, + 8048 << 14 | 837: 8114, + 945 << 14 | 837: 8115, + 940 << 14 | 837: 8116, + 945 << 14 | 834: 8118, + 8118 << 14 | 837: 8119, + 913 << 14 | 774: 8120, + 913 << 14 | 772: 8121, + 913 << 14 | 768: 8122, + 913 << 14 | 837: 8124, + 168 << 14 | 834: 8129, + 8052 << 14 | 837: 8130, + 951 << 14 | 837: 8131, + 942 << 14 | 837: 8132, + 951 << 14 | 834: 8134, + 8134 << 14 | 837: 8135, + 917 << 14 | 768: 8136, + 919 << 14 | 768: 8138, + 919 << 14 | 837: 8140, + 8127 << 14 | 768: 8141, + 8127 << 14 | 769: 8142, + 8127 << 14 | 834: 8143, + 953 << 14 | 774: 8144, + 953 << 14 | 772: 8145, + 970 << 14 | 768: 8146, + 953 << 14 | 834: 8150, + 970 << 14 | 834: 8151, + 921 << 14 | 774: 8152, + 921 << 14 | 772: 8153, + 921 << 14 | 768: 8154, + 8190 << 14 | 768: 8157, + 8190 << 14 | 769: 8158, + 8190 << 14 | 834: 8159, + 965 << 14 | 774: 8160, + 965 << 14 | 772: 8161, + 971 << 14 | 768: 8162, + 961 << 14 | 787: 8164, + 961 << 14 | 788: 8165, + 965 << 14 | 834: 8166, + 971 << 14 | 834: 8167, + 933 << 14 | 774: 8168, + 933 << 14 | 772: 8169, + 933 << 14 | 768: 8170, + 929 << 14 | 788: 8172, + 168 << 14 | 768: 8173, + 8060 << 14 | 837: 8178, + 969 << 14 | 837: 8179, + 974 << 14 | 837: 8180, + 969 << 14 | 834: 8182, + 8182 << 14 | 837: 8183, + 927 << 14 | 768: 8184, + 937 << 14 | 768: 8186, + 937 << 14 | 837: 8188, + 8592 << 14 | 824: 8602, + 8594 << 14 | 824: 8603, + 8596 << 14 | 824: 8622, + 8656 << 14 | 824: 8653, + 8660 << 14 | 824: 8654, + 8658 << 14 | 824: 8655, + 8707 << 14 | 824: 8708, + 8712 << 14 | 824: 8713, + 8715 << 14 | 824: 8716, + 8739 << 14 | 824: 8740, + 8741 << 14 | 824: 8742, + 8764 << 14 | 824: 8769, + 8771 << 14 | 824: 8772, + 8773 << 14 | 824: 8775, + 8776 << 14 | 824: 8777, + 61 << 14 | 824: 8800, + 8801 << 14 | 824: 8802, + 8781 << 14 | 824: 8813, + 60 << 14 | 824: 8814, + 62 << 14 | 824: 8815, + 8804 << 14 | 824: 8816, + 8805 << 14 | 824: 8817, + 8818 << 14 | 824: 8820, + 8819 << 14 | 824: 8821, + 8822 << 14 | 824: 8824, + 8823 << 14 | 824: 8825, + 8826 << 14 | 824: 8832, + 8827 << 14 | 824: 8833, + 8834 << 14 | 824: 8836, + 8835 << 14 | 824: 8837, + 8838 << 14 | 824: 8840, + 8839 << 14 | 824: 8841, + 8866 << 14 | 824: 8876, + 8872 << 14 | 824: 8877, + 8873 << 14 | 824: 8878, + 8875 << 14 | 824: 8879, + 8828 << 14 | 824: 8928, + 8829 << 14 | 824: 8929, + 8849 << 14 | 824: 8930, + 8850 << 14 | 824: 8931, + 8882 << 14 | 824: 8938, + 8883 << 14 | 824: 8939, + 8884 << 14 | 824: 8940, + 8885 << 14 | 824: 8941, +12363 << 14 | 12441: 12364, +12365 << 14 | 12441: 12366, +12367 << 14 | 12441: 12368, +12369 << 14 | 12441: 12370, +12371 << 14 | 12441: 12372, +12373 << 14 | 12441: 12374, +12375 << 14 | 12441: 12376, +12377 << 14 | 12441: 12378, +12379 << 14 | 12441: 12380, +12381 << 14 | 12441: 12382, +12383 << 14 | 12441: 12384, +12385 << 14 | 12441: 12386, +12388 << 14 | 12441: 12389, +12390 << 14 | 12441: 12391, +12392 << 14 | 12441: 12393, +12399 << 14 | 12441: 12400, +12399 << 14 | 12442: 12401, +12402 << 14 | 12441: 12403, +12402 << 14 | 12442: 12404, +12405 << 14 | 12441: 12406, +12405 << 14 | 12442: 12407, +12408 << 14 | 12441: 12409, +12408 << 14 | 12442: 12410, +12411 << 14 | 12441: 12412, +12411 << 14 | 12442: 12413, +12358 << 14 | 12441: 12436, +12445 << 14 | 12441: 12446, +12459 << 14 | 12441: 12460, +12461 << 14 | 12441: 12462, +12463 << 14 | 12441: 12464, +12465 << 14 | 12441: 12466, +12467 << 14 | 12441: 12468, +12469 << 14 | 12441: 12470, +12471 << 14 | 12441: 12472, +12473 << 14 | 12441: 12474, +12475 << 14 | 12441: 12476, +12477 << 14 | 12441: 12478, +12479 << 14 | 12441: 12480, +12481 << 14 | 12441: 12482, +12484 << 14 | 12441: 12485, +12486 << 14 | 12441: 12487, +12488 << 14 | 12441: 12489, +12495 << 14 | 12441: 12496, +12495 << 14 | 12442: 12497, +12498 << 14 | 12441: 12499, +12498 << 14 | 12442: 12500, +12501 << 14 | 12441: 12502, +12501 << 14 | 12442: 12503, +12504 << 14 | 12441: 12505, +12504 << 14 | 12442: 12506, +12507 << 14 | 12441: 12508, +12507 << 14 | 12442: 12509, +12454 << 14 | 12441: 12532, +12527 << 14 | 12441: 12535, +12528 << 14 | 12441: 12536, +12529 << 14 | 12441: 12537, +12530 << 14 | 12441: 12538, +12541 << 14 | 12441: 12542, } _canon_decomposition = { From hpk at codespeak.net Mon Jul 25 15:21:18 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 15:21:18 +0200 (CEST) Subject: [pypy-svn] r15020 - pypy/dist/pypy/translator/goal Message-ID: <20050725132118.AF4AB27B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 15:21:18 2005 New Revision: 15020 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: a few more notes on how to run the translation Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 25 15:21:18 2005 @@ -197,9 +197,21 @@ How to work in parallel: There is an environment variable to be set with your personal random seed. Seeds taken so far are -Armin: 42, Samuele: 46, Chris: 49, Arre: 97 +Armin: 42, Samuele: 46, Chris: 49, Arre: 97, hpk/rxe: 23 Under Windows, use SET RTYPERSEED=xx where xx is your seed. When you run translate_pypy, you will get a message with your seed, if everything is fine. The purpose of the seed is to shuffle the annotated blocks, in order to create different errors. + +To get the above RTYPER problems, do:: + + RTYPERORDER=order,SOMEFILE + # stopping on the first error + python translate_pypy.py -no-c -no-o -fork -text -t-insist + + # seeing things in the graph + python translate_pypy.py -no-c -no-o + +In the SOMEFILE you put: + pypy.rpython.rarithmetic.ovfcheck_float_to_int From hpk at codespeak.net Mon Jul 25 15:22:07 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 15:22:07 +0200 (CEST) Subject: [pypy-svn] r15021 - pypy/extradoc/sprintinfo Message-ID: <20050725132207.DE37927B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 15:22:07 2005 New Revision: 15021 Added: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: some morning planning for hildesheim2 sprint Added: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Mon Jul 25 15:22:07 2005 @@ -0,0 +1,45 @@ + +PyPy Hildesheim2 sprint planning (25th-31st July) +------------------------------------------------------- + +overall time planning:: + 25th full sprint day + 26th full sprint day + 27th afternoon break + 28th morning break + 29th full sprint day # (compliance test decision) + 30th full sprint day + 31th more or less full sprint day + + each day: + 9-10 AM breakfast + 10:30 planning session + evening: dinner + + Carl Friedrich Bolz + Richard Emslie + Armin Rigo + Holger Krekel whole-time + Christian Tismer whole-time + Samuele Pedroni whole-time + +Misc +-------- + +* -> TRACKER write a tool that discovers which revision of the pypy tree + broke the high level annotator (in that it produced SomeObjects). + Consider distributing the actual annotation to multiple hosts. + +* -> TRACKER: (mostly done) add missing docstrings on app-level built-in types and + functions, etc. (Laura): there now is a program that generates the + docstrings into the appropriate places but it needs prettification. + +Current Main task: RTYPER issues +----------------------------------- + +- we want to work on pypy/translator/goal/ISSUES.txt + +pairs: + Samuele, Carl Friedrich (progressing on External functions) + Armin, Christian (random RTyper problems) + richard, holger (random RTyper problems) From hpk at codespeak.net Mon Jul 25 15:40:24 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 15:40:24 +0200 (CEST) Subject: [pypy-svn] r15023 - pypy/branch/pypy-translation-snapshot/module/__builtin__ Message-ID: <20050725134024.0F69727B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 15:40:23 2005 New Revision: 15023 Modified: pypy/branch/pypy-translation-snapshot/module/__builtin__/importing.py Log: merge 15000:15017 pypy/module/__builtin__ (use os-functions for importing) Modified: pypy/branch/pypy-translation-snapshot/module/__builtin__/importing.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/__builtin__/importing.py (original) +++ pypy/branch/pypy-translation-snapshot/module/__builtin__/importing.py Mon Jul 25 15:40:23 2005 @@ -15,19 +15,19 @@ # XXX posixpath/ntpath/macpath modules. -def try_import_mod(space, w_modulename, f, w_parent, w_name, pkgdir=None): +def try_import_mod(space, w_modulename, fn, w_parent, w_name, pkgdir=None): w = space.wrap - if os.path.exists(f): + if os.path.exists(fn): w_mod = space.wrap(Module(space, w_modulename)) space.sys.setmodule(w_mod) - space.setattr(w_mod, w('__file__'), w(f)) + space.setattr(w_mod, w('__file__'), w(fn)) space.setattr(w_mod, w('__doc__'), space.w_None) if pkgdir is not None: space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) w_dict = space.getattr(w_mod, w('__dict__')) e = None try: - space.builtin.call('execfile', w(f), w_dict, w_dict) + imp_execfile(space, fn, w_dict, w_dict) except OperationError, e: if e.match(space, space.w_SyntaxError): w_mods = space.sys.get('modules') @@ -180,13 +180,13 @@ for path in space.unpackiterable(w_path): dir = os.path.join(space.str_w(path), partname) if os.path.isdir(dir): - f = os.path.join(dir,'__init__.py') - w_mod = try_import_mod(space, w_modulename, f, w_parent, + fn = os.path.join(dir,'__init__.py') + w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname), pkgdir=dir) if w_mod is not None: return w_mod - f = os.path.join(space.str_w(path), partname + '.py') - w_mod = try_import_mod(space, w_modulename, f, w_parent, + fn = os.path.join(space.str_w(path), partname + '.py') + w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname)) if w_mod is not None: return w_mod @@ -198,3 +198,22 @@ w_failing = w_modulename w_exc = space.call_function(space.w_ImportError, w_failing) raise OperationError(space.w_ImportError, w_exc) + + +def imp_execfile(space, fn, w_globals, w_locals): + fd = os.open(fn, os.O_RDONLY) # XXX newlines? + try: + size = os.fstat(fd)[6] + source = os.read(fd, size) + finally: + os.close(fd) + w_source = space.wrap(source) + w_mode = space.wrap("exec") + w_fn = space.wrap(fn) + w_code = space.builtin.call('compile', w_source, w_fn, w_mode) + pycode = space.interpclass_w(w_code) + space.call_method(w_globals, 'setdefault', + space.wrap('__builtins__'), + space.wrap(space.builtin)) + pycode.exec_code(space, w_globals, w_locals) + From arigo at codespeak.net Mon Jul 25 15:46:00 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 15:46:00 +0200 (CEST) Subject: [pypy-svn] r15025 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050725134600.21D3527B53@code1.codespeak.net> Author: arigo Date: Mon Jul 25 15:45:56 2005 New Revision: 15025 Modified: pypy/dist/pypy/objspace/std/intobject.py pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: Removed the special case "-1" for hash(int). Changed the interface of _FromDouble() to raise an interp-level OverflowError. Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Mon Jul 25 15:45:56 2005 @@ -99,31 +99,11 @@ j = w_int2.intval return space.newbool( i >= j ) -STRICT_HASH = True # temporary, to be put elsewhere or removed - -def _hash_strict(space, w_int1): - #/* XXX If this is changed, you also need to change the way - # Python's long, float and complex types are hashed. */ - x = w_int1.intval - if x == -1: - x = -2 - return W_IntObject(space, x) - -def _hash_liberal(space, w_int1): - # Armin: unlike CPython we have no need to special-case the value -1 - return w_int1 - -# Chris: I'm not yet convinced that we want to make hash() -# return different values that CPython does. -# So for the moment, both versions are here, -# and we might think of some config options -# or decide to drop compatibility (using pypy-dev). - def hash__Int(space, w_int1): - if STRICT_HASH: - return _hash_strict(space, w_int1) - else: - return _hash_liberal(space, w_int1) + # unlike CPython, we don't special-case the value -1 in most of our + # hash functions, so there is not much sense special-casing it here either. + # Make sure this is consistent with the hash of floats and longs. + return int__Int(space, w_int1) # coerce def coerce__Int_Int(space, w_int1, w_int2): Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Mon Jul 25 15:45:56 2005 @@ -204,7 +204,11 @@ space.wrap("long int too large to convert to float")) def long__Float(space, w_floatobj): - return _FromDouble(space, w_floatobj.floatval) + try: + return _FromDouble(space, w_floatobj.floatval) + except OverflowError: + raise OperationError(space.w_OverflowError, + space.wrap("cannot convert float infinity to long")) def int_w__Long(space, w_value): try: @@ -1303,8 +1307,7 @@ """ Create a new long int object from a C double """ neg = 0 if isinf(dval): - raise OperationError(space.w_OverflowError, - space.wrap("cannot convert float infinity to long")) + raise OverflowError if dval < 0.0: neg = 1 dval = -dval @@ -1604,6 +1607,4 @@ x += v.digits[i] i -= 1 x = intmask(x * sign) - if x == -1: - x = -2 return x 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 Mon Jul 25 15:45:56 2005 @@ -123,10 +123,7 @@ assert f1.longval() == long(x) # check overflow x = 12345.6789e10000000000000000000000000000 - try: - lobj._FromDouble(self.space, x) - except OperationError, e: - assert e.w_type is self.space.w_OverflowError + assert raises(OverflowError, lobj._FromDouble, self.space, x) # testing Karatsuba stuff def test__v_iadd(self): From tismer at codespeak.net Mon Jul 25 16:02:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 16:02:56 +0200 (CEST) Subject: [pypy-svn] r15027 - in pypy/dist/pypy: objspace/std objspace/std/test rpython Message-ID: <20050725140256.6A57E27B53@code1.codespeak.net> Author: tismer Date: Mon Jul 25 16:02:21 2005 New Revision: 15027 Modified: pypy/dist/pypy/objspace/std/floatobject.py pypy/dist/pypy/objspace/std/test/test_floatobject.py pypy/dist/pypy/rpython/rarithmetic.py Log: hashing for floats implemented as CPython does. added missing comment about ovfcheck_float_to_int Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Mon Jul 25 16:02:21 2005 @@ -1,6 +1,7 @@ from pypy.objspace.std.objspace import * from pypy.interpreter import gateway from pypy.objspace.std.noneobject import W_NoneObject +from pypy.rpython.rarithmetic import ovfcheck_float_to_int ############################################################## # for the time being, all calls that are made to some external @@ -106,10 +107,54 @@ j = w_float2.floatval return space.newbool( i >= j ) -def hash__Float(space,w_value): - ## %reimplement% - # real Implementation should be taken from _Py_HashDouble in object.c - return space.wrap(hash(w_value.floatval)) +def hash__Float(space, w_value): + return space.wrap(_hash_float(space, w_value.floatval)) + +def _hash_float(space, v): + from pypy.objspace.std.longobject import _FromDouble, _hash as _hashlong + + # This is designed so that Python numbers of different types + # that compare equal hash to the same value; otherwise comparisons + # of mapping keys will turn out weird. + fractpart, intpart = math.modf(v) + + if fractpart == 0.0: + # This must return the same hash as an equal int or long. + try: + x = ovfcheck_float_to_int(intpart) + # Fits in a C long == a Python int, so is its own hash. + return x + except OverflowError: + # Convert to long and use its hash. + try: + w_lval = _FromDouble(space, v) + except OverflowError: + # can't convert to long int -- arbitrary + if v < 0: + return -271828 + else: + return 314159 + return _hashlong(w_lval) + + # The fractional part is non-zero, so we don't have to worry about + # making this match the hash of some other type. + # Use frexp to get at the bits in the double. + # Since the VAX D double format has 56 mantissa bits, which is the + # most of any double format in use, each of these parts may have as + # many as (but no more than) 56 significant bits. + # So, assuming sizeof(long) >= 4, each part can be broken into two + # longs; frexp and multiplication are used to do that. + # Also, since the Cray double format has 15 exponent bits, which is + # the most of any double format in use, shifting the exponent field + # left by 15 won't overflow a long (again assuming sizeof(long) >= 4). + + v, expo = math.frexp(v) + v *= 2147483648.0 # 2**31 + hipart = int(v) # take the top 32 bits + v = (v - hipart) * 2147483648.0 # get the next 32 bits + x = hipart + int(v) + (expo << 15) + return x + # coerce def coerce__Float_Float(space, w_float1, w_float2): 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 Mon Jul 25 16:02:21 2005 @@ -50,6 +50,13 @@ def test_float_int(self): assert 42.0 == float(42) + def test_float_hash(self): + # these are taken from standard Python, which produces + # the same but for -1. + assert hash(42.0) == 42 + assert hash(42.1) == 1842335027 + assert hash(42.2E100) == 503430341 + def test_int_float(self): assert int(42.1234) == 42 assert int(4e10) == 40000000000L Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Mon Jul 25 16:02:21 2005 @@ -15,6 +15,8 @@ ovfcheck_lshift << with oveflow checking 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 From arigo at codespeak.net Mon Jul 25 16:03:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 16:03:03 +0200 (CEST) Subject: [pypy-svn] r15028 - pypy/dist/pypy/objspace/std/test Message-ID: <20050725140303.0A89E27B55@code1.codespeak.net> Author: arigo Date: Mon Jul 25 16:02:46 2005 New Revision: 15028 Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py Log: Tests for hash(long). 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 Mon Jul 25 16:02:46 2005 @@ -384,3 +384,12 @@ assert 0xAAAAAAAAL | 0x555555555L == 0x5FFFFFFFFL assert 0xAAAAAAAAL & 0x555555555L == 0x000000000L assert 0xAAAAAAAAL ^ 0x555555555L == 0x5FFFFFFFFL + + def test_hash(self): + # ints have the same hash as equal longs + for i in range(-4, 14): + assert hash(i) == hash(long(i)) + # might check too much -- it's ok to change the hashing algorithm + assert hash(123456789L) == 123456789 + assert hash(1234567890123456789L) == -1895067127 + assert hash(-3**333) == -368329968 From arigo at codespeak.net Mon Jul 25 16:14:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 16:14:22 +0200 (CEST) Subject: [pypy-svn] r15031 - pypy/dist/pypy/translator/goal Message-ID: <20050725141422.147A027B53@code1.codespeak.net> Author: arigo Date: Mon Jul 25 16:14:20 2005 New Revision: 15031 Modified: pypy/dist/pypy/translator/goal/ISSUES.txt Log: Remaining TyperErrors for rev 15019. Modified: pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- pypy/dist/pypy/translator/goal/ISSUES.txt (original) +++ pypy/dist/pypy/translator/goal/ISSUES.txt Mon Jul 25 16:14:20 2005 @@ -13,185 +13,138 @@ TyperError-1: (pypy.objspace.std.listobject:unwrap) no list() support for .. block at 73 with 1 exits - .. v591333 = simple_call((type list), v591328) + .. v627007 = simple_call((type list), v627002) - TyperError-2: (pypy.module.__builtin__.importing:load_part) - don't know about built-in function - .. block at 201 with 2 exits(v766387) - .. v766356 = simple_call((function isdir), v766319) - - TyperError-3: (pypy.module.__builtin__.importing:try_import_mod) + TyperError-2: (pypy.module.__builtin__.importing:try_import_mod) don't know about built-in function - .. block at -1 with 2 exits(v901991) - .. v901975 = simple_call((function exists), f_901945) + .. block at -1 with 2 exits(v908659) + .. v908643 = simple_call((function exists), f_908613) + + TyperError-3: (pypy.module.__builtin__.importing:load_part) + don't know about built-in function + .. block at 201 with 2 exits(v853316) + .. v853285 = simple_call((function isdir), v853248) TyperError-4: (pypy.module.sys.vm:getrefcount) don't know about built-in function .. block at -1 with 1 exits - .. v210471 = simple_call((builtin_function_or_method getrefcount), w_obj_210452) - - TyperError-5: (pypy.module.unicodedata.function:normalize) - cannot make repr of - .. block at 1498 with 2 exits(last_exception) - .. v341362 = getitem(({(104, 770): 293, (6...8): 366}), v341265) - - TyperError-6: (pypy.module.unicodedata.unicodedb:name) - unimplemented operation: 'divmod' on (, ) - .. block at 170 EH with 1 exits - .. v791070 = divmod(v791063, (21)) - - TyperError-7: (pypy.module.unicodedata.unicodedb:name) - unimplemented operation: 'divmod' on (, ) - .. block at 157 with 1 exits - .. v791029 = divmod(v791003, (28)) + .. v324725 = simple_call((builtin_function_or_method getrefcount), w_obj_324706) - TyperError-8: (pypy.objspace.std.fake:fake__new__) + TyperError-5: (pypy.objspace.std.fake:fake__new__) don't know about built-in function .. block at 145 with 1 exits - .. v531481 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v531453, v53 - 1454) + .. v439600 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v439572, v43 + 9573) - TyperError-9: (pypy.objspace.std.fake:fake__new__) + TyperError-6: (pypy.objspace.std.fake:fake__new__) don't know about built-in function .. block at 145 with 1 exits - .. v356204 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v356176, v35 - 6177) + .. v338257 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v338229, v33 + 8230) - TyperError-10: (pypy.objspace.std.fake:run) - don't know about built-in function - .. block at 62 with 1 exits - .. v358126 = simple_call((builtin_function_or_method apply), v358108, v358109, v358110) - - TyperError-11: (pypy.objspace.std.fake:setfastscope) + TyperError-7: (pypy.objspace.std.fake:setfastscope) ll_str unsupported for: .. block at 118 with 1 exits - .. v357756 = mod(('calling %s: %s'), v357745) + .. v181912 = mod(('calling %s: %s'), v181901) + + TyperError-8: (pypy.objspace.std.fake:run) + don't know about built-in function + .. block at 62 with 1 exits + .. v185355 = simple_call((builtin_function_or_method apply), v185337, v185338, v185339) - TyperError-12: (pypy.objspace.std.floatobject:hash__Float) + TyperError-9: (pypy.objspace.std.floatobject:hash__Float) unimplemented operation: 'hash' on .. block at -1 with 1 exits - .. v463799 = hash(v463788) + .. v374573 = hash(v374562) - TyperError-13: (pypy.objspace.std.longobject:_FromDouble) - don't know about built-in function - .. block at 245 with 1 exits - .. v427244 = simple_call((builtin_function_or_method ldexp), v427222, (15)) - - TyperError-14: (pypy.objspace.std.longobject:_AsDouble) - don't know about built-in function - .. block at 53 with 1 exits - .. v672412 = simple_call((builtin_function_or_method ldexp), v672396, v672400) - - TyperError-15: (pypy.objspace.std.longobject:longval) + TyperError-10: (pypy.objspace.std.longobject:longval) don't know about built-in function .. block at 50 with 1 exits - .. v604056 = simple_call((type long), d_604019) + .. v630648 = simple_call((type long), d_630611) - TyperError-16: (pypy.objspace.std.longobject:_FromDouble) - don't know about built-in function - .. block at 89 with 1 exits - .. v426806 = simple_call((builtin_function_or_method frexp), v426795) - - TyperError-17: (pypy.objspace.std.longobject:_long_true_divide) - don't know about built-in function - .. block at 183 with 1 exits - .. v539689 = simple_call((builtin_function_or_method ldexp), v539625, v539649) - - TyperError-18: (pypy.objspace.std.longobject:_FromDouble) - don't know about built-in function - .. block at 143 with 1 exits - .. v427059 = simple_call((builtin_function_or_method ldexp), frac_426871, v427043) + TyperError-11: (pypy.objspace.std.objspace:unwrap) + don't know how to convert from to + .. block at -1 EH with 2 exits(v471216) + .. link from block at -1 EH to codeless block - TyperError-19: (pypy.objspace.std.objspace:unwrap) - unimplemented operation: 'mod' on (, - ) - .. block at 63 with 1 exits - .. v507742 = mod(('cannot unwrap: %r'), v507736) + TyperError-12: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v768205) + .. link from block at -1 to block at 945 - TyperError-20: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v675927) + TyperError-13: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v767254) .. link from block at -1 to block at -1 - TyperError-21: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v675023) + TyperError-14: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v767231) .. link from block at -1 to block at -1 - TyperError-22: (pypy.objspace.std.objspace:wrap__object) + TyperError-15: (pypy.objspace.std.objspace:wrap__object) call_specialcase: unknown tag override:wrap_exception_cls - .. block at 886 with 2 exits(v676097) - .. v676057 = call_specialcase(v676020, x_675999) + .. block at 886 with 2 exits(v768328) + .. v768288 = call_specialcase(v768251, x_768230) - TyperError-23: (pypy.objspace.std.objspace:wrap__object) + TyperError-16: (pypy.objspace.std.objspace:wrap__object) no unichr() support for .. block at 265 with 1 exits - .. v675385 = simple_call((builtin_function_or_method unichr), v675355) - - TyperError-24: (pypy.objspace.std.objspace:unwrap) - don't know how to convert from to - .. block at -1 EH with 2 exits(v507719) - .. link from block at -1 EH to codeless block + .. v767616 = simple_call((builtin_function_or_method unichr), v767586) - TyperError-25: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v675000) - .. link from block at -1 to block at -1 + TyperError-17: (pypy.objspace.std.objspace:unwrap) + unimplemented operation: 'mod' on (, + ) + .. block at 63 with 1 exits + .. v471239 = mod(('cannot unwrap: %r'), v471233) - TyperError-26: (pypy.objspace.std.objspace:wrap__object) + TyperError-18: (pypy.objspace.std.objspace:wrap__object) don't know how to convert from to - .. block at -1 with 2 exits(v675487) + .. block at -1 with 2 exits(v767718) .. link from block at -1 to block at -1 - TyperError-27: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v675974) - .. link from block at -1 to block at 945 + TyperError-19: (pypy.objspace.std.objspace:wrap__object) + don't know how to convert from to + .. block at -1 with 2 exits(v768158) + .. link from block at -1 to block at -1 - TyperError-28: (pypy.objspace.std.objspace:wrap__object) + TyperError-20: (pypy.objspace.std.objspace:wrap__object) call_specialcase: unknown tag override:fake_object .. block at 945 with 1 exits - .. v676015 = call_specialcase((function fake_object), v675994, v675995) + .. v768246 = call_specialcase((function fake_object), v768225, v768226) - TyperError-29: (pypy.objspace.std.objspace:wrap__object) + TyperError-21: (pypy.objspace.std.objspace:wrap__object) no list() support for .. block at 446 with 1 exits - .. v675476 = simple_call((type list), x_675379) + .. v767707 = simple_call((type list), x_767610) - TyperError-30: (pypy.objspace.std.sliceobject:unwrap) + TyperError-22: (pypy.objspace.std.sliceobject:unwrap) don't know about built-in function .. block at -1 with 1 exits - .. v591645 = simple_call((type slice), v591557, v591593, v591632) + .. v626191 = simple_call((type slice), v626103, v626139, v626178) - TyperError-31: (pypy.objspace.std.tupleobject:unwrap) + TyperError-23: (pypy.objspace.std.tupleobject:unwrap) don't know about built-in function .. block at 66 with 1 exits - .. v590595 = simple_call((type tuple), v590590) + .. v626786 = simple_call((type tuple), v626781) - TyperError-32: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) - cannot make repr of - .. block at 185 with 2 exits(v596694) - .. v596669 = contains(((u'+', u'-')), v596629) - - TyperError-33: (pypy.objspace.std.unicodeobject:unwrap) + TyperError-24: (pypy.objspace.std.unicodeobject:unwrap) don't know how to convert from to .. block at -1 with 1 exits - .. v591049 = simple_call((builtin_function_or_method join), v591040) + .. v626273 = simple_call((builtin_function_or_method join), v626264) - TyperError-34: (pypy.rpython.rarithmetic:ovfcheck_float_to_int) - don't know about built-in function - .. block at -1 with 1 exits - .. v910653 = simple_call((builtin_function_or_method modf), x_910646) + TyperError-25: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) + cannot make repr of + .. block at 185 with 2 exits(v366540) + .. v366515 = contains(((u'+', u'-')), v366475) - TyperError-35: (pypy.interpreter.pycompiler:compile) + TyperError-26: (pypy.interpreter.pycompiler:compile) call_specialcase: unknown tag override:cpy_stablecompiler .. block at 156 with 1 exits - .. v783803 = call_specialcase(v783766, parse_result_783749, filename_783745, mode_783746) - + .. v775851 = call_specialcase(v775814, parse_result_775797, filename_775793, mode_775794) How to work in parallel: From tismer at codespeak.net Mon Jul 25 16:14:45 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 16:14:45 +0200 (CEST) Subject: [pypy-svn] r15032 - pypy/dist/pypy/objspace/std/test Message-ID: <20050725141445.6022827B54@code1.codespeak.net> Author: tismer Date: Mon Jul 25 16:14:32 2005 New Revision: 15032 Modified: pypy/dist/pypy/objspace/std/test/test_floatobject.py Log: added more corner case testing to float hash() 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 Mon Jul 25 16:14:32 2005 @@ -53,9 +53,13 @@ def test_float_hash(self): # these are taken from standard Python, which produces # the same but for -1. + import math assert hash(42.0) == 42 - assert hash(42.1) == 1842335027 - assert hash(42.2E100) == 503430341 + assert hash(42.125) == 1413677056 + assert hash(math.ldexp(0.125, 1000)) == 32 + # testing special overflow values + assert hash(1e200 * 1e200) == 314159 + assert hash(-1e200 * 1e200) == -271828 def test_int_float(self): assert int(42.1234) == 42 From hpk at codespeak.net Mon Jul 25 16:53:28 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 16:53:28 +0200 (CEST) Subject: [pypy-svn] r15036 - pypy/dist/pypy/lib/test2 Message-ID: <20050725145328.9F53127B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 16:53:27 2005 New Revision: 15036 Modified: pypy/dist/pypy/lib/test2/test_file_extra.py Log: rename confusing name usage of 'fd' to 'file' Modified: pypy/dist/pypy/lib/test2/test_file_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_file_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_file_extra.py Mon Jul 25 16:53:27 2005 @@ -5,13 +5,13 @@ class TestFile: def setup_method(self, method): - self.fd = _file.file(__file__, 'r') + self.file = _file.file(__file__, 'r') def teardown_method(self, method): - self.fd.close() + self.file.close() def test_case_1(self): - assert self.fd.tell() == 0 + assert self.file.tell() == 0 def test_case_readonly(self): fn = str(udir.join('temptestfile')) @@ -23,15 +23,15 @@ py.test.raises((TypeError, AttributeError), setattr, f, 'name', 42) def test_plain_read(self): - data1 = self.fd.read() + data1 = self.file.read() data2 = open(__file__, 'r').read() assert data1 == data2 def test_readline(self): cpyfile = open(__file__, 'r') - assert self.fd.readline() == cpyfile.readline() + assert self.file.readline() == cpyfile.readline() for i in range(-1, 10): - assert self.fd.readline(i) == cpyfile.readline(i) + assert self.file.readline(i) == cpyfile.readline(i) def test_readlines(self): fn = str(udir.join('temptestfile')) From arigo at codespeak.net Mon Jul 25 17:00:04 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 17:00:04 +0200 (CEST) Subject: [pypy-svn] r15037 - in pypy/dist/pypy/rpython: . test Message-ID: <20050725150004.9A76427B53@code1.codespeak.net> Author: arigo Date: Mon Jul 25 17:00:01 2005 New Revision: 15037 Modified: pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rconstantdict.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: * Constant dicts with unicode chars as keys * Fixed a bug in constant dicts (dicts of len 2 didn't get any unused entry) Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Mon Jul 25 17:00:01 2005 @@ -54,7 +54,7 @@ except KeyError: self.setup() dictlen = len(dictobj) - minentrylen = dictlen * 4 / 3 + minentrylen = (dictlen * 4 + 2) / 3 entrylen = 1 while entrylen < minentrylen: entrylen *= 2 @@ -62,20 +62,21 @@ self.dict_cache[key] = result r_key = self.key_repr r_value = self.value_repr - #hashcompute = self.get_key_hash_function() + hashcompute = self.get_key_hash_function() for dictkey, dictvalue in dictobj.items(): llkey = r_key.convert_const(dictkey) llvalue = r_value.convert_const(dictvalue) - ll_constantdict_setnewitem(result, llkey, llvalue)#,hashcompute) + ll_constantdict_setnewitem(result, llkey, llvalue, hashcompute) + assert result.num_items < len(result.entries) return result -## def get_key_hash_function(self): -## if isinstance(self.key_repr, rmodel.IntegerRepr): -## return ll_hash_identity -## elif isinstance(self.key_repr, rmodel.CharRepr): -## return ll_hash_char -## else: -## raise TyperError("no easy hash function for %r" % (self.key_repr,)) + def get_key_hash_function(self): + if isinstance(self.key_repr, rmodel.IntegerRepr): + return ll_hash_identity + elif isinstance(self.key_repr, rmodel.UniCharRepr): + return ll_hash_unichar + else: + raise TyperError("no easy hash function for %r" % (self.key_repr,)) def rtype_len(self, hop): v_dict, = hop.inputargs(self) @@ -87,23 +88,26 @@ def rtype_method_get(self, hop): v_dict, v_key, v_default = hop.inputargs(self, self.key_repr, self.value_repr) - return hop.gendirectcall(ll_constantdict_get, v_dict, v_key, v_default) + hashcompute = self.get_key_hash_function() + chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_get, v_dict, v_key, v_default, + chashcompute) class __extend__(pairtype(ConstantDictRepr, rmodel.Repr)): def rtype_getitem((r_dict, r_key), hop): v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) - #hashcompute = r_dict.get_key_hash_function() - #chashcompute = hop.inputconst(lltype.Void, hashcompute) - return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key) - #chashcompute) + hashcompute = r_dict.get_key_hash_function() + chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key, + chashcompute) def rtype_contains((r_dict, r_key), hop): v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) - #hashcompute = r_dict.get_key_hash_function() - #chashcompute = hop.inputconst(lltype.Void, hashcompute) - return hop.gendirectcall(ll_constantdict_contains, v_dict, v_key) - #chashcompute) + hashcompute = r_dict.get_key_hash_function() + chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_contains, v_dict, v_key, + chashcompute) # ____________________________________________________________ # @@ -114,26 +118,26 @@ def ll_constantdict_len(d): return d.num_items -def ll_constantdict_getitem(d, key):#, hashcompute): - entry = ll_constantdict_lookup(d, key)#, hashcompute) +def ll_constantdict_getitem(d, key, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) if entry.valid: return entry.value else: raise KeyError -def ll_constantdict_contains(d, key):#, hashcompute): - entry = ll_constantdict_lookup(d, key)#, hashcompute) +def ll_constantdict_contains(d, key, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) return entry.valid -def ll_constantdict_get(d, key, default):#, hashcompute): - entry = ll_constantdict_lookup(d, key)#, hashcompute) +def ll_constantdict_get(d, key, default, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) if entry.valid: return entry.value else: return default -def ll_constantdict_setnewitem(d, key, value):#, hashcompute): - entry = ll_constantdict_lookup(d, key)#, hashcompute) +def ll_constantdict_setnewitem(d, key, value, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) assert not entry.valid entry.key = key entry.valid = True @@ -143,12 +147,12 @@ # the below is a port of CPython's dictobject.c's lookdict implementation PERTURB_SHIFT = 5 -def ll_constantdict_lookup(d, key):#, hashcompute): - hash = key #hashcompute(key) +def ll_constantdict_lookup(d, key, hashcompute): + hash = r_uint(hashcompute(key)) entries = d.entries mask = len(entries) - 1 - perturb = r_uint(hash) - i = r_uint(hash) + perturb = hash + i = hash while 1: entry = entries[i & mask] if not entry.valid: @@ -158,8 +162,8 @@ perturb >>= PERTURB_SHIFT i = (i << 2) + i + perturb + 1 -##def ll_hash_identity(x): -## return x +def ll_hash_identity(x): + return x -##def ll_hash_char(x): -## return ord(x) +def ll_hash_unichar(x): + return ord(x) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Mon Jul 25 17:00:01 2005 @@ -35,7 +35,8 @@ dictvalue = self.dictdef.dictvalue return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), dictvalue) - elif isinstance(s_key, annmodel.SomeInteger): + elif isinstance(s_key, (annmodel.SomeInteger, + annmodel.SomeUnicodeCodePoint)): dictkey = self.dictdef.dictkey dictvalue = self.dictdef.dictvalue return rconstantdict.ConstantDictRepr( Modified: pypy/dist/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rconstantdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rconstantdict.py Mon Jul 25 17:00:01 2005 @@ -25,3 +25,14 @@ assert res == 62 res = interpret(func, [4, 25]) assert res == -44 + +def test_unichar_dict(): + d = {u'a': 5, u'b': 123, u'?': 321} + def func(i): + return d[unichr(i)] + res = interpret(func, [97]) + assert res == 5 + res = interpret(func, [98]) + assert res == 123 + res = interpret(func, [63]) + assert res == 321 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 Jul 25 17:00:01 2005 @@ -78,6 +78,14 @@ res = interpret(f, [0]) assert res is False +def test_constant_unichar_tuple_contains(): + def f(i): + return unichr(i) in (u'1', u'9') + res = interpret(f, [49]) + assert res is True + res = interpret(f, [50]) + assert res is False + def test_tuple_iterator_length1(): def f(i): total = 0 From hpk at codespeak.net Mon Jul 25 17:18:40 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 17:18:40 +0200 (CEST) Subject: [pypy-svn] r15039 - pypy/dist/pypy/lib/test2 Message-ID: <20050725151840.6586427B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 17:18:39 2005 New Revision: 15039 Modified: pypy/dist/pypy/lib/test2/test_file_extra.py Log: intermediate checkin: some tests for file.fdopen (failing) Modified: pypy/dist/pypy/lib/test2/test_file_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_file_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_file_extra.py Mon Jul 25 17:18:39 2005 @@ -111,3 +111,10 @@ f = _file.file(fn, 'rU') assert f.read() == 'hello\nworld\n' f.close() + +class TestFdFile(TestFile): + def setup_method(self, method): + self.file = _file.file.fdopen(__file__, 'r') + + def teardown_method(self, method): + self.file.close() From hpk at codespeak.net Mon Jul 25 17:21:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 17:21:58 +0200 (CEST) Subject: [pypy-svn] r15040 - pypy/dist/pypy/lib/test2 Message-ID: <20050725152158.094D027B53@code1.codespeak.net> Author: hpk Date: Mon Jul 25 17:21:57 2005 New Revision: 15040 Modified: pypy/dist/pypy/lib/test2/test_file_extra.py Log: some refactoring regarding the extra file tests Modified: pypy/dist/pypy/lib/test2/test_file_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_file_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_file_extra.py Mon Jul 25 17:21:57 2005 @@ -13,15 +13,6 @@ def test_case_1(self): assert self.file.tell() == 0 - def test_case_readonly(self): - fn = str(udir.join('temptestfile')) - f=_file.file(fn, 'w') - assert f.name == fn - assert f.mode == 'w' - assert f.closed == False - assert f.encoding == None # Fix when we find out what this is - py.test.raises((TypeError, AttributeError), setattr, f, 'name', 42) - def test_plain_read(self): data1 = self.file.read() data2 = open(__file__, 'r').read() @@ -33,88 +24,101 @@ for i in range(-1, 10): assert self.file.readline(i) == cpyfile.readline(i) - def test_readlines(self): - fn = str(udir.join('temptestfile')) - lines = ['line%d\n' % i for i in range(1000)] - f=_file.file(fn, 'w') - f.writelines(lines) - f.close() - assert open(fn, 'r').readlines() == lines - assert _file.file(fn, 'r').readlines() == lines - somelines = _file.file(fn, 'r').readlines(2000) - assert len(somelines) > 200 - assert somelines == lines[:len(somelines)] - - def stresstest(self, flags, checkflags, eolstyles): - fn = str(udir.join('temptestfile')) - f = _file.file(fn, flags) - expected = '' - pos = 0 - for i in range(5000): - x = random.random() - if x < 0.4: - l = int(x*100) - buf = f.read(l) - assert buf == expected[pos:pos+l] - pos += len(buf) - elif x < 0.75: - writeeol, expecteol = random.choice(eolstyles) - x = str(x) - buf1 = x+writeeol - buf2 = x+expecteol - f.write(buf1) - expected = expected[:pos] + buf2 + expected[pos+len(buf2):] - pos += len(buf2) - elif x < 0.80: - pos = random.randint(0, len(expected)) - f.seek(pos) - elif x < 0.85: - pos = random.randint(0, len(expected)) - f.seek(pos - len(expected), 2) - elif x < 0.90: - currentpos = pos - pos = random.randint(0, len(expected)) - f.seek(pos - currentpos, 1) - elif x < 0.95: - assert f.tell() == pos - else: - f.flush() - g = open(fn, checkflags) - buf = g.read() - g.close() - assert buf == expected - f.close() - g = open(fn, checkflags) - buf = g.read() - g.close() - assert buf == expected - - def test_rw_bin(self): - self.stresstest('w+b', 'rb', [('', ''), ('\n', '\n'), - ('\r', '\r'), ('\r\n', '\r\n')]) - - def test_rw(self): - # XXX tests in progress - fn = str(udir.join('temptestfile')) - f = _file.file(fn, 'w+') - f.write('hello\nworld\n') - f.seek(0) - assert f.read() == 'hello\nworld\n' - f.close() - - def test_r_universal(self): - # XXX tests in progress - fn = str(udir.join('temptestfile')) - f = open(fn, 'wb') - f.write('hello\r\nworld\r\n') - f.close() - f = _file.file(fn, 'rU') - assert f.read() == 'hello\nworld\n' - f.close() - class TestFdFile(TestFile): def setup_method(self, method): - self.file = _file.file.fdopen(__file__, 'r') + import os + fd = os.open(__file__, os.O_RDONLY) + self.file = _file.file.fdopen(fd, 'r') def teardown_method(self, method): self.file.close() + + +def test_case_readonly(): + fn = str(udir.join('temptestfile')) + f = _file.file(fn, 'w') + assert f.name == fn + assert f.mode == 'w' + assert f.closed == False + assert f.encoding == None # Fix when we find out what this is + py.test.raises((TypeError, AttributeError), setattr, f, 'name', 42) + +def test_readlines(): + fn = str(udir.join('temptestfile')) + lines = ['line%d\n' % i for i in range(1000)] + f=_file.file(fn, 'w') + f.writelines(lines) + f.close() + assert open(fn, 'r').readlines() == lines + assert _file.file(fn, 'r').readlines() == lines + somelines = _file.file(fn, 'r').readlines(2000) + assert len(somelines) > 200 + assert somelines == lines[:len(somelines)] + +def stresstest(flags, checkflags, eolstyles): + fn = str(udir.join('temptestfile')) + f = _file.file(fn, flags) + expected = '' + pos = 0 + for i in range(5000): + x = random.random() + if x < 0.4: + l = int(x*100) + buf = f.read(l) + assert buf == expected[pos:pos+l] + pos += len(buf) + elif x < 0.75: + writeeol, expecteol = random.choice(eolstyles) + x = str(x) + buf1 = x+writeeol + buf2 = x+expecteol + f.write(buf1) + expected = expected[:pos] + buf2 + expected[pos+len(buf2):] + pos += len(buf2) + elif x < 0.80: + pos = random.randint(0, len(expected)) + f.seek(pos) + elif x < 0.85: + pos = random.randint(0, len(expected)) + f.seek(pos - len(expected), 2) + elif x < 0.90: + currentpos = pos + pos = random.randint(0, len(expected)) + f.seek(pos - currentpos, 1) + elif x < 0.95: + assert f.tell() == pos + else: + f.flush() + g = open(fn, checkflags) + buf = g.read() + g.close() + assert buf == expected + f.close() + g = open(fn, checkflags) + buf = g.read() + g.close() + assert buf == expected + +def test_rw_bin(): + stresstest('w+b', 'rb', [('', ''), ('\n', '\n'), + ('\r', '\r'), ('\r\n', '\r\n')]) + +def test_rw(): + # XXX tests in progress + fn = str(udir.join('temptestfile')) + f = _file.file(fn, 'w+') + f.write('hello\nworld\n') + f.seek(0) + assert f.read() == 'hello\nworld\n' + f.close() + +def test_r_universal(): + # XXX tests in progress + fn = str(udir.join('temptestfile')) + f = open(fn, 'wb') + f.write('hello\r\nworld\r\n') + f.close() + f = _file.file(fn, 'rU') + assert f.read() == 'hello\nworld\n' + f.close() + From adim at codespeak.net Mon Jul 25 17:22:47 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 17:22:47 +0200 (CEST) Subject: [pypy-svn] r15041 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050725152247.39A0727B53@code1.codespeak.net> Author: adim Date: Mon Jul 25 17:22:43 2005 New Revision: 15041 Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: implemented genexpr discovered, while reading the grammar, that Python supported strange listcomps (or genexprs) constructs, like in: l = [i for j in k if j%2==0 if j*2<20 for i in j if i%2==0] Added new tests for this, and made genexpr code and listcomp code behave the same way. Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 17:22:43 2005 @@ -332,8 +332,12 @@ for i in range(0, l, 2): # this is L not 1 items.append(L[i]) else: - # genfor - assert False, "TODO" + # genfor: 'i for i in j' + # GenExpr(GenExprInner(Name('i'), [GenExprFor(AssName('i', 'OP_ASSIGN'), Name('j'), [])])))])) + expr = L[0] + genexpr_for = parse_genexpr_for(L[1:]) + builder.push(ast.GenExpr(ast.GenExprInner(expr, genexpr_for))) + return builder.push(ast.Tuple(items)) return @@ -366,48 +370,14 @@ builder.push(ArglistObject('arglist', parse_argument(L), None)) -def build_list_for(builder, nb): - """ - list_iter: list_for | list_if - list_for: 'for' exprlist 'in' testlist_safe [list_iter] - list_if: 'if' test [list_iter] - /!\ list_for is (possibly) recursive - """ - L = get_atoms(builder, nb) - built_listfors = [] - ifs = [] - assign_token = L[1] - ass_node = to_lvalue(assign_token, consts.OP_ASSIGN) - end_index = len(L) - 1 - while isinstance(L[end_index], ast.ListCompFor): - # we need to insert in reverse order to build the AST - built_listfors.insert(0, L[end_index]) - end_index -= 1 - index = 4 - while index <= end_index: - ifs.append(L[index]) - index += 1 - builder.push(ast.ListCompFor(ass_node, L[3], ifs)) - for listfor in built_listfors: - builder.push(listfor) - builder.push(TempRuleObject(0, len(built_listfors) + 1, None)) - -def build_list_if(builder, nb): - """list_if: 'if' test [list_iter]""" - L = get_atoms(builder, nb) - builder.push(ast.ListCompIf(L[1])) - def build_listmaker(builder, nb): """listmaker: test ( list_for | (',' test)* [','] )""" L = get_atoms(builder, nb) - if len(L) >= 2 and isinstance(L[1], ast.ListCompFor): + if len(L) >= 2 and isinstance(L[1], TokenObject) and L[1].value == 'for': # list comp - index = 1 - listfors = [] - while index < len(L): - listfors.append(L[index]) - index += 1 - builder.push(ast.ListComp(L[0], listfors)) + expr = L[0] + list_for = parse_listcomp(L[1:]) + builder.push(ast.ListComp(expr, list_for)) else: # regular list building (like in [1, 2, 3,]) index = 0 @@ -509,6 +479,61 @@ return names, defaults, flags +def parse_listcomp(tokens): + """parses 'for j in k for i in j if i %2 == 0' and returns + a GenExprFor instance + XXX: refactor with listmaker ? + """ + list_fors = [] + ifs = [] + index = 0 + while index < len(tokens): + if tokens[index].value == 'for': + index += 1 # skip 'for' + ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) + index += 2 # skip 'in' + iterable = tokens[index] + index += 1 + while index < len(tokens) and tokens[index].value == 'if': + ifs.append(ast.ListCompIf(tokens[index+1])) + index += 2 + list_fors.append(ast.ListCompFor(ass_node, iterable, ifs)) + ifs = [] + else: + raise ValueError('Unexpected token: %s' % tokens[index]) + return list_fors + + +def parse_genexpr_for(tokens): + """parses 'for j in k for i in j if i %2 == 0' and returns + a GenExprFor instance + XXX: if RPYTHON supports to pass a class object to a function, + we could refactor parse_listcomp and parse_genexpr_for, + and call : + - parse_listcomp(tokens, forclass=ast.GenExprFor, ifclass=...) + or: + - parse_listcomp(tokens, forclass=ast.ListCompFor, ifclass=...) + """ + genexpr_fors = [] + ifs = [] + index = 0 + while index < len(tokens): + if tokens[index].value == 'for': + index += 1 # skip 'for' + ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) + index += 2 # skip 'in' + iterable = tokens[index] + index += 1 + while index < len(tokens) and tokens[index].value == 'if': + ifs.append(ast.GenExprIf(tokens[index+1])) + index += 2 + genexpr_fors.append(ast.GenExprFor(ass_node, iterable, ifs)) + ifs = [] + else: + raise ValueError('Unexpected token: %s' % tokens[index]) + return genexpr_fors + + ASTRULES = { # "single_input" : build_single_input, sym.atom : build_atom, @@ -534,8 +559,6 @@ sym.varargslist : build_varargslist, sym.trailer : build_trailer, sym.arglist : build_arglist, - sym.list_for : build_list_for, - sym.list_if : build_list_if, sym.listmaker : build_listmaker, } Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 17:22:43 2005 @@ -44,9 +44,18 @@ "l = [i for i in range(10) if i%2 == 0 and i%2 == 1]", "l = [i for j in range(10) for i in range(j)]", "l = [i for j in range(10) for i in range(j) if j%2 == 0]", - "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 ==0]", + "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 == 0]", "l = [(a, b) for (a,b,c) in l2]", "l = [{a:b} for (a,b,c) in l2]", + "l = [i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0]", + ] + +genexps = [ + "l = (i for i in j)", + "l = (i for i in j if i%2 == 0)", + "l = (i for j in k for i in j)", + "l = (i for j in k for i in j if j%2==0)", + "l = (i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0)", ] @@ -91,6 +100,7 @@ funccalls, backtrackings, listmakers, + genexps, dictmakers, multiexpr, ] From rxe at codespeak.net Mon Jul 25 17:23:52 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 25 Jul 2005 17:23:52 +0200 (CEST) Subject: [pypy-svn] r15042 - pypy/dist/pypy/lib Message-ID: <20050725152352.A5B6627B53@code1.codespeak.net> Author: rxe Date: Mon Jul 25 17:23:51 2005 New Revision: 15042 Modified: pypy/dist/pypy/lib/_file.py Log: Added classmethod fdopen() and factored out the constructor for common code. (hpk/rxe) Modified: pypy/dist/pypy/lib/_file.py ============================================================================== --- pypy/dist/pypy/lib/_file.py (original) +++ pypy/dist/pypy/lib/_file.py Mon Jul 25 17:23:51 2005 @@ -79,12 +79,22 @@ """ def __init__(self, name, mode='r', bufsize=None): - self._mode = mode + self.fd = None self._name = name - self._closed = True # Until the file is successfully opened - self.softspace = 0 # Required according to file object docs - self.encoding = None # This is not used internally by file objects - + self._inithelper(mode, bufsize) + + def fdopen(cls, fd, mode='r', bufsize=None): + f = cls.__new__(cls) + + f.fd = fd + f._name = "" + f._inithelper(mode, bufsize) + return f + + fdopen = classmethod(fdopen) + + def _inithelper(self, mode, bufsize): + self._mode = mode if not mode or mode[0] not in ['r', 'w', 'a', 'U']: raise IOError('invalid mode : %s' % mode) @@ -110,19 +120,25 @@ if binary or universal: flag |= O_BINARY - self.fd = os.open(name, flag) + if self.fd is None: + self.fd = os.open(self.name, flag) if basemode == 'a': try: os.lseek(self.fd, 0, 2) except OSError: pass + + reading = basemode == 'r' or plus + writing = basemode != 'r' or plus + self._closed = True # Until the file is successfully opened + + self.softspace = 0 # Required according to file object docs + self.encoding = None # This is not used internally by file objects + self.stream = _sio.DiskFile(self.fd) self._closed = False - reading = basemode == 'r' or plus - writing = basemode != 'r' or plus - if bufsize == 0: # no buffering pass elif bufsize == 1: # line-buffering From cfbolz at codespeak.net Mon Jul 25 17:33:19 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 17:33:19 +0200 (CEST) Subject: [pypy-svn] r15043 - in pypy/dist/pypy: annotation rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20050725153319.6032C27B53@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 17:33:18 2005 New Revision: 15043 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py pypy/dist/pypy/translator/c/test/test_typed.py Log: (pedronis, cfbolz): - some more builtin cleanup regarding the time functions - implemented the os stat, fstat function in the c backend - tests Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Mon Jul 25 17:33:18 2005 @@ -253,9 +253,6 @@ def pathpart(*args): return SomeString() -def time_func(): - return SomeFloat() - def import_func(*args): return SomeObject() @@ -290,10 +287,6 @@ BUILTIN_ANALYZERS[os.path.exists] = test BUILTIN_ANALYZERS[os.path.isdir] = test -# time stuff -BUILTIN_ANALYZERS[time.time] = time_func -BUILTIN_ANALYZERS[time.clock] = time_func - # import BUILTIN_ANALYZERS[__import__] = import_func 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 Mon Jul 25 17:33:18 2005 @@ -110,6 +110,7 @@ tup.item7 = intmask(stat7) tup.item8 = intmask(stat8) tup.item9 = intmask(stat9) + return tup def ll_os_fstat(fd): (stat0, stat1, stat2, stat3, stat4, @@ -123,4 +124,4 @@ stat5, stat6, stat7, stat8, stat9) = os.stat(from_rstr(path)) return ll_stat_result(stat0, stat1, stat2, stat3, stat4, stat5, stat6, stat7, stat8, stat9) -ll_os_fstat.suggested_primitive = True +ll_os_stat.suggested_primitive = True Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jul 25 17:33:18 2005 @@ -258,25 +258,6 @@ BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate -import time - -def rtype_time_clock(hop): - c = hop.inputconst(pyobj_repr, time.clock) - v = hop.genop('simple_call', [c], resulttype = pyobj_repr) - return hop.llops.convertvar(v, pyobj_repr, float_repr) - -BUILTIN_TYPER[time.clock] = rtype_time_clock - - -def rtype_time_time(hop): - c = hop.inputconst(pyobj_repr, time.time) - v = hop.genop('simple_call', [c], resulttype = pyobj_repr) - return hop.llops.convertvar(v, pyobj_repr, float_repr) - -BUILTIN_TYPER[time.time] = rtype_time_time - -import math - from pypy.rpython import extfunctable def make_rtype_extfunc(extfuncinfo): Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Mon Jul 25 17:33:18 2005 @@ -14,6 +14,8 @@ ll_os .ll_os_close: 'LL_os_close', ll_os .ll_os_dup: 'LL_os_dup', ll_os .ll_os_getcwd: 'LL_os_getcwd', + ll_os .ll_os_stat: 'LL_os_stat', + ll_os .ll_os_fstat: 'LL_os_fstat', ll_time.ll_time_clock: 'LL_time_clock', ll_math.ll_math_log10: 'LL_math_log10', ll_math.ll_math_ceil: 'LL_math_ceil', @@ -32,6 +34,7 @@ yield ('RPyString', STR) yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT) yield ('RPyMODF_RESULT', ll_math.MODF_RESULT) + yield ('RPySTAT_RESULT', ll_os.STAT_RESULT) def predeclare_utility_functions(db, rtyper): # Common utility functions @@ -51,14 +54,14 @@ yield annotate(ll_math.ll_frexp_result, lltype.Float, lltype.Signed) yield annotate(ll_math.ll_modf_result, lltype.Float, lltype.Float) - + yield annotate(ll_os.ll_stat_result, *([lltype.Signed] * 10)) + def predeclare_extfuncs(db, rtyper): for func, funcobj in db.externalfuncs.items(): c_name = EXTERNALS[func] funcptr = lltype._ptr(lltype.Ptr(lltype.typeOf(funcobj)), funcobj) # hum yield c_name, funcptr - def predeclare_exception_data(db, rtyper): # Exception-related types and constants exceptiondata = rtyper.getexceptiondata() Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Mon Jul 25 17:33:18 2005 @@ -19,6 +19,19 @@ */ +/* just do what CPython is doing... */ + +#if defined(MS_WIN64) || defined(MS_WINDOWS) +# define STAT _stati64 +# define FSTAT _fstati64 +# define STRUCT_STAT struct _stati64 +#else +# define STAT stat +# define FSTAT fstat +# define STRUCT_STAT struct stat +#endif + + int LL_os_open(RPyString *filename, int flag, int mode) { /* XXX unicode_file_names */ @@ -79,3 +92,43 @@ } return RPyString_FromString(buf); } + +RPySTAT_RESULT* _stat_construct_result_helper(STRUCT_STAT st) { + long res0, res1, res2, res3, res4, res5, res6, res7, res8, res9; + res0 = (long)st.st_mode; + res1 = (long)st.st_ino; /*XXX HAVE_LARGEFILE_SUPPORT!*/ + res2 = (long)st.st_dev; /*XXX HAVE_LONG_LONG!*/ + res3 = (long)st.st_nlink; + res4 = (long)st.st_uid; + res5 = (long)st.st_gid; + res6 = (long)st.st_size; /*XXX HAVE_LARGEFILE_SUPPORT!*/ + res7 = (long)st.st_atime; /*XXX ignoring quite a lot of things for time here */ + res8 = (long)st.st_mtime; /*XXX ignoring quite a lot of things for time here */ + res9 = (long)st.st_ctime; /*XXX ignoring quite a lot of things for time here */ + /*XXX ignoring BLOCK info here*/ + + return ll_stat_result(res0, res1, res2, res3, res4, + res5, res6, res7, res8, res9); +} + + +RPySTAT_RESULT* LL_os_stat(RPyString * fname) { + STRUCT_STAT st; + int error = STAT(RPyString_AsString(fname), &st); + if (error != 0) { + RAISE_OSERROR(errno); + return NULL; + } + return _stat_construct_result_helper(st); +} + +RPySTAT_RESULT* LL_os_fstat(long fd) { + STRUCT_STAT st; + int error = FSTAT(fd, &st); + if (error != 0) { + RAISE_OSERROR(errno); + return NULL; + } + return _stat_construct_result_helper(st); +} + Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Mon Jul 25 17:33:18 2005 @@ -54,9 +54,54 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) +def test_os_stat(): + filename = str(py.magic.autopath()) + def call_stat(): + st = os.stat(filename) + return st + f = compile(call_stat, []) + result = f() + assert result[0] == os.stat(filename)[0] + assert result[1] == os.stat(filename)[1] + assert result[2] == os.stat(filename)[2] + +def test_os_fstat(): + filename = str(py.magic.autopath()) + def call_fstat(): + fd = os.open(filename, os.O_RDONLY, 0777) + st = os.fstat(fd) + return st + f = compile(call_fstat, []) + result = f() + assert result[0] == os.stat(filename)[0] + assert result[1] == os.stat(filename)[1] + assert result[2] == os.stat(filename)[2] + def test_getcwd(): def does_stuff(): return os.getcwd() f1 = compile(does_stuff, []) res = f1() assert res == os.getcwd() + +def test_math_exp(): + from math import exp + def fn(f): + return exp(f) + f = compile(fn, [float]) + assert f(1.0) == exp(1.0) + +def test_math_frexp(): + from math import frexp + def fn(x): + return frexp(x) + f = compile(fn, [float]) + assert f(10.123) == frexp(10.123) + +def test_math_modf(): + from math import modf + def fn(x): + return modf(x) + f = compile(fn, [float]) + assert f(10.123) == modf(10.123) + 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 Jul 25 17:33:18 2005 @@ -275,27 +275,6 @@ res = self.getcompiled(fn)() assert res == 0 - def test_math_exp(self): - from math import exp - def fn(f=float): - return exp(f) - f = self.getcompiled(fn) - assert f(1.0) == exp(1.0) - - def test_math_frexp(self): - from math import frexp - def fn(x=float): - return frexp(x) - f = self.getcompiled(fn) - assert f(10.123) == frexp(10.123) - - def test_math_modf(self): - from math import modf - def fn(x=float): - return modf(x) - f = self.getcompiled(fn) - assert f(10.123) == modf(10.123) - def test_stringformatting(self): def fn(i=int): From adim at codespeak.net Mon Jul 25 17:58:04 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 25 Jul 2005 17:58:04 +0200 (CEST) Subject: [pypy-svn] r15045 - in pypy/dist/pypy/interpreter/pyparser: . test test/samples Message-ID: <20050725155804.5B1ED27B55@code1.codespeak.net> Author: adim Date: Mon Jul 25 17:58:02 2005 New Revision: 15045 Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_several_statements.py Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Log: implemented file_input target (missing docstring management) Modified: pypy/dist/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/astbuilder.py Mon Jul 25 17:58:02 2005 @@ -66,9 +66,6 @@ L.reverse() return L -def build_single_input( builder, nb ): - pass - def eval_number(value): """temporary implementation""" return eval(value) @@ -313,6 +310,26 @@ nodes.append(node) builder.push( ast.Stmt(nodes) ) +def build_file_input(builder, nb): + # FIXME: need to handle docstring ! + doc = None + # doc = self.get_docstring(nodelist, symbol.file_input) + # if doc is not None: + # i = 1 + # else: + # i = 0 + stmts = [] + L = get_atoms(builder, nb) + for node in L: + if isinstance(node, ast.Stmt): + stmts.extend(node.nodes) + elif isinstance(node, TokenObject) and node.name == tok.ENDMARKER: + # XXX Can't we just remove the last element of the list ? + break + else: + stmts.append(node) + return builder.push(ast.Module(doc, ast.Stmt(stmts))) + def build_single_input( builder, nb ): L = get_atoms( builder, nb ) l = len(L) @@ -320,7 +337,8 @@ builder.push(ast.Module(None, L[0])) return raise WalkerError("error") - + + def build_testlist_gexp(builder, nb): L = get_atoms(builder, nb) l = len(L) @@ -554,6 +572,7 @@ sym.small_stmt : return_one, sym.simple_stmt : build_simple_stmt, sym.single_input : build_single_input, + sym.file_input : build_file_input, sym.testlist_gexp : build_testlist_gexp, sym.lambdef : build_lambdef, sym.varargslist : build_varargslist, Added: pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_several_statements.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_several_statements.py Mon Jul 25 17:58:02 2005 @@ -0,0 +1,3 @@ +a = 1 +b = 2 +c = a + b Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py Mon Jul 25 17:58:02 2005 @@ -105,18 +105,25 @@ multiexpr, ] -def ast_parse_expr(expr): +TARGET_DICT = { + 'single' : 'single_input', + 'exec' : 'file_input', + 'eval' : 'eval_input', + } + +def ast_parse_expr(expr, target='single'): + target = TARGET_DICT[target] builder = AstBuilder() - PYTHON_PARSER.parse_source(expr, 'single_input', builder) + PYTHON_PARSER.parse_source(expr, target, builder) return builder -def tuple_parse_expr(expr): +def tuple_parse_expr(expr, target='single'): t = Transformer() - return ast_from_input(expr, 'single', t) + return ast_from_input(expr, target, t) -def check_expression(expr): - r1 = ast_parse_expr(expr) - ast = tuple_parse_expr(expr) +def check_expression(expr, target='single'): + r1 = ast_parse_expr(expr, target) + ast = tuple_parse_expr(expr, target) print "-" * 30 print "ORIG :", ast print @@ -131,8 +138,9 @@ yield check_expression, expr -SNIPPETS = [ -# 'snippet_1.py', +SNIPPETS = [ + 'snippet_1.py', + 'snippet_several_statements.py', # 'snippet_2.py', # 'snippet_3.py', # 'snippet_4.py', @@ -157,10 +165,9 @@ # 'snippet_whitespaces.py', ] -def skippedtest_snippets(): - py.test.skip('Not ready to test on real snippet files') +def test_snippets(): for snippet_name in SNIPPETS: filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name) source = file(filepath).read() - yield check_expression, source + yield check_expression, source, 'exec' From arigo at codespeak.net Mon Jul 25 18:31:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 18:31:37 +0200 (CEST) Subject: [pypy-svn] r15049 - pypy/dist/pypy/lib/test2 Message-ID: <20050725163137.91A3C27B57@code1.codespeak.net> Author: arigo Date: Mon Jul 25 18:31:35 2005 New Revision: 15049 Added: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py (contents, props changed) Log: In-progress test for marshal. Added: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Mon Jul 25 18:31:35 2005 @@ -0,0 +1,69 @@ +import sys +import marshal as cpy_marshal +from pypy.lib import marshal + +hello = "he" +hello += "llo" +def func(x): + return lambda y: x+y +scopefunc = func(42) + +TESTCASES = [ + None, + False, + True, + StopIteration, + Ellipsis, + 42, + sys.maxint, + -1.25, + 2+5j, + 42L, + -1234567890123456789012345678901234567890L, + hello, # not interned + "hello", + (), + (1, 2), + [], + [3, 4], + {}, + {5: 6, 7: 8}, + func.func_code, + scopefunc.func_code, + u'hello', + ] + +try: + TESTCASES += [ + set(), + set([1, 2]), + frozenset(), + frozenset([3, 4]), + ] +except NameError: + pass # Python < 2.4 + + +def test_cases(): + for case in TESTCASES: + yield dump_and_reload, case + yield load_from_cpython, case + yield dump_to_cpython, case + +def dump_and_reload(case): + print 'dump_and_reload', case + s = marshal.dumps(case) + obj = marshal.loads(s) + assert obj == case + +def load_from_cpython(case): + print 'load_from_cpython', case + s = cpy_marshal.dumps(case) + obj = marshal.loads(s) + assert obj == case + +def dump_to_cpython(case): + print 'dump_to_cpython', case + s = marshal.dumps(case) + obj = cpy_marshal.loads(s) + assert obj == case From arigo at codespeak.net Mon Jul 25 18:37:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 18:37:26 +0200 (CEST) Subject: [pypy-svn] r15050 - pypy/dist/pypy/lib/test2 Message-ID: <20050725163726.E663E27B57@code1.codespeak.net> Author: arigo Date: Mon Jul 25 18:37:25 2005 New Revision: 15050 Modified: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Log: Polishing. Modified: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py (original) +++ pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Mon Jul 25 18:37:25 2005 @@ -51,19 +51,19 @@ yield dump_to_cpython, case def dump_and_reload(case): - print 'dump_and_reload', case + print 'dump_and_reload', `case` s = marshal.dumps(case) obj = marshal.loads(s) assert obj == case def load_from_cpython(case): - print 'load_from_cpython', case + print 'load_from_cpython', `case` s = cpy_marshal.dumps(case) obj = marshal.loads(s) assert obj == case def dump_to_cpython(case): - print 'dump_to_cpython', case + print 'dump_to_cpython', `case` s = marshal.dumps(case) obj = cpy_marshal.loads(s) assert obj == case From cfbolz at codespeak.net Mon Jul 25 18:38:32 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 18:38:32 +0200 (CEST) Subject: [pypy-svn] r15051 - in pypy/dist/pypy/rpython/module: . test Message-ID: <20050725163832.DD2D127B57@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 18:38:32 2005 New Revision: 15051 Added: pypy/dist/pypy/rpython/module/support.py pypy/dist/pypy/rpython/module/test/test_ll_os_path.py Modified: pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/ll_os_path.py Log: (pedronis, cfbolz): - added tests for os.path.exists - moved some functions to rpython/module/support 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 Mon Jul 25 18:38:32 2005 @@ -17,23 +17,9 @@ from pypy.rpython.rstr import STR from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc -# utility conversion functions -def to_rstr(s): - p = malloc(STR, len(s)) - for i in range(len(s)): - p.chars[i] = s[i] - return p - -def from_rstr(rs): - return ''.join([rs.chars[i] for i in range(len(rs.chars))]) - -def ll_strcpy(dstchars, srcchars, n): - i = 0 - while i < n: - dstchars[i] = srcchars[i] - i += 1 -# ____________________________________________________________ +from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy + def ll_os_open(fname, flag, mode): return os.open(from_rstr(fname), flag, mode) 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 Mon Jul 25 18:38:32 2005 @@ -7,6 +7,7 @@ import os from pypy.rpython.rstr import STR from pypy.rpython.module.ll_os import from_rstr +from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy # Does a path exist? @@ -16,6 +17,6 @@ """Test whether a path exists""" try: st = os.stat(from_rstr(path)) - except os.error: + except OSError: return False return True Added: pypy/dist/pypy/rpython/module/support.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/support.py Mon Jul 25 18:38:32 2005 @@ -0,0 +1,19 @@ +from pypy.rpython.rstr import STR +from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc + + +# utility conversion functions +def to_rstr(s): + p = malloc(STR, len(s)) + for i in range(len(s)): + p.chars[i] = s[i] + return p + +def from_rstr(rs): + return ''.join([rs.chars[i] for i in range(len(rs.chars))]) + +def ll_strcpy(dstchars, srcchars, n): + i = 0 + while i < n: + dstchars[i] = srcchars[i] + i += 1 Added: pypy/dist/pypy/rpython/module/test/test_ll_os_path.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/module/test/test_ll_os_path.py Mon Jul 25 18:38:32 2005 @@ -0,0 +1,12 @@ +import py + +import os + +from pypy.rpython.module.ll_os_path import * +from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy + +def test_exists(): + filename = to_rstr(str(py.magic.autopath())) + assert ll_os_path_exists(filename) == True + assert not ll_os_path_exists(to_rstr( + "strange_filename_that_looks_improbable.sde")) From cfbolz at codespeak.net Mon Jul 25 18:39:41 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 18:39:41 +0200 (CEST) Subject: [pypy-svn] r15053 - pypy/dist/pypy/rpython/module Message-ID: <20050725163941.4C4C427B57@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 18:39:41 2005 New Revision: 15053 Modified: pypy/dist/pypy/rpython/module/ll_os_path.py Log: removed nonsensical import 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 Mon Jul 25 18:39:41 2005 @@ -6,7 +6,6 @@ import os from pypy.rpython.rstr import STR -from pypy.rpython.module.ll_os import from_rstr from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy From tismer at codespeak.net Mon Jul 25 18:58:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 18:58:20 +0200 (CEST) Subject: [pypy-svn] r15056 - pypy/dist/pypy/lib Message-ID: <20050725165820.6B6F527B51@code1.codespeak.net> Author: tismer Date: Mon Jul 25 18:58:18 2005 New Revision: 15056 Modified: pypy/dist/pypy/lib/marshal.py Log: made marshal CPython 2.5 compatible. next step is to geninterp it, to have something to bootstrap compiled code. Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Mon Jul 25 18:58:18 2005 @@ -15,6 +15,9 @@ TYPE_NULL = '0' TYPE_NONE = 'N' +TYPE_FALSE = 'F' +TYPE_TRUE = 'T' +TYPE_STOPITER = 'S' TYPE_ELLIPSIS = '.' TYPE_INT = 'i' TYPE_INT64 = 'I' @@ -22,13 +25,17 @@ TYPE_COMPLEX = 'x' TYPE_LONG = 'l' TYPE_STRING = 's' +TYPE_INTERNED = 't' +TYPE_STRINGREF= 'R' TYPE_TUPLE = '(' TYPE_LIST = '[' TYPE_DICT = '{' TYPE_CODE = 'c' TYPE_UNKNOWN = '?' -FALSE_CODE = 'F' -TRUE_CODE = 'T' +TYPE_UNICODE = 'u' +TYPE_UNKNOWN = '?' +TYPE_SET = '<' +TYPE_FROZENSET= '>' class Marshaller: @@ -62,11 +69,16 @@ def dump_bool(self, x): if x: - self.f.write(TRUE_CODE) + self.f.write(TYPE_TRUE) else: - self.f.write(FALSE_CODE) + self.f.write(TYPE_FALSE) dispatch[bool] = dump_bool + def dump_stopiter(self, x): + assert x is StopIteration + self.f.write(TYPE_STOPITER) + dispatch[type(StopIteration)] = dump_stopiter + def dump_ellipsis(self, x): self.f.write(TYPE_ELLIPSIS) @@ -123,11 +135,20 @@ pass def dump_string(self, x): + # XXX we can't check for interned strings, yet, + # so we (for now) never create TYPE_INTERNED or TYPE_STRINGREF self.f.write(TYPE_STRING) self.w_long(len(x)) self.f.write(x) dispatch[StringType] = dump_string + def dump_unicode(self, x): + self.f.write(TYPE_UNICODE) + s = x.encode('utf8') + self.w_long(len(s)) + self.f.write(s) + dispatch[UnicodeType] = dump_unicode + def dump_tuple(self, x): self.f.write(TYPE_TUPLE) self.w_long(len(x)) @@ -152,17 +173,19 @@ def dump_code(self, x): self.f.write(TYPE_CODE) - self.w_short(x.co_argcount) - self.w_short(x.co_nlocals) - self.w_short(x.co_stacksize) - self.w_short(x.co_flags) + self.w_long(x.co_argcount) + self.w_long(x.co_nlocals) + self.w_long(x.co_stacksize) + self.w_long(x.co_flags) self.dump(x.co_code) self.dump(x.co_consts) self.dump(x.co_names) self.dump(x.co_varnames) + self.dump(x.co_freevars) + self.dump(x.co_cellvars) self.dump(x.co_filename) self.dump(x.co_name) - self.w_short(x.co_firstlineno) + self.w_long(x.co_firstlineno) self.dump(x.co_lnotab) try: dispatch[CodeType] = dump_code @@ -179,6 +202,7 @@ def __init__(self, f): self.f = f + self._stringtable = [] def load(self): c = self.f.read(1) @@ -232,14 +256,18 @@ def load_true(self): return True - dispatch[TRUE_CODE] = load_true + dispatch[TYPE_TRUE] = load_true def load_false(self): return False - dispatch[FALSE_CODE] = load_false + dispatch[TYPE_FALSE] = load_false + + def load_stopiter(self): + return StopIteration + dispatch[TYPE_STOPITER] = load_stopiter def load_ellipsis(self): - return EllipsisType + return Ellipsis dispatch[TYPE_ELLIPSIS] = load_ellipsis def load_int(self): @@ -284,6 +312,25 @@ return self.f.read(n) dispatch[TYPE_STRING] = load_string + def load_interned(self): + n = self.r_long() + ret = intern(self.f.read(n)) + self._stringtable.append(ret) + return ret + dispatch[TYPE_INTERNED] = load_interned + + def load_stringref(self): + n = self.r_long() + return self._stringtable[n] + dispatch[TYPE_STRINGREF] = load_stringref + + def load_unicode(self): + n = self.r_long() + s = self.f.read(n) + ret = s.decode('utf8') + return ret + dispatch[TYPE_UNICODE] = load_unicode + def load_tuple(self): return tuple(self.load_list()) dispatch[TYPE_TUPLE] = load_tuple @@ -308,22 +355,25 @@ dispatch[TYPE_DICT] = load_dict def load_code(self): - argcount = self.r_short() - nlocals = self.r_short() - stacksize = self.r_short() - flags = self.r_short() + argcount = self.r_long() + nlocals = self.r_long() + stacksize = self.r_long() + flags = self.r_long() code = self.load() consts = self.load() names = self.load() varnames = self.load() + freevars = self.load() + cellvars = self.load() filename = self.load() name = self.load() - firstlineno = self.r_short() + firstlineno = self.r_long() lnotab = self.load() if not new: raise RuntimeError, "can't unmarshal code objects; no 'new' module" return new.code(argcount, nlocals, stacksize, flags, code, consts, - names, varnames, filename, name, firstlineno, lnotab) + names, varnames, filename, name, firstlineno, lnotab, + freevars, cellvars) dispatch[TYPE_CODE] = load_code From cfbolz at codespeak.net Mon Jul 25 19:10:24 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 25 Jul 2005 19:10:24 +0200 (CEST) Subject: [pypy-svn] r15061 - in pypy/dist/pypy/rpython: . module test Message-ID: <20050725171024.6DB1927B56@code1.codespeak.net> Author: cfbolz Date: Mon Jul 25 19:10:23 2005 New Revision: 15061 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: (pedronis, cfbolz): intermediate checkin to be able to continue working on a different machine. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Mon Jul 25 19:10:23 2005 @@ -78,6 +78,7 @@ declare(os.ftruncate, noneannotation, 'll_os/ftruncate') declare(os.fstat , statannotation, 'll_os/fstat') declare(os.stat , statannotation, 'll_os/stat') +declare(os.path.exists, bool , 'll_os_path/exists') declare(time.time , float , 'll_time/time') declare(time.clock , float , 'll_time/clock') declare(time.sleep , noneannotation, 'll_time/sleep') Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jul 25 19:10:23 2005 @@ -161,6 +161,13 @@ etype = exdata.ll_type_of_exc_inst(evalue) raise LLException(etype, evalue) + def invoke_callable_with_pyexceptions(self, fptr, *args): + print "invoking %s(%s)" % (fptr, args) + try: + return fptr._obj._callable(*args) + except Exception, e: + self.make_llexception(e.__class__) + # __________________________________________________________ # misc LL operation implementations @@ -180,7 +187,7 @@ def op_direct_call(self, f, *args): has_callable = getattr(f._obj, '_callable', None) is not None if has_callable and getattr(f._obj._callable, 'suggested_primitive', False): - return f._obj._callable(*args) + self.invoke_callable_with_pyexceptions(f, *args) if hasattr(f._obj, 'graph'): graph = f._obj.graph else: @@ -188,7 +195,7 @@ graph = self.llinterpreter.getgraph(f._obj._callable) except KeyError: assert has_callable, "don't know how to execute %r" % f - return f._obj._callable(*args) + return self.invoke_callable_with_pyexceptions(f, *args) frame = self.__class__(graph, args, self.llinterpreter) return frame.eval() 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 Mon Jul 25 19:10:23 2005 @@ -16,8 +16,6 @@ import os, errno from pypy.rpython.rstr import STR from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc - - from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Mon Jul 25 19:10:23 2005 @@ -6,6 +6,7 @@ from pypy.translator.translator import Translator from pypy.rpython.rlist import * from pypy.rpython.rint import signed_repr +from pypy.rpython import rstr from pypy.annotation.model import lltype_to_annotation # switch on logging of interp to show more info on failing tests @@ -61,6 +62,8 @@ T = typeOf(x) if T == Ptr(PyObject) and someobjects: return object + elif T == Ptr(rstr.STR): + return str else: return lltype_to_annotation(T) Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Mon Jul 25 19:10:23 2005 @@ -6,6 +6,7 @@ from pypy.tool import udir from pypy.annotation.builtin import * +from pypy.rpython.module.support import to_rstr import py def test_rbuiltin_list(): @@ -118,7 +119,17 @@ assert cfptr.value._obj._callable == ll_os.ll_os_open count += 1 assert count == 1 - + +def test_os_path_exists(): + import os + def f(fn): + return os.path.exists(fn) + filename = to_rstr(str(py.magic.autopath())) + assert interpret(f, [filename]) == True + assert interpret(f, [ + to_rstr("strange_filename_that_looks_improbable.sde")]) == False + + def test_pbc_isTrue(): class C: def f(self): @@ -191,3 +202,4 @@ assert res is True res = interpret(f, [1]) assert res is False + From arigo at codespeak.net Mon Jul 25 19:16:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 19:16:30 +0200 (CEST) Subject: [pypy-svn] r15062 - pypy/dist/pypy/lib/test2 Message-ID: <20050725171630.418D827B56@code1.codespeak.net> Author: arigo Date: Mon Jul 25 19:16:28 2005 New Revision: 15062 Modified: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Log: More marshal tests: marshalling instances of subclasses of built-in types. Modified: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py (original) +++ pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Mon Jul 25 19:16:28 2005 @@ -49,6 +49,7 @@ yield dump_and_reload, case yield load_from_cpython, case yield dump_to_cpython, case + yield dump_subclass, case def dump_and_reload(case): print 'dump_and_reload', `case` @@ -67,3 +68,15 @@ s = marshal.dumps(case) obj = cpy_marshal.loads(s) assert obj == case + +def dump_subclass(case): + try: + class Subclass(type(case)): + pass + case = Subclass(case) + except TypeError: + return + print 'dump_subclass', `case` + s = marshal.dumps(case) + obj = marshal.loads(s) + assert obj == case From tismer at codespeak.net Mon Jul 25 19:17:41 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 19:17:41 +0200 (CEST) Subject: [pypy-svn] r15063 - pypy/dist/pypy/lib Message-ID: <20050725171741.8857027B56@code1.codespeak.net> Author: tismer Date: Mon Jul 25 19:17:40 2005 New Revision: 15063 Modified: pypy/dist/pypy/lib/marshal.py Log: added support for sets Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Mon Jul 25 19:17:40 2005 @@ -31,7 +31,6 @@ TYPE_LIST = '[' TYPE_DICT = '{' TYPE_CODE = 'c' -TYPE_UNKNOWN = '?' TYPE_UNICODE = 'u' TYPE_UNKNOWN = '?' TYPE_SET = '<' @@ -192,6 +191,13 @@ except NameError: pass + def dump_set(self, x): + self.f.write(TYPE_SET) + self.w_long(len(x)) + for each in set: + self.dump(each) + dispatch[TYPE_SET] = dump_set + dispatch[TYPE_FROZENSET] = dump_set class NULL: pass @@ -376,6 +382,17 @@ freevars, cellvars) dispatch[TYPE_CODE] = load_code + def load_set(self): + n = self.r_long() + args = [self.load() for i in range(n)] + return set(args) + dispatch[TYPE_SET] = load_set + + def load_frozenset(self): + n = self.r_long() + args = [self.load() for i in range(n)] + return frozenset(args) + dispatch[TYPE_FROZENSET] = load_frozenset def dump(x, f): Marshaller(f).dump(x) From tismer at codespeak.net Mon Jul 25 19:25:43 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 19:25:43 +0200 (CEST) Subject: [pypy-svn] r15064 - pypy/dist/pypy/lib Message-ID: <20050725172543.6EFEE27B56@code1.codespeak.net> Author: tismer Date: Mon Jul 25 19:25:42 2005 New Revision: 15064 Modified: pypy/dist/pypy/lib/marshal.py Log: added support for not crashing on subtypes Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Mon Jul 25 19:25:42 2005 @@ -44,7 +44,16 @@ self.f = f def dump(self, x): - self.dispatch[type(x)](self, x) + try: + self.dispatch[type(x)](self, x) + except KeyError: + for tp in type(x).mro(): + func = self.dispatch.get(tp) + if func: + break + else: + raise ValueError, "unsupported type for marshal.dump" + func(self, x) def w_long64(self, x): self.w_long(x) From arigo at codespeak.net Mon Jul 25 19:29:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 25 Jul 2005 19:29:27 +0200 (CEST) Subject: [pypy-svn] r15065 - in pypy/dist/pypy/lib: . test2 Message-ID: <20050725172927.55B2527B56@code1.codespeak.net> Author: arigo Date: Mon Jul 25 19:29:24 2005 New Revision: 15065 Added: pypy/dist/pypy/lib/test2/test_marshal_extra.py - copied, changed from r15064, pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Removed: pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Modified: pypy/dist/pypy/lib/marshal.py Log: Completed marshal. Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Mon Jul 25 19:29:24 2005 @@ -203,10 +203,22 @@ def dump_set(self, x): self.f.write(TYPE_SET) self.w_long(len(x)) - for each in set: + for each in x: self.dump(each) - dispatch[TYPE_SET] = dump_set - dispatch[TYPE_FROZENSET] = dump_set + try: + dispatch[set] = dump_set + except NameError: + pass + + def dump_frozenset(self, x): + self.f.write(TYPE_FROZENSET) + self.w_long(len(x)) + for each in x: + self.dump(each) + try: + dispatch[frozenset] = dump_frozenset + except NameError: + pass class NULL: pass Deleted: /pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py ============================================================================== --- /pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py Mon Jul 25 19:29:24 2005 +++ (empty file) @@ -1,82 +0,0 @@ -import sys -import marshal as cpy_marshal -from pypy.lib import marshal - -hello = "he" -hello += "llo" -def func(x): - return lambda y: x+y -scopefunc = func(42) - -TESTCASES = [ - None, - False, - True, - StopIteration, - Ellipsis, - 42, - sys.maxint, - -1.25, - 2+5j, - 42L, - -1234567890123456789012345678901234567890L, - hello, # not interned - "hello", - (), - (1, 2), - [], - [3, 4], - {}, - {5: 6, 7: 8}, - func.func_code, - scopefunc.func_code, - u'hello', - ] - -try: - TESTCASES += [ - set(), - set([1, 2]), - frozenset(), - frozenset([3, 4]), - ] -except NameError: - pass # Python < 2.4 - - -def test_cases(): - for case in TESTCASES: - yield dump_and_reload, case - yield load_from_cpython, case - yield dump_to_cpython, case - yield dump_subclass, case - -def dump_and_reload(case): - print 'dump_and_reload', `case` - s = marshal.dumps(case) - obj = marshal.loads(s) - assert obj == case - -def load_from_cpython(case): - print 'load_from_cpython', `case` - s = cpy_marshal.dumps(case) - obj = marshal.loads(s) - assert obj == case - -def dump_to_cpython(case): - print 'dump_to_cpython', `case` - s = marshal.dumps(case) - obj = cpy_marshal.loads(s) - assert obj == case - -def dump_subclass(case): - try: - class Subclass(type(case)): - pass - case = Subclass(case) - except TypeError: - return - print 'dump_subclass', `case` - s = marshal.dumps(case) - obj = marshal.loads(s) - assert obj == case Copied: pypy/dist/pypy/lib/test2/test_marshal_extra.py (from r15064, pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py) ============================================================================== --- pypy/dist/pypy/lib/test2/inprogress_marshal_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_marshal_extra.py Mon Jul 25 19:29:24 2005 @@ -59,12 +59,19 @@ def load_from_cpython(case): print 'load_from_cpython', `case` - s = cpy_marshal.dumps(case) + try: + s = cpy_marshal.dumps(case) + except ValueError: + return # this version of CPython doesn't support this object obj = marshal.loads(s) assert obj == case def dump_to_cpython(case): print 'dump_to_cpython', `case` + try: + cpy_marshal.dumps(case) + except ValueError: + return # this version of CPython doesn't support this object s = marshal.dumps(case) obj = cpy_marshal.loads(s) assert obj == case From hpk at codespeak.net Mon Jul 25 19:33:00 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 19:33:00 +0200 (CEST) Subject: [pypy-svn] r15066 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050725173300.251D227B56@code1.codespeak.net> Author: hpk Date: Mon Jul 25 19:32:59 2005 New Revision: 15066 Added: pypy/dist/pypy/module/__builtin__/special.py pypy/dist/pypy/module/__builtin__/test/test_special.py Modified: pypy/dist/pypy/module/__builtin__/__init__.py Log: (rxe,hpk) add a helper '_isfake' for determining at app level if an instance is a Faked one. Modified: pypy/dist/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/__init__.py (original) +++ pypy/dist/pypy/module/__builtin__/__init__.py Mon Jul 25 19:32:59 2005 @@ -72,8 +72,8 @@ '_classobj' : 'space.w_classobj', '_instance' : 'space.w_instance', # default __metaclass__ - # XXX can use _classobj when we have a working one integrated '__metaclass__' : '(space.w_type)', + '_isfake' : 'special._isfake', # interp-level function definitions 'abs' : 'operation.abs', Added: pypy/dist/pypy/module/__builtin__/special.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/special.py Mon Jul 25 19:32:59 2005 @@ -0,0 +1,4 @@ + +def _isfake(space, w_obj): + return space.wrap(bool(w_obj.typedef.fakedcpytype)) + #return space.wrap(bool(getattr(w_obj.typedef, 'fakedcpytype', None))) Added: pypy/dist/pypy/module/__builtin__/test/test_special.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/test/test_special.py Mon Jul 25 19:32:59 2005 @@ -0,0 +1,15 @@ +import py + +def app_test__isfake(): + assert not _isfake(map) + assert not _isfake(object) + assert not _isfake(_isfake) + +def app_test__isfake_currently_true(): + import array + assert _isfake(array) + +def XXXapp_test__isfake_file(): # only if you are not using --file + import sys + assert _isfake(sys.stdout) + From tismer at codespeak.net Mon Jul 25 19:47:25 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 19:47:25 +0200 (CEST) Subject: [pypy-svn] r15068 - pypy/dist/pypy/lib Message-ID: <20050725174725.F0DEC27B5A@code1.codespeak.net> Author: tismer Date: Mon Jul 25 19:47:24 2005 New Revision: 15068 Modified: pypy/dist/pypy/lib/marshal.py Log: made the exception string as dumb as in CPython Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Mon Jul 25 19:47:24 2005 @@ -52,7 +52,7 @@ if func: break else: - raise ValueError, "unsupported type for marshal.dump" + raise ValueError, "unmarshallable object" func(self, x) def w_long64(self, x): From ericvrp at codespeak.net Mon Jul 25 19:50:33 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 25 Jul 2005 19:50:33 +0200 (CEST) Subject: [pypy-svn] r15069 - pypy/dist/pypy/translator/llvm2/tool Message-ID: <20050725175033.0903227B5A@code1.codespeak.net> Author: ericvrp Date: Mon Jul 25 19:50:32 2005 New Revision: 15069 Added: pypy/dist/pypy/translator/llvm2/tool/ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (contents, props changed) Log: Wrote simple tool to get an overview of the suggested_primitive functions that still need to be implemented in the llvm backend. The tool should be run from it's own directory for now! This is the current output: (tail is what we want to know) rpython suggested primitives: ['ll_os_stat', 'll_math_floor', 'll_os_isatty', 'll_time_sleep', 'll_math_frexp', 'll_math_atan2', 'll_os_open', 'll_os_ftruncate', 'll_read_into', 'll_math_fmod', 'll_time_time', 'll_math_ceil', 'll_math_modf', 'll_os_write', 'll_os_lseek', 'll_time_clock', 'll_math_log10', 'll_os_dup', 'll_os_fstat', 'll_os_getcwd', 'll_os_close'] llvm implemented functions: ['ll_time_time', 'll_os_write', 'll_time_sleep', 'll_os_open', 'll_read_into', 'cast', 'll_time_clock', 'll_os_dup', 'll_os_close'] llvm missing primitives: ['ll_os_stat', 'll_math_floor', 'll_os_isatty', 'll_math_frexp', 'll_math_atan2', 'll_os_ftruncate', 'll_math_fmod', 'll_math_ceil', 'll_math_modf', 'll_os_lseek', 'll_math_log10', 'll_os_fstat', 'll_os_getcwd'] Added: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Mon Jul 25 19:50:32 2005 @@ -0,0 +1,42 @@ +#!/usr/bin/python + +import os + +def main(): + + ll_modules_path = '../../../rpython/module' + ll_files = [ll_modules_path + '/' + f for f in os.listdir(ll_modules_path) if f[:3] == 'll_' and f[-3:] == '.py'] + ll_function = {} #XXX better use sets + for ll_file in ll_files: + for s in file(ll_file): + s = s.strip() + if not s.startswith('ll_') or s.find('suggested_primitive') == -1 or s.find('True') == -1: + continue + ll_function[s.split('.')[0]] = True + + llvm_modules_path = '..' + llvm_files = [llvm_modules_path + '/' + 'extfunction.py'] + llvm_function = {} + for llvm_file in llvm_files: + t = 'extfunctions["%' + for s in file(llvm_file): + s = s.strip() + if not s.startswith(t): + continue + llvm_function[s.split('"')[1][1:]] = True + + print 'rpython suggested primitives:' + print ll_function.keys() + print + + print 'llvm implemented functions:' + print llvm_function.keys() + print + + print 'llvm missing primitives:' + missing_functions = [func for func in ll_function.keys() if func not in llvm_function] + print missing_functions + print + +if __name__ == '__main__': + main() From hpk at codespeak.net Mon Jul 25 20:04:22 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 20:04:22 +0200 (CEST) Subject: [pypy-svn] r15070 - in pypy/dist/pypy/lib: . test2 Message-ID: <20050725180422.A8D9927B5A@code1.codespeak.net> Author: hpk Date: Mon Jul 25 20:04:21 2005 New Revision: 15070 Modified: pypy/dist/pypy/lib/_file.py pypy/dist/pypy/lib/test2/test_file_extra.py Log: (rxe,hpk) change file's 'buffering'argname to cpython's name Modified: pypy/dist/pypy/lib/_file.py ============================================================================== --- pypy/dist/pypy/lib/_file.py (original) +++ pypy/dist/pypy/lib/_file.py Mon Jul 25 20:04:21 2005 @@ -78,22 +78,22 @@ Note: open() is an alias for file(). """ - def __init__(self, name, mode='r', bufsize=None): + def __init__(self, name, mode='r', buffering=None): self.fd = None self._name = name - self._inithelper(mode, bufsize) + self._inithelper(mode, buffering) - def fdopen(cls, fd, mode='r', bufsize=None): + def fdopen(cls, fd, mode='r', buffering=None): f = cls.__new__(cls) f.fd = fd f._name = "" - f._inithelper(mode, bufsize) + f._inithelper(mode, buffering) return f fdopen = classmethod(fdopen) - def _inithelper(self, mode, bufsize): + def _inithelper(self, mode, buffering): self._mode = mode if not mode or mode[0] not in ['r', 'w', 'a', 'U']: raise IOError('invalid mode : %s' % mode) @@ -139,21 +139,21 @@ self.stream = _sio.DiskFile(self.fd) self._closed = False - if bufsize == 0: # no buffering + if buffering == 0: # no buffering pass - elif bufsize == 1: # line-buffering + elif buffering == 1: # line-buffering if writing: self.stream = _sio.LineBufferingOutputStream(self.stream) if reading: self.stream = _sio.BufferingInputStream(self.stream) else: # default or explicit buffer sizes - if bufsize is not None and bufsize < 0: - bufsize = None + if buffering is not None and buffering < 0: + buffering = None if writing: - self.stream = _sio.BufferingOutputStream(self.stream, bufsize) + self.stream = _sio.BufferingOutputStream(self.stream, buffering) if reading: - self.stream = _sio.BufferingInputStream(self.stream, bufsize) + self.stream = _sio.BufferingInputStream(self.stream, buffering) if universal: # Wants universal newlines if writing and os.linesep != '\n': Modified: pypy/dist/pypy/lib/test2/test_file_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_file_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_file_extra.py Mon Jul 25 20:04:21 2005 @@ -5,7 +5,7 @@ class TestFile: def setup_method(self, method): - self.file = _file.file(__file__, 'r') + self.file = _file.file(__file__, 'r', buffering=None) def teardown_method(self, method): self.file.close() From rxe at codespeak.net Mon Jul 25 20:25:22 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Mon, 25 Jul 2005 20:25:22 +0200 (CEST) Subject: [pypy-svn] r15072 - in pypy/dist/pypy: objspace/std/test tool Message-ID: <20050725182522.6ADDB27B47@code1.codespeak.net> Author: rxe Date: Mon Jul 25 20:25:19 2005 New Revision: 15072 Added: pypy/dist/pypy/objspace/std/test/test_nonfakefile.py Modified: pypy/dist/pypy/tool/option.py Log: Make sys.stdout and friends use non faked version of file. (hpk/rxe) Added: pypy/dist/pypy/objspace/std/test/test_nonfakefile.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/std/test/test_nonfakefile.py Mon Jul 25 20:25:19 2005 @@ -0,0 +1,24 @@ + +import autopath +from pypy.tool.udir import udir +import py +import sys + +pypypath = str(py.path.local(autopath.pypydir).join('bin', 'py.py')) + +def test_nonfake_stdfile(): + """ """ + uselibfile = udir.join('uselibfile.py') + uselibfile.write("""if 1: + import sys + assert not _isfake(sys.stdin) + assert not _isfake(sys.stdout) + assert not _isfake(sys.stderr) + assert not _isfake(sys.__stdin__) + assert not _isfake(sys.__stdout__) + assert not _isfake(sys.__stderr__) + print "ok" + """) + output = py.process.cmdexec( '''"%s" "%s" --file "%s"''' % + (sys.executable, pypypath, uselibfile) ) + assert output.splitlines()[-1] == "ok" Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Mon Jul 25 20:25:19 2005 @@ -92,5 +92,19 @@ space.appexec([], '''(): from _file import file __builtins__.file = __builtins__.open = file + import sys + sys.stdout = file.fdopen(sys.stdout.fileno(), + sys.stdout.mode, + buffering=1) + sys.stdin = file.fdopen(sys.stdin.fileno(), + sys.stdin.mode, + buffering=1) + sys.stderr = file.fdopen(sys.stderr.fileno(), + sys.stderr.mode, + buffering=0) + sys.__stdout__ = sys.stdout + sys.__stderr__ = sys.stderr + sys.__stdin__ = sys.stdin ''') + return _spacecache.setdefault(name, space) From tismer at codespeak.net Mon Jul 25 20:37:08 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 25 Jul 2005 20:37:08 +0200 (CEST) Subject: [pypy-svn] r15074 - pypy/dist/pypy/objspace/std Message-ID: <20050725183708.2EE8827B4E@code1.codespeak.net> Author: tismer Date: Mon Jul 25 20:37:06 2005 New Revision: 15074 Modified: pypy/dist/pypy/objspace/std/floatobject.py Log: ensure that hash(float) wrapps into integer Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Mon Jul 25 20:37:06 2005 @@ -1,7 +1,7 @@ from pypy.objspace.std.objspace import * from pypy.interpreter import gateway from pypy.objspace.std.noneobject import W_NoneObject -from pypy.rpython.rarithmetic import ovfcheck_float_to_int +from pypy.rpython.rarithmetic import ovfcheck_float_to_int, intmask ############################################################## # for the time being, all calls that are made to some external @@ -152,7 +152,7 @@ v *= 2147483648.0 # 2**31 hipart = int(v) # take the top 32 bits v = (v - hipart) * 2147483648.0 # get the next 32 bits - x = hipart + int(v) + (expo << 15) + x = intmask(hipart + int(v) + (expo << 15)) return x From pedronis at codespeak.net Mon Jul 25 20:38:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 25 Jul 2005 20:38:13 +0200 (CEST) Subject: [pypy-svn] r15075 - pypy/dist/pypy/rpython Message-ID: <20050725183813.9AC7327B4E@code1.codespeak.net> Author: pedronis Date: Mon Jul 25 20:38:12 2005 New Revision: 15075 Modified: pypy/dist/pypy/rpython/llinterp.py Log: oops, missing return, avoid infinite recursion Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jul 25 20:38:12 2005 @@ -187,7 +187,7 @@ def op_direct_call(self, f, *args): has_callable = getattr(f._obj, '_callable', None) is not None if has_callable and getattr(f._obj._callable, 'suggested_primitive', False): - self.invoke_callable_with_pyexceptions(f, *args) + return self.invoke_callable_with_pyexceptions(f, *args) if hasattr(f._obj, 'graph'): graph = f._obj.graph else: From ericvrp at codespeak.net Mon Jul 25 21:00:51 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 25 Jul 2005 21:00:51 +0200 (CEST) Subject: [pypy-svn] r15077 - pypy/dist/pypy/translator/llvm2/tool Message-ID: <20050725190051.E0BEF27B53@code1.codespeak.net> Author: ericvrp Date: Mon Jul 25 21:00:51 2005 New Revision: 15077 Added: pypy/dist/pypy/translator/llvm2/tool/autopath.py Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Log: Followed Christians suggestions, code more r0obust now. Does not need to be run from it's own dir.. Added: pypy/dist/pypy/translator/llvm2/tool/autopath.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/tool/autopath.py Mon Jul 25 21:00:51 2005 @@ -0,0 +1,117 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories don't have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.realpath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + break + else: + raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + + checkpaths = sys.path[:] + pypy_root = os.path.join(head, '') + + while checkpaths: + orig = checkpaths.pop() + fullorig = os.path.join(os.path.realpath(orig), '') + if fullorig.startswith(pypy_root): + if os.path.exists(os.path.join(fullorig, '__init__.py')): + sys.path.remove(orig) + if head not in sys.path: + sys.path.insert(0, head) + + munged = {} + for name, mod in sys.modules.items(): + fn = getattr(mod, '__file__', None) + if '.' in name or not isinstance(fn, str): + continue + newname = os.path.splitext(os.path.basename(fn))[0] + if not newname.startswith(part + '.'): + continue + path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') + if path.startswith(pypy_root) and newname != part: + modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) + if newname != '__init__': + modpaths.append(newname) + modpath = '.'.join(modpaths) + if modpath not in sys.modules: + munged[modpath] = mod + + for name, mod in munged.iteritems(): + if name not in sys.modules: + sys.modules[name] = mod + if '.' in name: + prename = name[:name.rfind('.')] + postname = name[len(prename)+1:] + if prename not in sys.modules: + __import__(prename) + if not hasattr(sys.modules[prename], postname): + setattr(sys.modules[prename], postname, mod) + + return partdir, this_dir + +def __clone(): + """ clone master version of autopath.py into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f = open(fn, 'w') + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (original) +++ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Mon Jul 25 21:00:51 2005 @@ -1,42 +1,28 @@ #!/usr/bin/python +import autopath import os +from pypy.rpython.module import ll_os, ll_os_path, ll_time, ll_math #XXX keep this list up-to-date +from pypy.translator.llvm2.extfunction import extfunctions + def main(): + suggested_primitives = [] + for module in (ll_os, ll_os_path, ll_time, ll_math): #XXX keep this list up-to-date too + suggested_primitives += [func for func in dir(module) if getattr(module.__dict__[func], 'suggested_primitive', False)] + + implemented_primitives = [f[1:] for f in extfunctions.keys()] - ll_modules_path = '../../../rpython/module' - ll_files = [ll_modules_path + '/' + f for f in os.listdir(ll_modules_path) if f[:3] == 'll_' and f[-3:] == '.py'] - ll_function = {} #XXX better use sets - for ll_file in ll_files: - for s in file(ll_file): - s = s.strip() - if not s.startswith('ll_') or s.find('suggested_primitive') == -1 or s.find('True') == -1: - continue - ll_function[s.split('.')[0]] = True - - llvm_modules_path = '..' - llvm_files = [llvm_modules_path + '/' + 'extfunction.py'] - llvm_function = {} - for llvm_file in llvm_files: - t = 'extfunctions["%' - for s in file(llvm_file): - s = s.strip() - if not s.startswith(t): - continue - llvm_function[s.split('"')[1][1:]] = True + missing_primitives = [func for func in suggested_primitives if func not in implemented_primitives] print 'rpython suggested primitives:' - print ll_function.keys() + print suggested_primitives print - - print 'llvm implemented functions:' - print llvm_function.keys() + print 'llvm implemented primitives:' + print implemented_primitives print - print 'llvm missing primitives:' - missing_functions = [func for func in ll_function.keys() if func not in llvm_function] - print missing_functions - print + print missing_primitives if __name__ == '__main__': main() From pedronis at codespeak.net Mon Jul 25 21:03:50 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 25 Jul 2005 21:03:50 +0200 (CEST) Subject: [pypy-svn] r15078 - pypy/dist/pypy/rpython/test Message-ID: <20050725190350.DF69B27B53@code1.codespeak.net> Author: pedronis Date: Mon Jul 25 21:03:50 2005 New Revision: 15078 Modified: pypy/dist/pypy/rpython/test/test_rarithmetic.py Log: code changed, update 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 Mon Jul 25 21:03:50 2005 @@ -245,9 +245,9 @@ # strange things happening for float to int on 64 bit maxint32 = 2 ** 31 - 1 assert ovfcheck_float_to_int(float(maxint32-1)) == maxint32-1 - assert ovfcheck_float_to_int(float(maxint32)) == maxint32 + #assert ovfcheck_float_to_int(float(maxint32)) == maxint32 assert ovfcheck_float_to_int(float(-maxint32)) == -maxint32 - assert ovfcheck_float_to_int(float(-maxint32-1)) == -maxint32-1 + #assert ovfcheck_float_to_int(float(-maxint32-1)) == -maxint32-1 try: ovfcheck_float_to_int(float(-sys.maxint-1)-1) From hpk at codespeak.net Mon Jul 25 21:13:36 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 21:13:36 +0200 (CEST) Subject: [pypy-svn] r15080 - in pypy/dist/pypy: objspace/std tool translator/goal Message-ID: <20050725191336.CDCCA27B55@code1.codespeak.net> Author: hpk Date: Mon Jul 25 21:13:35 2005 New Revision: 15080 Modified: pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: (rxe,hpk) - move unfaking of files to the stdobjspace - targetpypymain.py now does unfaking of files by default Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Mon Jul 25 21:13:35 2005 @@ -124,6 +124,28 @@ self.w_classobj = w_classobj self.w_instance = w_instance + def unfakefile(self): + """ NOT_RPYTHON use our application level file implementation + including re-wrapping sys.stdout/err/in + """ + self.appexec([], '''(): + from _file import file + __builtins__.file = __builtins__.open = file + import sys + sys.stdout = file.fdopen(sys.stdout.fileno(), + sys.stdout.mode, + buffering=1) + sys.stdin = file.fdopen(sys.stdin.fileno(), + sys.stdin.mode, + buffering=1) + sys.stderr = file.fdopen(sys.stderr.fileno(), + sys.stderr.mode, + buffering=0) + sys.__stdout__ = sys.stdout + sys.__stderr__ = sys.stderr + sys.__stdin__ = sys.stdin + ''') + def setup_exceptions(self): """NOT_RPYTHON""" ## hacking things in @@ -233,6 +255,7 @@ w_result = self.wrap_exception_cls(x) if w_result is not None: return w_result + #print "fake-wrapping", x from fake import fake_object return fake_object(self, x) Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Mon Jul 25 21:13:35 2005 @@ -89,22 +89,6 @@ if name == 'std' and Options.oldstyle: space.enable_old_style_classes_as_default_metaclass() if Options.uselibfile: - space.appexec([], '''(): - from _file import file - __builtins__.file = __builtins__.open = file - import sys - sys.stdout = file.fdopen(sys.stdout.fileno(), - sys.stdout.mode, - buffering=1) - sys.stdin = file.fdopen(sys.stdin.fileno(), - sys.stdin.mode, - buffering=1) - sys.stderr = file.fdopen(sys.stderr.fileno(), - sys.stderr.mode, - buffering=0) - sys.__stdout__ = sys.stdout - sys.__stderr__ = sys.stderr - sys.__stdin__ = sys.stdin - ''') + space.unfakefile() return _spacecache.setdefault(name, space) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Mon Jul 25 21:13:35 2005 @@ -39,6 +39,7 @@ gateway.ApplevelClass.use_geninterp = False space = StdObjSpace() + space.unfakefile() # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From hpk at codespeak.net Mon Jul 25 21:17:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 25 Jul 2005 21:17:58 +0200 (CEST) Subject: [pypy-svn] r15081 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050725191758.E4E7627B54@code1.codespeak.net> Author: hpk Date: Mon Jul 25 21:17:58 2005 New Revision: 15081 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: don't implicitely use default arg (thanks pedronis) Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Mon Jul 25 21:17:58 2005 @@ -201,7 +201,7 @@ def imp_execfile(space, fn, w_globals, w_locals): - fd = os.open(fn, os.O_RDONLY) # XXX newlines? + fd = os.open(fn, os.O_RDONLY, 0777) # XXX newlines? try: size = os.fstat(fd)[6] source = os.read(fd, size) From cfbolz at codespeak.net Tue Jul 26 00:02:54 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 00:02:54 +0200 (CEST) Subject: [pypy-svn] r15083 - pypy/dist/pypy/rpython/module Message-ID: <20050725220254.955E727B51@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 00:02:53 2005 New Revision: 15083 Modified: pypy/dist/pypy/rpython/module/ll_os_path.py Log: (pedronis, cfbolz) trying to fix os.path.exists. still failing tests 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 Tue Jul 26 00:02:53 2005 @@ -7,15 +7,25 @@ import os from pypy.rpython.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 # Does a path exist? # This is false for dangling symbolic links. +## This version produces nonsense, keeping it for reference +## def ll_os_path_exists(path): +## """Test whether a path exists""" +## try: +## st = os.stat(from_rstr(path)) +## except OSError: +## return False +## return True + def ll_os_path_exists(path): """Test whether a path exists""" try: - st = os.stat(from_rstr(path)) + st = ll_os_stat(path) except OSError: return False return True + From arigo at codespeak.net Tue Jul 26 09:41:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 09:41:16 +0200 (CEST) Subject: [pypy-svn] r15086 - pypy/dist/pypy/lib Message-ID: <20050726074116.9694D27B5B@code1.codespeak.net> Author: arigo Date: Tue Jul 26 09:41:13 2005 New Revision: 15086 Modified: pypy/dist/pypy/lib/marshal.py Log: Raise ValueError instead of AssertionError for marshal.dump() Modified: pypy/dist/pypy/lib/marshal.py ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Tue Jul 26 09:41:13 2005 @@ -83,7 +83,8 @@ dispatch[bool] = dump_bool def dump_stopiter(self, x): - assert x is StopIteration + if x is not StopIteration: + raise ValueError, "unmarshallable object" self.f.write(TYPE_STOPITER) dispatch[type(StopIteration)] = dump_stopiter From arigo at codespeak.net Tue Jul 26 10:08:56 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 10:08:56 +0200 (CEST) Subject: [pypy-svn] r15087 - in pypy/dist/pypy: interpreter lib lib/test2 module/marshal module/marshal/test tool translator Message-ID: <20050726080856.A247227B56@code1.codespeak.net> Author: arigo Date: Tue Jul 26 10:08:45 2005 New Revision: 15087 Added: pypy/dist/pypy/module/marshal/ (props changed) pypy/dist/pypy/module/marshal/__init__.py (contents, props changed) pypy/dist/pypy/module/marshal/app_marshal.py - copied, changed from r15086, pypy/dist/pypy/lib/marshal.py pypy/dist/pypy/module/marshal/test/ (props changed) pypy/dist/pypy/module/marshal/test/autopath.py - copied unchanged from r15085, pypy/dist/pypy/module/sys/test/autopath.py pypy/dist/pypy/module/marshal/test/test_marshal_extra.py - copied, changed from r15085, pypy/dist/pypy/lib/test2/test_marshal_extra.py Removed: pypy/dist/pypy/lib/marshal.py pypy/dist/pypy/lib/test2/test_marshal_extra.py Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/geninterplevel.py Log: - moved marshal to a mixed module. - a few changes to geninterplevel to support it. - an option --compile="pyparseapp" to call the stablecompiler pure Python package at app-level (to be done!). Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jul 26 10:08:45 2005 @@ -149,6 +149,7 @@ # XXX we need to resolve unwrapping issues to # make this the default _sre module #self.setbuiltinmodule("_sre", "_sre_pypy") + self.setbuiltinmodule('marshal') if self.options.useparsermodule == "recparser": self.setbuiltinmodule('parser', 'recparser') elif self.options.useparsermodule == "parser": @@ -196,6 +197,8 @@ return PythonCompiler(self) elif self.options.compiler == 'cpython': return CPythonCompiler(self) + elif self.options.compiler == 'pyparseapp': + return PythonCompilerApp(self) else: raise ValueError('unknown --compiler option value: %r' % ( self.options.compiler,)) Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Tue Jul 26 10:08:45 2005 @@ -238,6 +238,39 @@ compile_parse_result._annspecialcase_ = 'override:cpy_stablecompiler' +##class PythonCompilerApp(PythonCompiler): +## """Temporary. Calls the stablecompiler package at app-level.""" + +## def __init__(self, space): +## PythonCompiler.__init__(self, space) +## space.appexec(r'''(): +## # NOT_RPYTHON +## from pypy.interpreter import stablecompiler +## from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator +## from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator +## from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator +## from pypy.interpreter.stablecompiler.transformer import Transformer +## transformer = Transformer() +## tree = transformer.compile_node(tuples) +## stablecompiler.misc.set_filename(filename, tree) +## if mode == 'exec': +## codegenerator = ModuleCodeGenerator(tree) +## elif mode == 'single': +## codegenerator = InteractiveCodeGenerator(tree) +## else: # mode == 'eval': +## codegenerator = ExpressionCodeGenerator(tree) +## c = codegenerator.getCode() +## ''') + +## def compile_parse_result(self, parse_result, filename, mode): + + + + + + + + class PyPyCompiler(CPythonCompiler): """Uses the PyPy implementation of Compiler Deleted: /pypy/dist/pypy/lib/marshal.py ============================================================================== --- /pypy/dist/pypy/lib/marshal.py Tue Jul 26 10:08:45 2005 +++ (empty file) @@ -1,432 +0,0 @@ -"""Marshal module written in Python. - -This doesn't marshal code objects, but supports everything else. -Performance or careful error checking is not an issue. - -""" - -import StringIO -import string -from types import * -try: - import new -except ImportError: - new = None - -TYPE_NULL = '0' -TYPE_NONE = 'N' -TYPE_FALSE = 'F' -TYPE_TRUE = 'T' -TYPE_STOPITER = 'S' -TYPE_ELLIPSIS = '.' -TYPE_INT = 'i' -TYPE_INT64 = 'I' -TYPE_FLOAT = 'f' -TYPE_COMPLEX = 'x' -TYPE_LONG = 'l' -TYPE_STRING = 's' -TYPE_INTERNED = 't' -TYPE_STRINGREF= 'R' -TYPE_TUPLE = '(' -TYPE_LIST = '[' -TYPE_DICT = '{' -TYPE_CODE = 'c' -TYPE_UNICODE = 'u' -TYPE_UNKNOWN = '?' -TYPE_SET = '<' -TYPE_FROZENSET= '>' - -class Marshaller: - - dispatch = {} - - def __init__(self, f): - self.f = f - - def dump(self, x): - try: - self.dispatch[type(x)](self, x) - except KeyError: - for tp in type(x).mro(): - func = self.dispatch.get(tp) - if func: - break - else: - raise ValueError, "unmarshallable object" - func(self, x) - - def w_long64(self, x): - self.w_long(x) - self.w_long(x>>32) - - def w_long(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) - write(chr((x>>16) & 0xff)) - write(chr((x>>24) & 0xff)) - - def w_short(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) - - def dump_none(self, x): - self.f.write(TYPE_NONE) - dispatch[NoneType] = dump_none - - def dump_bool(self, x): - if x: - self.f.write(TYPE_TRUE) - else: - self.f.write(TYPE_FALSE) - dispatch[bool] = dump_bool - - def dump_stopiter(self, x): - if x is not StopIteration: - raise ValueError, "unmarshallable object" - self.f.write(TYPE_STOPITER) - dispatch[type(StopIteration)] = dump_stopiter - - def dump_ellipsis(self, x): - self.f.write(TYPE_ELLIPSIS) - - try: - dispatch[EllipsisType] = dump_ellipsis - except NameError: - pass - - def dump_int(self, x): - y = x>>31 - if y and y != -1: - self.f.write(TYPE_INT64) - self.w_long64(x) - else: - self.f.write(TYPE_INT) - self.w_long(x) - dispatch[IntType] = dump_int - - def dump_long(self, x): - self.f.write(TYPE_LONG) - sign = 1 - if x < 0: - sign = -1 - x = -x - digits = [] - while x: - digits.append(x & 0x7FFF) - x = x>>15 - self.w_long(len(digits) * sign) - for d in digits: - self.w_short(d) - dispatch[LongType] = dump_long - - def dump_float(self, x): - write = self.f.write - write(TYPE_FLOAT) - s = `x` - write(chr(len(s))) - write(s) - dispatch[FloatType] = dump_float - - def dump_complex(self, x): - write = self.f.write - write(TYPE_COMPLEX) - s = `x.real` - write(chr(len(s))) - write(s) - s = `x.imag` - write(chr(len(s))) - write(s) - try: - dispatch[ComplexType] = dump_complex - except NameError: - pass - - def dump_string(self, x): - # XXX we can't check for interned strings, yet, - # so we (for now) never create TYPE_INTERNED or TYPE_STRINGREF - self.f.write(TYPE_STRING) - self.w_long(len(x)) - self.f.write(x) - dispatch[StringType] = dump_string - - def dump_unicode(self, x): - self.f.write(TYPE_UNICODE) - s = x.encode('utf8') - self.w_long(len(s)) - self.f.write(s) - dispatch[UnicodeType] = dump_unicode - - def dump_tuple(self, x): - self.f.write(TYPE_TUPLE) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[TupleType] = dump_tuple - - def dump_list(self, x): - self.f.write(TYPE_LIST) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[ListType] = dump_list - - def dump_dict(self, x): - self.f.write(TYPE_DICT) - for key, value in x.items(): - self.dump(key) - self.dump(value) - self.f.write(TYPE_NULL) - dispatch[DictionaryType] = dump_dict - - def dump_code(self, x): - self.f.write(TYPE_CODE) - self.w_long(x.co_argcount) - self.w_long(x.co_nlocals) - self.w_long(x.co_stacksize) - self.w_long(x.co_flags) - self.dump(x.co_code) - self.dump(x.co_consts) - self.dump(x.co_names) - self.dump(x.co_varnames) - self.dump(x.co_freevars) - self.dump(x.co_cellvars) - self.dump(x.co_filename) - self.dump(x.co_name) - self.w_long(x.co_firstlineno) - self.dump(x.co_lnotab) - try: - dispatch[CodeType] = dump_code - except NameError: - pass - - def dump_set(self, x): - self.f.write(TYPE_SET) - self.w_long(len(x)) - for each in x: - self.dump(each) - try: - dispatch[set] = dump_set - except NameError: - pass - - def dump_frozenset(self, x): - self.f.write(TYPE_FROZENSET) - self.w_long(len(x)) - for each in x: - self.dump(each) - try: - dispatch[frozenset] = dump_frozenset - except NameError: - pass - -class NULL: - pass - -class Unmarshaller: - - dispatch = {} - - def __init__(self, f): - self.f = f - self._stringtable = [] - - def load(self): - c = self.f.read(1) - if not c: - raise EOFError - return self.dispatch[c](self) - - def r_short(self): - read = self.f.read - lo = ord(read(1)) - hi = ord(read(1)) - x = lo | (hi<<8) - if x & 0x8000: - x = x - 0x10000 - return x - - def r_long(self): - read = self.f.read - a = ord(read(1)) - b = ord(read(1)) - c = ord(read(1)) - d = ord(read(1)) - x = a | (b<<8) | (c<<16) | (d<<24) - if d & 0x80 and x > 0: - x = -((1L<<32) - x) - return x - - def r_long64(self): - read = self.f.read - a = ord(read(1)) - b = ord(read(1)) - c = ord(read(1)) - d = ord(read(1)) - e = long(ord(read(1))) - f = long(ord(read(1))) - g = long(ord(read(1))) - h = long(ord(read(1))) - x = a | (b<<8) | (c<<16) | (d<<24) - x = x | (e<<32) | (f<<40) | (g<<48) | (h<<56) - if h & 0x80 and x > 0: - x = -((1L<<64) - x) - return x - - def load_null(self): - return NULL - dispatch[TYPE_NULL] = load_null - - def load_none(self): - return None - dispatch[TYPE_NONE] = load_none - - def load_true(self): - return True - dispatch[TYPE_TRUE] = load_true - - def load_false(self): - return False - dispatch[TYPE_FALSE] = load_false - - def load_stopiter(self): - return StopIteration - dispatch[TYPE_STOPITER] = load_stopiter - - def load_ellipsis(self): - return Ellipsis - dispatch[TYPE_ELLIPSIS] = load_ellipsis - - def load_int(self): - return self.r_long() - dispatch[TYPE_INT] = load_int - - def load_int64(self): - return self.r_long64() - dispatch[TYPE_INT64] = load_int64 - - def load_long(self): - size = self.r_long() - sign = 1 - if size < 0: - sign = -1 - size = -size - x = 0L - for i in range(size): - d = self.r_short() - x = x | (d<<(i*15L)) - return x * sign - dispatch[TYPE_LONG] = load_long - - def load_float(self): - n = ord(self.f.read(1)) - s = self.f.read(n) - return string.atof(s) - dispatch[TYPE_FLOAT] = load_float - - def load_complex(self): - n = ord(self.f.read(1)) - s = self.f.read(n) - real = float(s) - n = ord(self.f.read(1)) - s = self.f.read(n) - imag = float(s) - return complex(real, imag) - dispatch[TYPE_COMPLEX] = load_complex - - def load_string(self): - n = self.r_long() - return self.f.read(n) - dispatch[TYPE_STRING] = load_string - - def load_interned(self): - n = self.r_long() - ret = intern(self.f.read(n)) - self._stringtable.append(ret) - return ret - dispatch[TYPE_INTERNED] = load_interned - - def load_stringref(self): - n = self.r_long() - return self._stringtable[n] - dispatch[TYPE_STRINGREF] = load_stringref - - def load_unicode(self): - n = self.r_long() - s = self.f.read(n) - ret = s.decode('utf8') - return ret - dispatch[TYPE_UNICODE] = load_unicode - - def load_tuple(self): - return tuple(self.load_list()) - dispatch[TYPE_TUPLE] = load_tuple - - def load_list(self): - n = self.r_long() - list = [] - for i in range(n): - list.append(self.load()) - return list - dispatch[TYPE_LIST] = load_list - - def load_dict(self): - d = {} - while 1: - key = self.load() - if key is NULL: - break - value = self.load() - d[key] = value - return d - dispatch[TYPE_DICT] = load_dict - - def load_code(self): - argcount = self.r_long() - nlocals = self.r_long() - stacksize = self.r_long() - flags = self.r_long() - code = self.load() - consts = self.load() - names = self.load() - varnames = self.load() - freevars = self.load() - cellvars = self.load() - filename = self.load() - name = self.load() - firstlineno = self.r_long() - lnotab = self.load() - if not new: - raise RuntimeError, "can't unmarshal code objects; no 'new' module" - return new.code(argcount, nlocals, stacksize, flags, code, consts, - names, varnames, filename, name, firstlineno, lnotab, - freevars, cellvars) - dispatch[TYPE_CODE] = load_code - - def load_set(self): - n = self.r_long() - args = [self.load() for i in range(n)] - return set(args) - dispatch[TYPE_SET] = load_set - - def load_frozenset(self): - n = self.r_long() - args = [self.load() for i in range(n)] - return frozenset(args) - dispatch[TYPE_FROZENSET] = load_frozenset - -def dump(x, f): - Marshaller(f).dump(x) - -def load(f): - return Unmarshaller(f).load() - -def dumps(x): - f = StringIO.StringIO() - dump(x, f) - return f.getvalue() - -def loads(s): - f = StringIO.StringIO(s) - return load(f) Deleted: /pypy/dist/pypy/lib/test2/test_marshal_extra.py ============================================================================== --- /pypy/dist/pypy/lib/test2/test_marshal_extra.py Tue Jul 26 10:08:45 2005 +++ (empty file) @@ -1,89 +0,0 @@ -import sys -import marshal as cpy_marshal -from pypy.lib import marshal - -hello = "he" -hello += "llo" -def func(x): - return lambda y: x+y -scopefunc = func(42) - -TESTCASES = [ - None, - False, - True, - StopIteration, - Ellipsis, - 42, - sys.maxint, - -1.25, - 2+5j, - 42L, - -1234567890123456789012345678901234567890L, - hello, # not interned - "hello", - (), - (1, 2), - [], - [3, 4], - {}, - {5: 6, 7: 8}, - func.func_code, - scopefunc.func_code, - u'hello', - ] - -try: - TESTCASES += [ - set(), - set([1, 2]), - frozenset(), - frozenset([3, 4]), - ] -except NameError: - pass # Python < 2.4 - - -def test_cases(): - for case in TESTCASES: - yield dump_and_reload, case - yield load_from_cpython, case - yield dump_to_cpython, case - yield dump_subclass, case - -def dump_and_reload(case): - print 'dump_and_reload', `case` - s = marshal.dumps(case) - obj = marshal.loads(s) - assert obj == case - -def load_from_cpython(case): - print 'load_from_cpython', `case` - try: - s = cpy_marshal.dumps(case) - except ValueError: - return # this version of CPython doesn't support this object - obj = marshal.loads(s) - assert obj == case - -def dump_to_cpython(case): - print 'dump_to_cpython', `case` - try: - cpy_marshal.dumps(case) - except ValueError: - return # this version of CPython doesn't support this object - s = marshal.dumps(case) - obj = cpy_marshal.loads(s) - assert obj == case - -def dump_subclass(case): - try: - class Subclass(type(case)): - pass - case = Subclass(case) - except TypeError: - return - print 'dump_subclass', `case` - s = marshal.dumps(case) - obj = marshal.loads(s) - assert obj == case Added: pypy/dist/pypy/module/marshal/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/marshal/__init__.py Tue Jul 26 10:08:45 2005 @@ -0,0 +1,16 @@ +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + """Internal Python object serialization + +This module contains functions that can read and write Python values in a binary format. The format is specific to Python, but independent of machine architecture issues (e.g., you can write a Python value to a file on a PC, transport the file to a Sun, and read it back there). Details of the format may change between Python versions.""" + + appleveldefs = { + 'dump' : 'app_marshal.dump', + 'dumps' : 'app_marshal.dumps', + 'load' : 'app_marshal.load', + 'loads' : 'app_marshal.loads', + } + + interpleveldefs = { + } Copied: pypy/dist/pypy/module/marshal/app_marshal.py (from r15086, pypy/dist/pypy/lib/marshal.py) ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 10:08:45 2005 @@ -1,13 +1,9 @@ """Marshal module written in Python. - -This doesn't marshal code objects, but supports everything else. -Performance or careful error checking is not an issue. - """ import StringIO import string -from types import * +import types try: import new except ImportError: @@ -73,7 +69,7 @@ def dump_none(self, x): self.f.write(TYPE_NONE) - dispatch[NoneType] = dump_none + dispatch[types.NoneType] = dump_none def dump_bool(self, x): if x: @@ -92,7 +88,7 @@ self.f.write(TYPE_ELLIPSIS) try: - dispatch[EllipsisType] = dump_ellipsis + dispatch[types.EllipsisType] = dump_ellipsis except NameError: pass @@ -104,7 +100,7 @@ else: self.f.write(TYPE_INT) self.w_long(x) - dispatch[IntType] = dump_int + dispatch[types.IntType] = dump_int def dump_long(self, x): self.f.write(TYPE_LONG) @@ -119,7 +115,7 @@ self.w_long(len(digits) * sign) for d in digits: self.w_short(d) - dispatch[LongType] = dump_long + dispatch[types.LongType] = dump_long def dump_float(self, x): write = self.f.write @@ -127,7 +123,7 @@ s = `x` write(chr(len(s))) write(s) - dispatch[FloatType] = dump_float + dispatch[types.FloatType] = dump_float def dump_complex(self, x): write = self.f.write @@ -139,7 +135,7 @@ write(chr(len(s))) write(s) try: - dispatch[ComplexType] = dump_complex + dispatch[types.ComplexType] = dump_complex except NameError: pass @@ -149,28 +145,28 @@ self.f.write(TYPE_STRING) self.w_long(len(x)) self.f.write(x) - dispatch[StringType] = dump_string + dispatch[types.StringType] = dump_string def dump_unicode(self, x): self.f.write(TYPE_UNICODE) s = x.encode('utf8') self.w_long(len(s)) self.f.write(s) - dispatch[UnicodeType] = dump_unicode + dispatch[types.UnicodeType] = dump_unicode def dump_tuple(self, x): self.f.write(TYPE_TUPLE) self.w_long(len(x)) for item in x: self.dump(item) - dispatch[TupleType] = dump_tuple + dispatch[types.TupleType] = dump_tuple def dump_list(self, x): self.f.write(TYPE_LIST) self.w_long(len(x)) for item in x: self.dump(item) - dispatch[ListType] = dump_list + dispatch[types.ListType] = dump_list def dump_dict(self, x): self.f.write(TYPE_DICT) @@ -178,7 +174,7 @@ self.dump(key) self.dump(value) self.f.write(TYPE_NULL) - dispatch[DictionaryType] = dump_dict + dispatch[types.DictionaryType] = dump_dict def dump_code(self, x): self.f.write(TYPE_CODE) @@ -197,7 +193,7 @@ self.w_long(x.co_firstlineno) self.dump(x.co_lnotab) try: - dispatch[CodeType] = dump_code + dispatch[types.CodeType] = dump_code except NameError: pass @@ -416,6 +412,13 @@ return frozenset(args) dispatch[TYPE_FROZENSET] = load_frozenset +try: + set +except NameError: + def set(x): + raise ValueError("cannot unmarshal set objects on Python < 2.4") + frozenset = set + def dump(x, f): Marshaller(f).dump(x) Copied: pypy/dist/pypy/module/marshal/test/test_marshal_extra.py (from r15085, pypy/dist/pypy/lib/test2/test_marshal_extra.py) ============================================================================== --- pypy/dist/pypy/lib/test2/test_marshal_extra.py (original) +++ pypy/dist/pypy/module/marshal/test/test_marshal_extra.py Tue Jul 26 10:08:45 2005 @@ -1,6 +1,7 @@ +import autopath import sys import marshal as cpy_marshal -from pypy.lib import marshal +from pypy.module.marshal import app_marshal as marshal hello = "he" hello += "llo" Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Tue Jul 26 10:08:45 2005 @@ -12,7 +12,8 @@ uselibfile = 0 useparsermodule = "recparser" # "cpython" / "recparser" / "parser" compiler = "pyparse" # "cpython" - # "pyparse" pypy parser, cpython compiler + # "pyparse" pypy parser, cpython's compiler package + # "pyparseapp" same, running the compiler at app-level # "pycomp" pypy parser and compiler (TBD) version = "2.4" # "native" / "2.3" / "2.4" @@ -47,7 +48,7 @@ options.append(make_option( '--compiler', action="store", type="string", dest="compiler", help="select the parser/compiler to use internally", - metavar="[cpython|pyparse]")) + metavar="[cpython|pyparse|pyparseapp]")) options.append(make_option( '--parsermodule', action="store",type="string", dest="useparsermodule", help="select the parser module to use", Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Tue Jul 26 10:08:45 2005 @@ -77,7 +77,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.3' # bump this for substantial changes +GI_VERSION = '1.1.4' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): @@ -747,9 +747,9 @@ str: 'space.w_str', float: 'space.w_float', slice: 'space.w_slice', - type(Exception()): 'space.wrap(types.InstanceType)', + type(Exception()): (eval_helper, 'InstanceType', 'types.InstanceType'), type: 'space.w_type', - complex:'space.wrap(types.ComplexType)', + complex: (eval_helper, 'complex', 'types.ComplexType'), unicode:'space.w_unicode', basestring: (eval_helper, 'basestring', 'basestring'), file: (eval_helper, 'file', 'file'), @@ -785,6 +785,7 @@ types.MethodType: (eval_helper, "instancemethod", "type((lambda:42).__get__(42))"), property: (eval_helper, "property", 'property'), + type(Ellipsis): (eval_helper, 'EllipsisType', 'types.EllipsisType'), } def nameof_type(self, cls): From arigo at codespeak.net Tue Jul 26 10:09:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 10:09:39 +0200 (CEST) Subject: [pypy-svn] r15088 - in pypy/dist/pypy/module: __builtin__ __builtin__/test posix recparser recparser/compiler Message-ID: <20050726080939.B830E27B56@code1.codespeak.net> Author: arigo Date: Tue Jul 26 10:09:09 2005 New Revision: 15088 Modified: pypy/dist/pypy/module/__builtin__/app_sets.py (props changed) pypy/dist/pypy/module/__builtin__/special.py (props changed) pypy/dist/pypy/module/__builtin__/test/test_special.py (props changed) pypy/dist/pypy/module/posix/app_posix.py (props changed) pypy/dist/pypy/module/recparser/app_class.py (props changed) pypy/dist/pypy/module/recparser/codegen.py (props changed) pypy/dist/pypy/module/recparser/compiler/ (props changed) pypy/dist/pypy/module/recparser/compiler/__init__.py (props changed) pypy/dist/pypy/module/recparser/compiler/ast.py (props changed) pypy/dist/pypy/module/recparser/compiler/ast.txt (props changed) pypy/dist/pypy/module/recparser/compiler/astfactory.py (props changed) pypy/dist/pypy/module/recparser/compiler/astgen.py (props changed) pypy/dist/pypy/module/recparser/compiler/bytecode.py (props changed) pypy/dist/pypy/module/recparser/compiler/consts.py (props changed) pypy/dist/pypy/module/recparser/compiler/future.py (props changed) pypy/dist/pypy/module/recparser/compiler/misc.py (props changed) pypy/dist/pypy/module/recparser/compiler/pyassem.py (props changed) pypy/dist/pypy/module/recparser/compiler/pycodegen.py (props changed) pypy/dist/pypy/module/recparser/compiler/symbols.py (props changed) pypy/dist/pypy/module/recparser/compiler/syntax.py (props changed) pypy/dist/pypy/module/recparser/compiler/transformer.py (props changed) pypy/dist/pypy/module/recparser/compiler/visitor.py (props changed) Log: fixeol From pedronis at codespeak.net Tue Jul 26 10:13:24 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 26 Jul 2005 10:13:24 +0200 (CEST) Subject: [pypy-svn] r15089 - pypy/dist/pypy/translator/c/test Message-ID: <20050726081324.C444627B56@code1.codespeak.net> Author: pedronis Date: Tue Jul 26 10:13:23 2005 New Revision: 15089 Modified: pypy/dist/pypy/translator/c/test/test_exception.py Log: skip this test until we figure out what we want Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Tue Jul 26 10:13:23 2005 @@ -6,6 +6,7 @@ pass def test_simple2(): #taken from ../../llvm2/test/test_exception.py + py.test.skip("decided whethe we want to support IndexError on [] at interp-level") def fn(n): lst = range(10) try: From pedronis at codespeak.net Tue Jul 26 10:56:38 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 26 Jul 2005 10:56:38 +0200 (CEST) Subject: [pypy-svn] r15090 - pypy/extradoc/sprintinfo Message-ID: <20050726085638.2734227B5B@code1.codespeak.net> Author: pedronis Date: Tue Jul 26 10:56:37 2005 New Revision: 15090 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: update with planning for today and what was done yesterday Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Tue Jul 26 10:56:37 2005 @@ -28,18 +28,60 @@ * -> TRACKER write a tool that discovers which revision of the pypy tree broke the high level annotator (in that it produced SomeObjects). - Consider distributing the actual annotation to multiple hosts. + Consider distributing the actual annotation to multiple hosts. (holger) * -> TRACKER: (mostly done) add missing docstrings on app-level built-in types and functions, etc. (Laura): there now is a program that generates the docstrings into the appropriate places but it needs prettification. + (christian) Current Main task: RTYPER issues ----------------------------------- +- do we want to continue to work with the snapshsot? does it make sense + during the sprint? + decision: during the sprint use directly the trunk, mail pypy-dev + about this (holger, samuele) + + - we want to work on pypy/translator/goal/ISSUES.txt -pairs: +pairs:: Samuele, Carl Friedrich (progressing on External functions) + DONE: refactored math and os function out of annotation/builtin and + rpython/rbuiltin into the extfunctable, implemented some + math.*, os.* functions. fixed os.stat + + Open issues: + - RPython string -> C null-terminated string + conversion. The null termination char is not there! + + - The flow space kills exception handling for built-ins, + this is not what we want e.g. for os.* functions; + decide new criteria. Maybe only for thing in __builtin__ + or list only the built-ins we want exception handling + suppressed. + + - finish os.path.exists and os.path.isdir support + + (Armin, Carl Friedrich) + + Armin, Christian (random RTyper problems) - richard, holger (random RTyper problems) + DONE: down to override:cpy_stablecompiler, + up to wrap/unwrap issues related to faking. + The hope is that we can get rid of faking. + + Completing marshal, made it into a mixed-module + that can be geinterped. + + Plan: enable pyc loading to bootstrap compiler + at app-level (Christian, Richard) + + Richard, Holger (getting rid of faked files) + DONE: importing uses only os.* functions at + interp-level. With --file option sys.std* + use our own app-level implementation of files. + --file is on by default now when translating + + From arigo at codespeak.net Tue Jul 26 11:33:29 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 11:33:29 +0200 (CEST) Subject: [pypy-svn] r15092 - in pypy/dist/pypy: annotation/test bin documentation/revreport interpreter interpreter/test module/__builtin__/test module/marshal/test module/sys/test objspace/flow/test objspace/std objspace/std/test objspace/test tool tool/pytest tool/test translator translator/c translator/c/test translator/goal translator/java translator/java/test translator/llvm2/tool translator/pyrex translator/pyrex/test translator/test translator/tool translator/tool/pygame Message-ID: <20050726093329.8472F27B60@code1.codespeak.net> Author: arigo Date: Tue Jul 26 11:33:23 2005 New Revision: 15092 Modified: pypy/dist/pypy/annotation/test/autopath.py pypy/dist/pypy/bin/autopath.py pypy/dist/pypy/documentation/revreport/autopath.py pypy/dist/pypy/interpreter/autopath.py pypy/dist/pypy/interpreter/test/autopath.py pypy/dist/pypy/module/__builtin__/test/autopath.py pypy/dist/pypy/module/marshal/test/autopath.py pypy/dist/pypy/module/sys/test/autopath.py pypy/dist/pypy/objspace/flow/test/autopath.py pypy/dist/pypy/objspace/std/autopath.py pypy/dist/pypy/objspace/std/test/autopath.py pypy/dist/pypy/objspace/test/autopath.py pypy/dist/pypy/tool/autopath.py pypy/dist/pypy/tool/pytest/autopath.py pypy/dist/pypy/tool/test/autopath.py pypy/dist/pypy/translator/autopath.py pypy/dist/pypy/translator/c/autopath.py pypy/dist/pypy/translator/c/test/autopath.py pypy/dist/pypy/translator/goal/autopath.py pypy/dist/pypy/translator/java/autopath.py pypy/dist/pypy/translator/java/test/autopath.py pypy/dist/pypy/translator/llvm2/tool/autopath.py pypy/dist/pypy/translator/pyrex/autopath.py pypy/dist/pypy/translator/pyrex/test/autopath.py pypy/dist/pypy/translator/test/autopath.py pypy/dist/pypy/translator/tool/autopath.py pypy/dist/pypy/translator/tool/pygame/autopath.py Log: Yet Another Autopath Fix (tm). Modified: pypy/dist/pypy/annotation/test/autopath.py ============================================================================== --- pypy/dist/pypy/annotation/test/autopath.py (original) +++ pypy/dist/pypy/annotation/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/bin/autopath.py ============================================================================== --- pypy/dist/pypy/bin/autopath.py (original) +++ pypy/dist/pypy/bin/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/documentation/revreport/autopath.py ============================================================================== --- pypy/dist/pypy/documentation/revreport/autopath.py (original) +++ pypy/dist/pypy/documentation/revreport/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/interpreter/autopath.py ============================================================================== --- pypy/dist/pypy/interpreter/autopath.py (original) +++ pypy/dist/pypy/interpreter/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/interpreter/test/autopath.py ============================================================================== --- pypy/dist/pypy/interpreter/test/autopath.py (original) +++ pypy/dist/pypy/interpreter/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/module/__builtin__/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/autopath.py (original) +++ pypy/dist/pypy/module/__builtin__/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/module/marshal/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/marshal/test/autopath.py (original) +++ pypy/dist/pypy/module/marshal/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/module/sys/test/autopath.py ============================================================================== --- pypy/dist/pypy/module/sys/test/autopath.py (original) +++ pypy/dist/pypy/module/sys/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/objspace/flow/test/autopath.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/autopath.py (original) +++ pypy/dist/pypy/objspace/flow/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/objspace/std/autopath.py ============================================================================== --- pypy/dist/pypy/objspace/std/autopath.py (original) +++ pypy/dist/pypy/objspace/std/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/objspace/std/test/autopath.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/autopath.py (original) +++ pypy/dist/pypy/objspace/std/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/objspace/test/autopath.py ============================================================================== --- pypy/dist/pypy/objspace/test/autopath.py (original) +++ pypy/dist/pypy/objspace/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/tool/autopath.py ============================================================================== --- pypy/dist/pypy/tool/autopath.py (original) +++ pypy/dist/pypy/tool/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/tool/pytest/autopath.py ============================================================================== --- pypy/dist/pypy/tool/pytest/autopath.py (original) +++ pypy/dist/pypy/tool/pytest/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/tool/test/autopath.py ============================================================================== --- pypy/dist/pypy/tool/test/autopath.py (original) +++ pypy/dist/pypy/tool/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/autopath.py ============================================================================== --- pypy/dist/pypy/translator/autopath.py (original) +++ pypy/dist/pypy/translator/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/c/autopath.py ============================================================================== --- pypy/dist/pypy/translator/c/autopath.py (original) +++ pypy/dist/pypy/translator/c/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/c/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/c/test/autopath.py (original) +++ pypy/dist/pypy/translator/c/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/goal/autopath.py ============================================================================== --- pypy/dist/pypy/translator/goal/autopath.py (original) +++ pypy/dist/pypy/translator/goal/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/java/autopath.py ============================================================================== --- pypy/dist/pypy/translator/java/autopath.py (original) +++ pypy/dist/pypy/translator/java/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/java/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/java/test/autopath.py (original) +++ pypy/dist/pypy/translator/java/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/llvm2/tool/autopath.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/tool/autopath.py (original) +++ pypy/dist/pypy/translator/llvm2/tool/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/pyrex/autopath.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/autopath.py (original) +++ pypy/dist/pypy/translator/pyrex/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/pyrex/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/test/autopath.py (original) +++ pypy/dist/pypy/translator/pyrex/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/test/autopath.py ============================================================================== --- pypy/dist/pypy/translator/test/autopath.py (original) +++ pypy/dist/pypy/translator/test/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/tool/autopath.py ============================================================================== --- pypy/dist/pypy/translator/tool/autopath.py (original) +++ pypy/dist/pypy/translator/tool/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): Modified: pypy/dist/pypy/translator/tool/pygame/autopath.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/autopath.py (original) +++ pypy/dist/pypy/translator/tool/pygame/autopath.py Tue Jul 26 11:33:23 2005 @@ -50,8 +50,11 @@ if fullorig.startswith(pypy_root): if os.path.exists(os.path.join(fullorig, '__init__.py')): sys.path.remove(orig) - if head not in sys.path: - sys.path.insert(0, head) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) munged = {} for name, mod in sys.modules.items(): From arigo at codespeak.net Tue Jul 26 11:43:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 11:43:25 +0200 (CEST) Subject: [pypy-svn] r15093 - in pypy/dist/pypy/objspace/flow: . test Message-ID: <20050726094325.EC0FA27B62@code1.codespeak.net> Author: arigo Date: Tue Jul 26 11:43:25 2005 New Revision: 15093 Modified: pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/test/test_objspace.py Log: Raise implicit exceptions for built-in functions that are not in the __builtin__ module. This is needed e.g. to call os.stat() and catch the OSError. (cfbolz, arigo) Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Tue Jul 26 11:43:25 2005 @@ -390,10 +390,10 @@ if isinstance(w_callable, Constant): c = w_callable.value if not self.builtins_can_raise_exceptions: - if isinstance(c, (types.BuiltinFunctionType, - types.BuiltinMethodType)): - exceptions = None - elif (isinstance(c, (type, types.ClassType)) and + if (isinstance(c, (types.BuiltinFunctionType, + types.BuiltinMethodType, + types.ClassType, + types.TypeType)) and c.__module__ in ['__builtin__', 'exceptions']): exceptions = None self.handle_implicit_exceptions(exceptions) Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Tue Jul 26 11:43:25 2005 @@ -6,6 +6,7 @@ objspacename = 'flow' +import os import operator is_operator = getattr(operator, 'is_', operator.eq) # it's not there 2.2 @@ -231,6 +232,37 @@ traverse(cannot_reach_exceptblock, x) #__________________________________________________________ + def implicitException_int_and_id(x): + try: + return int(x) + id(x) + except ValueError: # not captured by the flow graph! + return 0 + + def test_implicitException_int_and_id(self): + x = self.codetest(self.implicitException_int_and_id) + simplify_graph(x) + self.show(x) + assert len(x.startblock.exits) == 1 + assert x.startblock.exits[0].target is x.returnblock + + #__________________________________________________________ + def implicitException_os_stat(x): + try: + return os.stat(x) + except OSError: # *captured* by the flow graph! + return 0 + + def test_implicitException_os_stat(self): + x = self.codetest(self.implicitException_os_stat) + simplify_graph(x) + self.show(x) + assert len(x.startblock.exits) == 3 + d = {} + for link in x.startblock.exits: + d[link.exitcase] = True + assert d == {None: True, OSError: True, Exception: True} + + #__________________________________________________________ def reraiseKeyError(dic): try: x = dic[5] From ericvrp at codespeak.net Tue Jul 26 12:07:49 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 26 Jul 2005 12:07:49 +0200 (CEST) Subject: [pypy-svn] r15094 - pypy/dist/pypy/translator/llvm2/test Message-ID: <20050726100749.B749A27B6D@code1.codespeak.net> Author: ericvrp Date: Tue Jul 26 12:07:48 2005 New Revision: 15094 Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_exception.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Log: Skip currently (work on progress) failed tests. Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Tue Jul 26 12:07:48 2005 @@ -51,12 +51,14 @@ assert f(False) == 2 def test_global_instance(self): + py.test.skip("not working yet") f = compile_function(llvmsnippet.global_instance, [int]) assert f(-1) == llvmsnippet.global_instance(-1) for i in range(20): assert f(i) == llvmsnippet.global_instance(i) def test_call_degrading_func(self): + py.test.skip("not working yet") f = compile_function(llvmsnippet.call_degrading_func, [bool]) assert f(True) == llvmsnippet.call_degrading_func(True) #-36 assert f(False) == llvmsnippet.call_degrading_func(False) #14 Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Tue Jul 26 12:07:48 2005 @@ -1,3 +1,5 @@ +import py + from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.test.snippet import try_raise_choose @@ -27,6 +29,7 @@ assert f(1) == fn(1) def test_simple2(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -53,6 +56,7 @@ assert f(10) == fn(10) def test_divzero(): + py.test.skip("not working yet") def fn(n): try: n/0 @@ -63,6 +67,7 @@ assert f(0) == fn(0) def test_reraise1(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -76,6 +81,7 @@ assert f(10) == fn(10) def test_reraise2(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -89,6 +95,7 @@ assert f(10) == fn(10) def test_simple_exception(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -103,6 +110,7 @@ assert f(i) == fn(i) def test_two_exceptions(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -119,6 +127,7 @@ assert f(i) == fn(i) def test_catch_base_exception(): + py.test.skip("not working yet") def fn(n): lst = range(10) try: @@ -134,6 +143,7 @@ def test_catches(): + py.test.skip("not working yet") def raises(i): if i == 3: raise MyException, 12 @@ -157,6 +167,7 @@ assert f(13) == fn(13) def test_try_raise_choose(): + py.test.skip("not working yet") f = compile_function(try_raise_choose, [int]) for i in [-1, 0, 1, 2]: assert f(i) == i Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jul 26 12:07:48 2005 @@ -16,6 +16,7 @@ assert f() == 1 def test_simple_function_pointer(): + py.test.skip("not working yet") def f1(x): return x + 1 def f2(x): @@ -332,6 +333,7 @@ assert f() == 4 def test_dict_creation(): + py.test.skip("not working yet") d = {'hello' : 23, 'world' : 21} l = ["hello", "world"] Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Tue Jul 26 12:07:48 2005 @@ -55,6 +55,7 @@ assert shr(42,2) == llvmsnippet.shiftright(42,2) def test_shift_with_overflow(self): + py.test.skip("overflow not working yet") shl = compile_function(llvmsnippet.shiftleft, [int, int]) shr = compile_function(llvmsnippet.shiftright, [int, int]) for i in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: @@ -88,6 +89,7 @@ assert f(3) == 8 def test_pbc_function2(self): + py.test.skip("not working yet") f = compile_function(llvmsnippet.pbc_function2, [int]) assert f(0) == 13 assert f(1) == 15 From ericvrp at codespeak.net Tue Jul 26 12:10:00 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 26 Jul 2005 12:10:00 +0200 (CEST) Subject: [pypy-svn] r15095 - in pypy/dist/pypy/translator/llvm2: . module tool Message-ID: <20050726101000.AB18C27B6D@code1.codespeak.net> Author: ericvrp Date: Tue Jul 26 12:09:59 2005 New Revision: 15095 Added: pypy/dist/pypy/translator/llvm2/module/ pypy/dist/pypy/translator/llvm2/module/__init__.py pypy/dist/pypy/translator/llvm2/module/extfunction.py - copied unchanged from r15063, pypy/dist/pypy/translator/llvm2/extfunction.py Removed: pypy/dist/pypy/translator/llvm2/extfunction.py Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Log: starting to mirror rpyton.module layout Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfuncnode.py (original) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Tue Jul 26 12:09:59 2005 @@ -7,7 +7,6 @@ from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -#from pypy.rpython.extfunctable import table as extfunctable log = log.extfuncnode class ExternalFuncNode(LLVMNode): Deleted: /pypy/dist/pypy/translator/llvm2/extfunction.py ============================================================================== --- /pypy/dist/pypy/translator/llvm2/extfunction.py Tue Jul 26 12:09:59 2005 +++ (empty file) @@ -1,159 +0,0 @@ -extdeclarations = """ -declare sbyte* %gc_malloc(uint) -declare sbyte* %gc_malloc_atomic(uint) - -declare int %time(int*) ;void* actually -declare int %clock() -declare void %sleep(int) -declare int %dup(int) -declare void %close(int) -declare int %open(sbyte*, int, int) -declare int %write(int, sbyte*, int) -declare int %read(int, sbyte*, int) -declare sbyte* %strncpy(sbyte*, sbyte*, int) - -%st.rpy_string.0 = type {int, {int, [0 x sbyte]}} - -%last_exception_type = global long 0 -%last_exception_value = global long 0 -""" - -gc_boehm = """ -declare sbyte* %GC_malloc(uint) -declare sbyte* %GC_malloc_atomic(uint) - -sbyte* %gc_malloc(uint %n) { - %ptr = call sbyte* %GC_malloc(uint %n) - ret sbyte* %ptr -} - -sbyte* %gc_malloc_atomic(uint %n) { - %ptr = call sbyte* %GC_malloc_atomic(uint %n) - ret sbyte* %ptr -} - -""" - -gc_disabled = """ -sbyte* %gc_malloc(uint %n) { - %ptr = malloc sbyte, uint %n - ret sbyte* %ptr -} - -sbyte* %gc_malloc_atomic(uint %n) { - %ptr = malloc sbyte, uint %n - ret sbyte* %ptr -} - -""" - -extfunctions = {} #dependencies, llvm-code - -extfunctions["%cast"] = ((), """ -sbyte* %cast(%st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - %length = add int %reallength, 1 - %ulength = cast int %length to uint - %dest = call sbyte* %gc_malloc_atomic(uint %ulength) - - %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 - %source1 = cast [0 x sbyte]* %source1ptr to sbyte* - %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) - - %zeropos1 = cast sbyte* %dest to int - %zeropos2 = add int %zeropos1, %reallength - %zerodest = cast int %zeropos2 to sbyte* - store sbyte 0, sbyte* %zerodest - - ret sbyte* %dest -} - -""") - -extfunctions["%ll_time_time"] = ((), """ -double %ll_time_time() { - %v0 = call int %time(int* null) - %v1 = cast int %v0 to double - ret double %v1 -} - -""") - -extfunctions["%ll_time_clock"] = ((), """ -double %ll_time_clock() { - %v0 = call int %clock() - %v1 = cast int %v0 to double - ; XXX how to get at the proper division (or any other) constant per platform? - %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC accrdoing to single unix spec - ret double %v2 -} - -""") - -extfunctions["%ll_time_sleep"] = ((), """ -void %ll_time_sleep(double %f) { - %i = cast double %f to int - call void %sleep(int %i) - ret void -} - -""") - -extfunctions["%ll_os_dup"] = ((), """ -int %ll_os_dup(int %fd) { - %ret = call int %dup(int %fd) - ret int %ret -} - -""") - -extfunctions["%ll_os_close"] = ((), """ -void %ll_os_close(int %fd) { - call void %close(int %fd) - ret void -} - -""") - -extfunctions["%ll_os_open"] = (("%cast",), """ -int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) { - %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) - %fd = call int %open(sbyte* %dest, int %flag, int %mode) - ret int %fd -} - -""") - -extfunctions["%ll_os_write"] = (("%cast",), """ -int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) - %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) - ret int %byteswritten -} - -""") - -extfunctions["%ll_read_into"] = ((), """ -int %ll_read_into(int %fd, %st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - - %destptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 - %dest = cast [0 x sbyte]* %destptr to sbyte* - - %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength) - ret int %bytesread -} - -""") - -def dependencies(funcname, deplist): - deplist.append(funcname) - if funcname in extfunctions: - for depfuncname in extfunctions[funcname][0]: - if depfuncname not in deplist: #avoid loops - dependencies(depfuncname, deplist) - return deplist Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Tue Jul 26 12:09:59 2005 @@ -14,7 +14,7 @@ from pypy.translator.llvm2.extfuncnode import ExternalFuncNode from pypy.translator.backendoptimization import remove_void #from pypy.translator.backendoptimization import rename_extfunc_calls -from pypy.translator.llvm2.extfunction import extdeclarations, \ +from pypy.translator.llvm2.module.extfunction import extdeclarations, \ extfunctions, gc_boehm, gc_disabled, dependencies from pypy.translator.translator import Translator Added: pypy/dist/pypy/translator/llvm2/module/__init__.py ============================================================================== Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (original) +++ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Tue Jul 26 12:09:59 2005 @@ -4,7 +4,7 @@ import os from pypy.rpython.module import ll_os, ll_os_path, ll_time, ll_math #XXX keep this list up-to-date -from pypy.translator.llvm2.extfunction import extfunctions +from pypy.translator.llvm2.module.extfunction import extfunctions def main(): suggested_primitives = [] From tismer at codespeak.net Tue Jul 26 12:16:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 12:16:11 +0200 (CEST) Subject: [pypy-svn] r15096 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726101611.496AF27B6D@code1.codespeak.net> Author: tismer Date: Tue Jul 26 12:16:09 2005 New Revision: 15096 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Richard, Chris: started support for .pyc importing. Prepared a plan, some constants and an interface layout, to work in parallel. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 12:16:09 2005 @@ -165,11 +165,11 @@ def load_part(space, w_path, prefix, partname, w_parent, tentative): w = space.wrap - modulename = '.'.join(prefix+[partname]) + modulename = '.'.join(prefix + [partname]) w_modulename = w(modulename) w_mod = check_sys_modules(space, w_modulename) if w_mod is not None: - if not space.is_true(space.is_(w_mod,space.w_None)): + if not space.is_true(space.is_(w_mod, space.w_None)): return w_mod else: w_mod = space.sys.getmodule(modulename) @@ -180,7 +180,7 @@ for path in space.unpackiterable(w_path): dir = os.path.join(space.str_w(path), partname) if os.path.isdir(dir): - fn = os.path.join(dir,'__init__.py') + fn = os.path.join(dir, '__init__.py') w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname), pkgdir=dir) if w_mod is not None: @@ -217,3 +217,107 @@ space.wrap(space.builtin)) pycode.exec_code(space, w_globals, w_locals) +# __________________________________________________________________ +# +# .pyc file support + +""" + Magic word to reject .pyc files generated by other Python versions. + It should change for each incompatible change to the bytecode. + + The value of CR and LF is incorporated so if you ever read or write + a .pyc file in text mode the magic number will be wrong; also, the + Apple MPW compiler swaps their values, botching string constants. + + The magic numbers must be spaced apart atleast 2 values, as the + -U interpeter flag will cause MAGIC+1 being used. They have been + odd numbers for some time now. + + There were a variety of old schemes for setting the magic number. + The current working scheme is to increment the previous value by + 10. + + Known values: + Python 1.5: 20121 + Python 1.5.1: 20121 + Python 1.5.2: 20121 + Python 2.0: 50823 + Python 2.0.1: 50823 + Python 2.1: 60202 + Python 2.1.1: 60202 + Python 2.1.2: 60202 + Python 2.2: 60717 + Python 2.3a0: 62011 + Python 2.3a0: 62021 + Python 2.3a0: 62011 (!) + Python 2.4a0: 62041 + Python 2.4a3: 62051 + Python 2.4b1: 62061 +""" + +# XXX how do we configure this ??? +MAGIC = 62061 | (ord('\r')<<16) | (ord('\n')<<24) + +"""Magic word as global; note that _PyImport_Init() can change the + value of this global to accommodate for alterations of how the + compiler works which are enabled by command line switches. +""" + +pyc_magic = MAGIC + + +PLAN = """ +have a function that finds a .py or .pyc file and decides what to use. + +CPython: Looks into both and uses .pyc if alone. +We want this option, too, but disabled. + +implement +- check_compiled_module() +- read_compiled_module + header is skipped + check for valid code object +- load_compiled_module +- load_source_module +- write_compiled_module + called by load_source_module (maybe also optional) + +- load_module + loads what it gets, flag controls mode decision. + move the module creation stuff from try_import_mod into + load_module. + +modify imp_execfile to accept .pyc files as well. +The decision what to use has been driven, already. +""" + +def load_module(name, fd, type): # XXX later: loader): + """ + Load an external module using the default search path and return + its module object. + """ + +def load_source_module(name, pathname, fd): + """ + Load a source module from a given file and return its module + object. If there's a matching byte-compiled file, use that instead. + """ + + +def load_compiled_module(name, cpathname, fd): + """ + Load a module from a compiled file, execute it, and return its + module object. + """ + +def read_compiled_module(cpathname, fd): + """ Read a code object from a file and check it for validity """ + + +def write_compiled_module(co, cpathname, mtime): + """ + Write a compiled module to a file, placing the time of last + modification of its source into the header. + Errors are ignored, if a write error occurs an attempt is made to + remove the file. + """ From tismer at codespeak.net Tue Jul 26 12:18:19 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 12:18:19 +0200 (CEST) Subject: [pypy-svn] r15097 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726101819.B55A927B6D@code1.codespeak.net> Author: tismer Date: Tue Jul 26 12:18:18 2005 New Revision: 15097 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: addition to the interface stubs Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 12:18:18 2005 @@ -303,6 +303,15 @@ object. If there's a matching byte-compiled file, use that instead. """ +def check_compiled_module(pathname, mtime, cpathname): + """ + Given a pathname for a Python source file, its time of last + modification, and a pathname for a compiled file, check whether the + compiled file represents the same version of the source. If so, + return a FILE pointer for the compiled file, positioned just after + the header; if not, return NULL. + Doesn't set an exception. + """ def load_compiled_module(name, cpathname, fd): """ From arigo at codespeak.net Tue Jul 26 12:18:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 12:18:46 +0200 (CEST) Subject: [pypy-svn] r15098 - pypy/dist/pypy/rpython Message-ID: <20050726101846.BF2CC27B6D@code1.codespeak.net> Author: arigo Date: Tue Jul 26 12:18:45 2005 New Revision: 15098 Modified: pypy/dist/pypy/rpython/llinterp.py Log: Hack to handle OSErrors properly in the llinterp. The problem of OSErrors is that they carry an 'errno' field. (cfbolz, arigo) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Jul 26 12:18:45 2005 @@ -5,6 +5,7 @@ import py from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer, PyObject, pyobjectptr from pypy.rpython.lltype import Array +from pypy.rpython.rmodel import getfunctionptr import math log = py.log.Producer('llinterp') @@ -155,18 +156,25 @@ retval = ophandler(*vals) self.setvar(operation.result, retval) - def make_llexception(self, exc_class): + def make_llexception(self, exc): exdata = self.llinterpreter.typer.getexceptiondata() - evalue = exdata.ll_pyexcclass2exc(pyobjectptr(exc_class)) - etype = exdata.ll_type_of_exc_inst(evalue) + if isinstance(exc, OSError): + fn = getfunctionptr(self.llinterpreter.typer.annotator.translator, + exdata.ll_raise_OSError) + self.op_direct_call(fn, exc.errno) + assert False, "op_direct_call above should have raised" + else: + exc_class = exc.__class__ + evalue = exdata.ll_pyexcclass2exc(pyobjectptr(exc_class)) + etype = exdata.ll_type_of_exc_inst(evalue) raise LLException(etype, evalue) def invoke_callable_with_pyexceptions(self, fptr, *args): - print "invoking %s(%s)" % (fptr, args) try: return fptr._obj._callable(*args) except Exception, e: - self.make_llexception(e.__class__) + #print "GOT A CPYTHON EXCEPTION:", e.__class__, e + self.make_llexception(e) # __________________________________________________________ # misc LL operation implementations @@ -318,7 +326,7 @@ try: pyo = func(*[pyo._obj.value for pyo in pyobjs]) except Exception, e: - self.make_llexception(e.__class__) + self.make_llexception(e) return pyobjectptr(pyo) """ % locals()).compile() del opname From arigo at codespeak.net Tue Jul 26 12:44:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 12:44:14 +0200 (CEST) Subject: [pypy-svn] r15099 - in pypy/dist/pypy/translator/c: src test Message-ID: <20050726104414.DB24327B6D@code1.codespeak.net> Author: arigo Date: Tue Jul 26 12:44:12 2005 New Revision: 15099 Modified: pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: * ANSI C fix in ll_math.h. * added a test for os.path.exists() in genc, but disabled it and other tests handling strings for now, until we have properly zero-terminated C strings. (cfbolz, arigo) Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Tue Jul 26 12:44:12 2005 @@ -18,7 +18,7 @@ return ceil(x); } -struct RPyFREXP_RESULT* LL_math_frexp(double x) { +RPyFREXP_RESULT* LL_math_frexp(double x) { int expo; double m = frexp(x, &expo); return ll_frexp_result(m, expo); @@ -40,7 +40,7 @@ return ldexp(x, (int) y); } -struct RPyMODF_RESULT* LL_math_modf(double x) { +RPyMODF_RESULT* LL_math_modf(double x) { double intpart; double fracpart = modf(x, &intpart); return ll_modf_result(fracpart, intpart); Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Jul 26 12:44:12 2005 @@ -16,7 +16,7 @@ assert t0 <= t1 <= t2 -def test_os_open(): +def INPROGRESStest_os_open(): tmpfile = str(udir.join('test_os_open.txt')) def does_stuff(): fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) @@ -27,7 +27,7 @@ os.close(fd) assert os.path.exists(tmpfile) -def test_failing_os_open(): +def INPROGRESStest_failing_os_open(): tmpfile = str(udir.join('test_failing_os_open.DOESNTEXIST')) def does_stuff(): fd = os.open(tmpfile, os.O_RDONLY, 0777) @@ -37,7 +37,7 @@ py.test.raises(OSError, f1) assert not os.path.exists(tmpfile) -def test_open_read_write_close(): +def INPROGRESStest_open_read_write_close(): filename = str(udir.join('test_open_read_write_close.txt')) def does_stuff(): fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) @@ -54,7 +54,7 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) -def test_os_stat(): +def INPROGRESStest_os_stat(): filename = str(py.magic.autopath()) def call_stat(): st = os.stat(filename) @@ -65,7 +65,7 @@ assert result[1] == os.stat(filename)[1] assert result[2] == os.stat(filename)[2] -def test_os_fstat(): +def INPROGRESStest_os_fstat(): filename = str(py.magic.autopath()) def call_fstat(): fd = os.open(filename, os.O_RDONLY, 0777) @@ -105,3 +105,12 @@ f = compile(fn, [float]) assert f(10.123) == modf(10.123) +def INPROGRESStest_os_path_exists(): + tmpfile = str(udir.join('test_os_path_exists.TMP')) + def fn(): + return os.path.exists(tmpfile) + f = compile(fn, []) + open(tmpfile, 'w').close() + assert f() is True + os.unlink(tmpfile) + assert f() is False From rxe at codespeak.net Tue Jul 26 12:51:05 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 12:51:05 +0200 (CEST) Subject: [pypy-svn] r15100 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726105105.7E63027B6D@code1.codespeak.net> Author: rxe Date: Tue Jul 26 12:51:04 2005 New Revision: 15100 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Add a create_module() helper to importing. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 12:51:04 2005 @@ -14,17 +14,13 @@ # XXX a frozen version of some routines of only one of the # XXX posixpath/ntpath/macpath modules. - def try_import_mod(space, w_modulename, fn, w_parent, w_name, pkgdir=None): - w = space.wrap if os.path.exists(fn): - w_mod = space.wrap(Module(space, w_modulename)) - space.sys.setmodule(w_mod) - space.setattr(w_mod, w('__file__'), w(fn)) - space.setattr(w_mod, w('__doc__'), space.w_None) - if pkgdir is not None: - space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) - w_dict = space.getattr(w_mod, w('__dict__')) + w_mod, w_dict = create_module(space, + w_modulename, + space.wrap(fn), + pkgdir) + e = None try: imp_execfile(space, fn, w_dict, w_dict) @@ -217,6 +213,18 @@ space.wrap(space.builtin)) pycode.exec_code(space, w_globals, w_locals) +def create_module(space, w_modulename, w_name, pkgdir): + """ Helper to create module. """ + w = space.wrap + w_mod = w(Module(space, w_modulename)) + space.sys.setmodule(w_mod) + space.setattr(w_mod, w('__file__'), w_name) + space.setattr(w_mod, w('__doc__'), space.w_None) + if pkgdir is not None: + space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) + w_dict = space.getattr(w_mod, w('__dict__')) + return w_mod, w_dict + # __________________________________________________________________ # # .pyc file support From tismer at codespeak.net Tue Jul 26 13:16:19 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 13:16:19 +0200 (CEST) Subject: [pypy-svn] r15101 - pypy/dist/pypy/module/marshal Message-ID: <20050726111619.6C50727B6D@code1.codespeak.net> Author: tismer Date: Tue Jul 26 13:16:18 2005 New Revision: 15101 Modified: pypy/dist/pypy/module/marshal/app_marshal.py Log: Modified: pypy/dist/pypy/module/marshal/app_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 13:16:18 2005 @@ -1,9 +1,8 @@ """Marshal module written in Python. """ -import StringIO -import string import types +import os try: import new except ImportError: @@ -36,8 +35,18 @@ dispatch = {} - def __init__(self, f): - self.f = f + def __init__(self, fd): + self.fd = fd + self.buffer = [] + + def _write(self, data): + if self.fd >= 0: + os.write(self.fd, data) + else: + self.buffer.append(data) + + def getvalue(self): + return ''.join(self.buffer) def dump(self, x): try: @@ -56,36 +65,34 @@ self.w_long(x>>32) def w_long(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) - write(chr((x>>16) & 0xff)) - write(chr((x>>24) & 0xff)) + self._write(chr((x) & 0xff)) + self._write(chr((x>> 8) & 0xff)) + self._write(chr((x>>16) & 0xff)) + self._write(chr((x>>24) & 0xff)) def w_short(self, x): - write = self.f.write - write(chr((x) & 0xff)) - write(chr((x>> 8) & 0xff)) + self._write(chr((x) & 0xff)) + self._write(chr((x>> 8) & 0xff)) def dump_none(self, x): - self.f.write(TYPE_NONE) + self._write(TYPE_NONE) dispatch[types.NoneType] = dump_none def dump_bool(self, x): if x: - self.f.write(TYPE_TRUE) + self._write(TYPE_TRUE) else: - self.f.write(TYPE_FALSE) + self._write(TYPE_FALSE) dispatch[bool] = dump_bool def dump_stopiter(self, x): if x is not StopIteration: raise ValueError, "unmarshallable object" - self.f.write(TYPE_STOPITER) + self._write(TYPE_STOPITER) dispatch[type(StopIteration)] = dump_stopiter def dump_ellipsis(self, x): - self.f.write(TYPE_ELLIPSIS) + self._write(TYPE_ELLIPSIS) try: dispatch[types.EllipsisType] = dump_ellipsis @@ -95,15 +102,15 @@ def dump_int(self, x): y = x>>31 if y and y != -1: - self.f.write(TYPE_INT64) + self._write(TYPE_INT64) self.w_long64(x) else: - self.f.write(TYPE_INT) + self._write(TYPE_INT) self.w_long(x) dispatch[types.IntType] = dump_int def dump_long(self, x): - self.f.write(TYPE_LONG) + self._write(TYPE_LONG) sign = 1 if x < 0: sign = -1 @@ -118,7 +125,7 @@ dispatch[types.LongType] = dump_long def dump_float(self, x): - write = self.f.write + write = self._write write(TYPE_FLOAT) s = `x` write(chr(len(s))) @@ -126,7 +133,7 @@ dispatch[types.FloatType] = dump_float def dump_complex(self, x): - write = self.f.write + write = self._write write(TYPE_COMPLEX) s = `x.real` write(chr(len(s))) @@ -142,42 +149,42 @@ def dump_string(self, x): # XXX we can't check for interned strings, yet, # so we (for now) never create TYPE_INTERNED or TYPE_STRINGREF - self.f.write(TYPE_STRING) + self._write(TYPE_STRING) self.w_long(len(x)) - self.f.write(x) + self._write(x) dispatch[types.StringType] = dump_string def dump_unicode(self, x): - self.f.write(TYPE_UNICODE) + self._write(TYPE_UNICODE) s = x.encode('utf8') self.w_long(len(s)) - self.f.write(s) + self._write(s) dispatch[types.UnicodeType] = dump_unicode def dump_tuple(self, x): - self.f.write(TYPE_TUPLE) + self._write(TYPE_TUPLE) self.w_long(len(x)) for item in x: self.dump(item) dispatch[types.TupleType] = dump_tuple def dump_list(self, x): - self.f.write(TYPE_LIST) + self._write(TYPE_LIST) self.w_long(len(x)) for item in x: self.dump(item) dispatch[types.ListType] = dump_list def dump_dict(self, x): - self.f.write(TYPE_DICT) + self._write(TYPE_DICT) for key, value in x.items(): self.dump(key) self.dump(value) - self.f.write(TYPE_NULL) + self._write(TYPE_NULL) dispatch[types.DictionaryType] = dump_dict def dump_code(self, x): - self.f.write(TYPE_CODE) + self._write(TYPE_CODE) self.w_long(x.co_argcount) self.w_long(x.co_nlocals) self.w_long(x.co_stacksize) @@ -198,7 +205,7 @@ pass def dump_set(self, x): - self.f.write(TYPE_SET) + self._write(TYPE_SET) self.w_long(len(x)) for each in x: self.dump(each) @@ -208,7 +215,7 @@ pass def dump_frozenset(self, x): - self.f.write(TYPE_FROZENSET) + self._write(TYPE_FROZENSET) self.w_long(len(x)) for each in x: self.dump(each) @@ -224,46 +231,66 @@ dispatch = {} - def __init__(self, f): - self.f = f + def __init__(self, fd): + self.fd = fd + self.bufstr = '' + self.bufpos = 0 self._stringtable = [] + def _read(self): + if self.fd >= 0: + return self.fd.read(1) + else: + ret = self.bufstr[self.bufpos] + self.bufpos += 1 + return ret + + def _readn(self, n): + if self.fd >= 0: + return self.fd.read(n) + else: + ret = self.bufstr[self.bufpos : self.bufpos+n] + self.bufpos += n + if self.bufpos > len(self.bufstr): + raise EOFError, "read past buffer" + return ret + + def setvalue(self, data): + self.bufstr = data + def load(self): - c = self.f.read(1) + c = self._read() if not c: raise EOFError return self.dispatch[c](self) def r_short(self): - read = self.f.read - lo = ord(read(1)) - hi = ord(read(1)) + lo = ord(self._read()) + hi = ord(self._read()) x = lo | (hi<<8) if x & 0x8000: x = x - 0x10000 return x def r_long(self): - read = self.f.read - a = ord(read(1)) - b = ord(read(1)) - c = ord(read(1)) - d = ord(read(1)) + a = ord(self._read()) + b = ord(self._read()) + c = ord(self._read()) + d = ord(self._read()) x = a | (b<<8) | (c<<16) | (d<<24) if d & 0x80 and x > 0: x = -((1L<<32) - x) return x def r_long64(self): - read = self.f.read - a = ord(read(1)) - b = ord(read(1)) - c = ord(read(1)) - d = ord(read(1)) - e = long(ord(read(1))) - f = long(ord(read(1))) - g = long(ord(read(1))) - h = long(ord(read(1))) + a = ord(self._read()) + b = ord(self._read()) + c = ord(self._read()) + d = ord(self._read()) + e = long(ord(self._read())) + f = long(ord(self._read())) + g = long(ord(self._read())) + h = long(ord(self._read())) x = a | (b<<8) | (c<<16) | (d<<24) x = x | (e<<32) | (f<<40) | (g<<48) | (h<<56) if h & 0x80 and x > 0: @@ -316,29 +343,29 @@ dispatch[TYPE_LONG] = load_long def load_float(self): - n = ord(self.f.read(1)) - s = self.f.read(n) - return string.atof(s) + n = ord(self._read()) + s = self._readn(n) + return float(s) dispatch[TYPE_FLOAT] = load_float def load_complex(self): - n = ord(self.f.read(1)) - s = self.f.read(n) + n = ord(self._read()) + s = self._readn(n) real = float(s) - n = ord(self.f.read(1)) - s = self.f.read(n) + n = ord(self._read()) + s = self._readn(n) imag = float(s) return complex(real, imag) dispatch[TYPE_COMPLEX] = load_complex def load_string(self): n = self.r_long() - return self.f.read(n) + return self._readn(n) dispatch[TYPE_STRING] = load_string def load_interned(self): n = self.r_long() - ret = intern(self.f.read(n)) + ret = intern(self._readn(n)) self._stringtable.append(ret) return ret dispatch[TYPE_INTERNED] = load_interned @@ -350,7 +377,7 @@ def load_unicode(self): n = self.r_long() - s = self.f.read(n) + s = self._readn(n) ret = s.decode('utf8') return ret dispatch[TYPE_UNICODE] = load_unicode @@ -420,16 +447,17 @@ frozenset = set def dump(x, f): - Marshaller(f).dump(x) + Marshaller(f.fileno()).dump(x) def load(f): - return Unmarshaller(f).load() + return Unmarshaller(f.fileno()).load() def dumps(x): - f = StringIO.StringIO() - dump(x, f) - return f.getvalue() + m = Marshaller(-1) + m.dump(x) + return m.getvalue() def loads(s): - f = StringIO.StringIO(s) - return load(f) + um = Unmarshaller(-1) + um.setvalue(s) + return um.load() From tismer at codespeak.net Tue Jul 26 13:17:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 13:17:26 +0200 (CEST) Subject: [pypy-svn] r15102 - pypy/dist/pypy/module/marshal Message-ID: <20050726111726.747BA27B6D@code1.codespeak.net> Author: tismer Date: Tue Jul 26 13:17:25 2005 New Revision: 15102 Modified: pypy/dist/pypy/module/marshal/app_marshal.py Log: Richard & Christian: modified marshal to use plain os.open file descriptors instead of Python files. sorry about this check-in, missed the message. Modified: pypy/dist/pypy/module/marshal/app_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 13:17:25 2005 @@ -3,6 +3,7 @@ import types import os + try: import new except ImportError: From arigo at codespeak.net Tue Jul 26 13:35:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 13:35:18 +0200 (CEST) Subject: [pypy-svn] r15103 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050726113518.9F59227B6D@code1.codespeak.net> Author: arigo Date: Tue Jul 26 13:35:16 2005 New Revision: 15103 Modified: pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Hack to reserve an extra byte at the end of the array of characters in the STR objects. (cfbolz, arigo) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Jul 26 13:35:16 2005 @@ -8,6 +8,7 @@ from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType from pypy.translator.c import extfunc +from pypy.rpython.rstr import STR def needs_refcount(T): @@ -173,12 +174,15 @@ self.ARRAY = ARRAY self.LLTYPE = ARRAY self.varlength = varlength + self.original_varlength = varlength + if ARRAY is STR.chars: + self.varlength += 1 # for the NULL char at the end of the string def setup(self): db = self.db ARRAY = self.ARRAY varlength = self.varlength - if varlength == 1: + if self.original_varlength == 1: basename = 'array' with_number = True else: Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Jul 26 13:35:16 2005 @@ -16,7 +16,7 @@ assert t0 <= t1 <= t2 -def INPROGRESStest_os_open(): +def test_os_open(): tmpfile = str(udir.join('test_os_open.txt')) def does_stuff(): fd = os.open(tmpfile, os.O_WRONLY | os.O_CREAT, 0777) @@ -27,7 +27,7 @@ os.close(fd) assert os.path.exists(tmpfile) -def INPROGRESStest_failing_os_open(): +def test_failing_os_open(): tmpfile = str(udir.join('test_failing_os_open.DOESNTEXIST')) def does_stuff(): fd = os.open(tmpfile, os.O_RDONLY, 0777) @@ -37,7 +37,7 @@ py.test.raises(OSError, f1) assert not os.path.exists(tmpfile) -def INPROGRESStest_open_read_write_close(): +def test_open_read_write_close(): filename = str(udir.join('test_open_read_write_close.txt')) def does_stuff(): fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) @@ -54,7 +54,7 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) -def INPROGRESStest_os_stat(): +def test_os_stat(): filename = str(py.magic.autopath()) def call_stat(): st = os.stat(filename) @@ -65,11 +65,12 @@ assert result[1] == os.stat(filename)[1] assert result[2] == os.stat(filename)[2] -def INPROGRESStest_os_fstat(): +def CRASHING_test_os_fstat(): filename = str(py.magic.autopath()) def call_fstat(): fd = os.open(filename, os.O_RDONLY, 0777) st = os.fstat(fd) + os.close(fd) return st f = compile(call_fstat, []) result = f() @@ -105,7 +106,7 @@ f = compile(fn, [float]) assert f(10.123) == modf(10.123) -def INPROGRESStest_os_path_exists(): +def test_os_path_exists(): tmpfile = str(udir.join('test_os_path_exists.TMP')) def fn(): return os.path.exists(tmpfile) From rxe at codespeak.net Tue Jul 26 13:53:24 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 13:53:24 +0200 (CEST) Subject: [pypy-svn] r15105 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726115324.87F7927B6D@code1.codespeak.net> Author: rxe Date: Tue Jul 26 13:53:23 2005 New Revision: 15105 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Christian and Richard Added an intial version of load_source_module() and use that for importing. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 13:53:23 2005 @@ -14,16 +14,21 @@ # XXX a frozen version of some routines of only one of the # XXX posixpath/ntpath/macpath modules. -def try_import_mod(space, w_modulename, fn, w_parent, w_name, pkgdir=None): - if os.path.exists(fn): - w_mod, w_dict = create_module(space, - w_modulename, - space.wrap(fn), - pkgdir) +def try_import_mod(space, w_modulename, filename, w_parent, w_name, pkgdir=None): + if os.path.exists(filename): + w = space.wrap + w_mod = w(Module(space, w_modulename)) + space.sys.setmodule(w_mod) + space.setattr(w_mod, w('__file__'), space.wrap(filename)) + space.setattr(w_mod, w('__doc__'), space.w_None) + if pkgdir is not None: + space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) e = None try: - imp_execfile(space, fn, w_dict, w_dict) + fd = os.open(filename, os.O_RDONLY, 0777) # XXX newlines? + load_source_module(space, w_modulename, w_mod, filename, fd) + except OperationError, e: if e.match(space, space.w_SyntaxError): w_mods = space.sys.get('modules') @@ -195,36 +200,6 @@ w_exc = space.call_function(space.w_ImportError, w_failing) raise OperationError(space.w_ImportError, w_exc) - -def imp_execfile(space, fn, w_globals, w_locals): - fd = os.open(fn, os.O_RDONLY, 0777) # XXX newlines? - try: - size = os.fstat(fd)[6] - source = os.read(fd, size) - finally: - os.close(fd) - w_source = space.wrap(source) - w_mode = space.wrap("exec") - w_fn = space.wrap(fn) - w_code = space.builtin.call('compile', w_source, w_fn, w_mode) - pycode = space.interpclass_w(w_code) - space.call_method(w_globals, 'setdefault', - space.wrap('__builtins__'), - space.wrap(space.builtin)) - pycode.exec_code(space, w_globals, w_locals) - -def create_module(space, w_modulename, w_name, pkgdir): - """ Helper to create module. """ - w = space.wrap - w_mod = w(Module(space, w_modulename)) - space.sys.setmodule(w_mod) - space.setattr(w_mod, w('__file__'), w_name) - space.setattr(w_mod, w('__doc__'), space.w_None) - if pkgdir is not None: - space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) - w_dict = space.getattr(w_mod, w('__dict__')) - return w_mod, w_dict - # __________________________________________________________________ # # .pyc file support @@ -299,17 +274,39 @@ The decision what to use has been driven, already. """ -def load_module(name, fd, type): # XXX later: loader): +def load_module(space, name, fd, type): # XXX later: loader): """ Load an external module using the default search path and return its module object. """ -def load_source_module(name, pathname, fd): +def load_source_module(space, w_modulename, w_mod, pathname, fd): """ Load a source module from a given file and return its module - object. If there's a matching byte-compiled file, use that instead. + object. XXX Wrong: If there's a matching byte-compiled file, use that instead. """ + w = space.wrap + try: + size = os.fstat(fd)[6] + source = os.read(fd, size) + finally: + os.close(fd) + + w_source = w(source) + w_mode = w("exec") + w_pathname = w(pathname) + w_code = space.builtin.call('compile', w_source, w_pathname, w_mode) + pycode = space.interpclass_w(w_code) + + w_dict = space.getattr(w_mod, w('__dict__')) + space.call_method(w_dict, 'setdefault', + w('__builtins__'), + w(space.builtin)) + pycode.exec_code(space, w_dict, w_dict) + + #XXX write file + + return w_mod def check_compiled_module(pathname, mtime, cpathname): """ From arigo at codespeak.net Tue Jul 26 13:58:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 13:58:19 +0200 (CEST) Subject: [pypy-svn] r15106 - pypy/dist/pypy/translator/c/test Message-ID: <20050726115819.E8FB627B6D@code1.codespeak.net> Author: arigo Date: Tue Jul 26 13:58:18 2005 New Revision: 15106 Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py Log: This test doesn't seem to crash after all, as long as it is not run on my machine :-( Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Jul 26 13:58:18 2005 @@ -65,7 +65,7 @@ assert result[1] == os.stat(filename)[1] assert result[2] == os.stat(filename)[2] -def CRASHING_test_os_fstat(): +def test_os_fstat(): filename = str(py.magic.autopath()) def call_fstat(): fd = os.open(filename, os.O_RDONLY, 0777) From tismer at codespeak.net Tue Jul 26 14:01:03 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 14:01:03 +0200 (CEST) Subject: [pypy-svn] r15107 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726120103.7CF6327B6D@code1.codespeak.net> Author: tismer Date: Tue Jul 26 14:01:01 2005 New Revision: 15107 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: soome merged state Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 14:01:01 2005 @@ -3,6 +3,7 @@ """ import sys, os +import marshal from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError @@ -308,7 +309,7 @@ return w_mod -def check_compiled_module(pathname, mtime, cpathname): +def check_compiled_module(space, pathname, mtime, cpathname): """ Given a pathname for a Python source file, its time of last modification, and a pathname for a compiled file, check whether the @@ -318,17 +319,35 @@ Doesn't set an exception. """ -def load_compiled_module(name, cpathname, fd): + fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) # using no defaults + um = marshal.Unmarshaller(fd) + + magic = um.load_int() + if magic != pyc_magic: + # XXX what to do about Py_VerboseFlag ? + # PySys_WriteStderr("# %s has bad magic\n", cpathname); + os.close(fp) + return + pyc_mtime = um.load_int() + if pyc_mtime != mtime: + # PySys_WriteStderr("# %s has bad mtime\n", cpathname); + os.close(fp) + return + # if (Py_VerboseFlag) + # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); + return fp + +def load_compiled_module(space, name, cpathname, fd): """ Load a module from a compiled file, execute it, and return its module object. """ -def read_compiled_module(cpathname, fd): +def read_compiled_module(space, cpathname, fd): """ Read a code object from a file and check it for validity """ -def write_compiled_module(co, cpathname, mtime): +def write_compiled_module(space, co, cpathname, mtime): """ Write a compiled module to a file, placing the time of last modification of its source into the header. From hpk at codespeak.net Tue Jul 26 14:23:18 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 14:23:18 +0200 (CEST) Subject: [pypy-svn] r15109 - in pypy/dist/pypy/rpython/module: . test Message-ID: <20050726122318.2E6CD27B70@code1.codespeak.net> Author: hpk Date: Tue Jul 26 14:23:17 2005 New Revision: 15109 Modified: pypy/dist/pypy/rpython/module/ll_math.py (props changed) pypy/dist/pypy/rpython/module/support.py (props changed) pypy/dist/pypy/rpython/module/test/test_ll_math.py (props changed) pypy/dist/pypy/rpython/module/test/test_ll_os_path.py (props changed) Log: fixeol From hpk at codespeak.net Tue Jul 26 14:29:44 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 14:29:44 +0200 (CEST) Subject: [pypy-svn] r15110 - in pypy/dist/pypy: interpreter objspace/std rpython translator/goal Message-ID: <20050726122944.7B99427B76@code1.codespeak.net> Author: hpk Date: Tue Jul 26 14:29:42 2005 New Revision: 15110 Added: pypy/dist/pypy/rpython/error.py (contents, props changed) Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/goal/translate_pypy.py Log: (hpk,pedronis) - making rtyping more robust by - Repr's now have a more controled way of initialization/setup phases - more strictly tracking and flagging RTyper problems. - factoring out the typer error printing to dump_typererrors() - "-fork" now checks that there are no random rpython modules imported. Some related changes like factoring out a 'pypy/rpython/error.py' module so that 'rmodel.py' doesn't need to imported at pre-fork time. - longobject.py now doesn't have debugging on by default because the annotator doesn't like that and we are running translation from the trunk currently. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jul 26 14:29:42 2005 @@ -197,8 +197,8 @@ return PythonCompiler(self) elif self.options.compiler == 'cpython': return CPythonCompiler(self) - elif self.options.compiler == 'pyparseapp': - return PythonCompilerApp(self) + #elif self.options.compiler == 'pyparseapp': + # return PythonCompilerApp(self) else: raise ValueError('unknown --compiler option value: %r' % ( self.options.compiler,)) Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Tue Jul 26 14:29:42 2005 @@ -63,7 +63,7 @@ # False == no checking at all # True == check 0 <= value <= MASK -CHECK_DIGITS = True +CHECK_DIGITS = False # True if CHECK_DIGITS: class DigitArray(list): Added: pypy/dist/pypy/rpython/error.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/error.py Tue Jul 26 14:29:42 2005 @@ -0,0 +1,10 @@ + +class TyperError(Exception): + def __str__(self): + result = Exception.__str__(self) + if hasattr(self, 'where'): + result += '\n.. %r\n.. %r' % self.where + return result + +class MissingRTypeOperation(TyperError): + pass Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jul 26 14:29:42 2005 @@ -66,7 +66,7 @@ else: result = ClassRepr(rtyper, classdef) rtyper.class_reprs[classdef] = result - rtyper.reprs_must_call_setup.append(result) + rtyper.add_pendingsetup(result) return result def getinstancerepr(rtyper, classdef): @@ -79,7 +79,7 @@ else: result = InstanceRepr(rtyper,classdef) rtyper.instance_reprs[classdef] = result - rtyper.reprs_must_call_setup.append(result) + rtyper.add_pendingsetup(result) return result class MissingRTypeAttribute(TyperError): @@ -93,8 +93,6 @@ class ClassRepr(Repr): - initialized = False - def __init__(self, rtyper, classdef): self.rtyper = rtyper self.classdef = classdef @@ -112,11 +110,7 @@ cls = self.classdef.cls return '' % (cls.__module__, cls.__name__) - def setup(self): - if self.initialized: - assert self.initialized == True - return - self.initialized = "in progress" + def _setup_repr(self): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these @@ -158,7 +152,6 @@ self.pbcfields = pbcfields self.allmethods = allmethods self.vtable = None - self.initialized = True def prepare_method(self, name, s_value, allmethods): # special-casing for methods: @@ -345,8 +338,6 @@ class InstanceRepr(Repr): - initialized = False - def __init__(self, rtyper, classdef): self.rtyper = rtyper self.classdef = classdef @@ -364,11 +355,7 @@ cls = self.classdef.cls return '' % (cls.__module__, cls.__name__) - def setup(self): - if self.initialized: - assert self.initialized == True - return - self.initialized = "in progress" + def _setup_repr(self): # NOTE: don't store mutable objects like the dicts below on 'self' # before they are fully built, to avoid strange bugs in case # of recursion where other code would uses these @@ -401,9 +388,8 @@ self.fields = fields self.allinstancefields = allinstancefields attachRuntimeTypeInfo(self.object_type) - self.initialized = True - def setup_final_touch(self): + def _setup_repr_final(self): self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT) Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Tue Jul 26 14:29:42 2005 @@ -30,7 +30,7 @@ self.value_repr = value_repr self.dict_cache = {} - def setup(self): + def _setup_repr(self): if isinstance(self.CONSTANTDICT, lltype.ForwardReference): self.DICTKEY = self.key_repr.lowleveltype self.DICTVALUE = self.value_repr.lowleveltype Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Tue Jul 26 14:29:42 2005 @@ -67,7 +67,7 @@ self.dict_cache = {} # setup() needs to be called to finish this initialization - def setup(self): + def _setup_repr(self): if 'value_repr' not in self.__dict__: self.value_repr = self._value_repr_computer() if isinstance(self.STRDICT, lltype.GcForwardReference): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Tue Jul 26 14:29:42 2005 @@ -57,7 +57,7 @@ self.list_cache = {} # setup() needs to be called to finish this initialization - def setup(self): + def _setup_repr(self): if 'item_repr' not in self.__dict__: self.item_repr = self._item_repr_computer() if isinstance(self.LIST, GcForwardReference): Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 26 14:29:42 2005 @@ -5,7 +5,15 @@ from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject from pypy.rpython.lltype import FuncType, functionptr from pypy.tool.ansi_print import ansi_print +from pypy.rpython.error import TyperError, MissingRTypeOperation +# initialization states for Repr instances + +class setupstate: + NOTINITIALIZED = 0 + INPROGRESS = 1 + BROKEN = 2 + FINISHED = 3 class Repr: """ An instance of Repr is associated with each instance of SomeXxx. @@ -16,27 +24,66 @@ iterating over. """ __metaclass__ = extendabletype + _initialized = setupstate.NOTINITIALIZED def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.lowleveltype) - def setup(self): + def setup(self): + """ call _setup_repr() and keep track of the initializiation + status to e.g. detect recursive _setup_repr invocations. + the '_initialized' attr has four states: + """ + if self._initialized == setupstate.FINISHED: + return + elif self._initialized == setupstate.BROKEN: + raise BrokenReprTyperError( + "cannot setup already failed Repr: %r" %(self,)) + elif self._initialized == setupstate.INPROGRESS: + raise AssertionError( + "recursive invocation of Repr setup(): %r" %(self,)) + assert self._initialized == setupstate.NOTINITIALIZED + self._initialized = setupstate.INPROGRESS + try: + self._setup_repr() + except TyperError, e: + self._initialized = setupstate.BROKEN + raise + else: + self._initialized = setupstate.FINISHED + + def _setup_repr(self): "For recursive data structure, which must be initialized in two steps." - def setup_final_touch(self): + def setup_final(self): """Same as setup(), called a bit later, for effects that are only needed after the typer finished (as opposed to needed for other parts of the typer itself).""" + if self._initialized == setupstate.BROKEN: + raise BrokenReprTyperError("cannot perform setup_final_touch " + "on failed Repr: %r" %(self,)) + assert self._initialized == setupstate.FINISHED, ( + "setup_final() on repr with state %s: %r" % + (self._initialized, self)) + self._setup_repr_final() + + def _setup_repr_final(self): + pass def __getattr__(self, name): # Assume that when an attribute is missing, it's because setup() needs # to be called - self.setup() - try: - return self.__dict__[name] - except KeyError: - raise AttributeError("%s instance has no attribute %s" % ( - self.__class__.__name__, name)) + if name[:2] != '__' or name[-2:] != '__': + if self._initialized != setupstate.NOTINITIALIZED: + warning("__getattr__ %r in strange state %r" %(name, self,)) + else: + self.setup() + try: + return self.__dict__[name] + except KeyError: + pass + raise AttributeError("%s instance has no attribute %s" % ( + self.__class__.__name__, name)) def _freeze_(self): return True @@ -148,15 +195,6 @@ # ____________________________________________________________ -class TyperError(Exception): - def __str__(self): - result = Exception.__str__(self) - if hasattr(self, 'where'): - result += '\n.. %r\n.. %r' % self.where - return result - -class MissingRTypeOperation(TyperError): - pass def missing_rtype_operation(self, hop): raise MissingRTypeOperation("unimplemented operation: '%s' on %r" % ( @@ -240,6 +278,11 @@ c.concretetype = lltype return c +class BrokenReprTyperError(TyperError): + """ raised when trying to setup a Repr whose setup + has failed already. + """ + # __________ utilities __________ PyObjPtr = Ptr(PyObject) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 26 14:29:42 2005 @@ -127,7 +127,7 @@ except KeyError: result = MultipleFrozenPBCRepr(rtyper, access) rtyper.pbc_reprs[access] = result - rtyper.reprs_must_call_setup.append(result) + rtyper.add_pendingsetup(result) return result @@ -183,8 +183,6 @@ class MultipleFrozenPBCRepr(Repr): """Representation selected for multiple non-callable pre-built constants.""" - initialized = False - def __init__(self, rtyper, access_set): self.rtyper = rtyper self.access_set = access_set @@ -192,11 +190,7 @@ self.lowleveltype = Ptr(self.pbc_type) self.pbc_cache = {} - def setup(self): - if self.initialized: - assert self.initialized == True - return - self.initialized = "in progress" + def _setup_repr(self): llfields = [] llfieldmap = {} if self.access_set is not None: @@ -210,7 +204,6 @@ llfieldmap[attr] = mangled_name, r_value self.pbc_type.become(Struct('pbc', *llfields)) self.llfieldmap = llfieldmap - self.initialized = True def convert_const(self, pbc): if pbc is None: Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jul 26 14:29:42 2005 @@ -24,7 +24,9 @@ from pypy.rpython.lltype import attachRuntimeTypeInfo, Primitive from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block -from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr +from pypy.rpython.rmodel import Repr, inputconst +from pypy.rpython.rmodel import TyperError, BrokenReprTyperError +from pypy.rpython.rmodel import getfunctionptr, warning from pypy.rpython.normalizecalls import perform_normalizations from pypy.rpython.annlowlevel import annotate_lowlevel_helper from pypy.rpython.exceptiondata import ExceptionData @@ -38,7 +40,8 @@ def __init__(self, annotator): self.annotator = annotator self.reprs = {} - self.reprs_must_call_setup = [] + self._reprs_must_call_setup = [] + self._seen_reprs_must_call_setup = {} self.specialized_ll_functions = {} self.class_reprs = {} self.instance_reprs = {} @@ -71,8 +74,14 @@ print '*' * len(s) self.crash_on_first_typeerror = True - - + def add_pendingsetup(self, repr): + assert isinstance(repr, Repr) + if repr in self._seen_reprs_must_call_setup: + warning("ignoring already seen repr for setup: %r" %(repr,)) + return + self._reprs_must_call_setup.append(repr) + self._seen_reprs_must_call_setup[repr] = True + def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -88,7 +97,7 @@ "missing a Ptr in the type specification " "of %s:\n%r" % (s_obj, result.lowleveltype)) self.reprs[key] = result - self.reprs_must_call_setup.append(result) + self.add_pendingsetup(result) return result def binding(self, var): @@ -153,35 +162,43 @@ # make sure all reprs so far have had their setup() called self.call_all_setups() - if self.typererrors: - c = 1 - for err in self.typererrors: - block, position = err.where - func = self.annotator.annotated.get(block, None) - if func: - func = "(%s:%s)" %(func.__module__ or '?', func.__name__) - else: - func = "(?:?)" - print "TyperError-%d: %s" % (c, func) - print str(err) - print "" - c += 1 + if self.typererrors: + self.dump_typererrors() 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.flowgraphs.values(): v = graph.getreturnvar() self.setconcretetype(v) + def dump_typererrors(self, num=None, minimize=True): + c = 0 + bc = 0 + for err in self.typererrors[:num]: + c += 1 + if minimize and isinstance(err, BrokenReprTyperError): + bc += 1 + continue + block, position = err.where + func = self.annotator.annotated.get(block, None) + if func: + func = "(%s:%s)" %(func.__module__ or '?', func.__name__) + else: + func = "(?:?)" + print "TyperError-%d: %s" % (c, func) + print str(err) + print "" + if bc: + print "(minimized %d errors away for this dump)" % (bc,) + def call_all_setups(self): # make sure all reprs so far have had their setup() called must_setup_more = [] - while self.reprs_must_call_setup: - r = self.reprs_must_call_setup.pop() + while self._reprs_must_call_setup: + r = self._reprs_must_call_setup.pop() r.setup() must_setup_more.append(r) for r in must_setup_more: - r.setup_final_touch() + r.setup_final() def setconcretetype(self, v): assert isinstance(v, Variable) Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Tue Jul 26 14:29:42 2005 @@ -76,7 +76,7 @@ from pypy.tool.ansi_print import ansi_print from pypy.translator.pickle.main import load, save # catch TyperError to allow for post-mortem dump -from pypy.rpython.rmodel import TyperError +from pypy.rpython.error import TyperError # XXX this tries to make compiling faster from pypy.translator.tool import buildpyxmodule @@ -112,6 +112,7 @@ a.simplify() if a and options['-fork']: from pypy.translator.goal import unixcheckpoint + assert_rpython_mostly_not_imported() unixcheckpoint.restartable_point(auto='run') if a and not options['-no-t']: print 'Specializing...' @@ -123,6 +124,19 @@ if a: t.frozen = True # cannot freeze if we don't have annotations +def assert_rpython_mostly_not_imported(): + prefix = 'pypy.rpython.' + oknames = 'rarithmetic extfunctable lltype objectmodel error'.split() + wrongimports = [] + for name, module in sys.modules.items(): + if module is not None and name.startswith(prefix): + sname = name[len(prefix):] + if sname not in oknames: + wrongimports.append(name) + if wrongimports: + raise RuntimeError("cannot fork because improper rtyper code" + " has already been imported: %r" %(wrongimports,)) + def sanity_check_exceptblocks(translator): annotator = translator.annotator irreg = 0 From arigo at codespeak.net Tue Jul 26 15:18:10 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 15:18:10 +0200 (CEST) Subject: [pypy-svn] r15120 - pypy/dist/pypy/translator/c/test Message-ID: <20050726131810.0A63727B64@code1.codespeak.net> Author: arigo Date: Tue Jul 26 15:18:08 2005 New Revision: 15120 Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Looking at the assembler produced by tcc, it seems to be a problem with tcc or the linker. Disable the test for now... Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Jul 26 15:18:08 2005 @@ -66,6 +66,8 @@ assert result[2] == os.stat(filename)[2] def test_os_fstat(): + if os.environ.get('PYPY_CC', '').startswith('tcc'): + py.test.skip("segfault with tcc :-(") filename = str(py.magic.autopath()) def call_fstat(): fd = os.open(filename, os.O_RDONLY, 0777) From tismer at codespeak.net Tue Jul 26 15:28:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 15:28:11 +0200 (CEST) Subject: [pypy-svn] r15124 - in pypy/dist/pypy: interpreter module/__builtin__ module/__builtin__/test module/marshal Message-ID: <20050726132811.9143027B64@code1.codespeak.net> Author: tismer Date: Tue Jul 26 15:28:08 2005 New Revision: 15124 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py pypy/dist/pypy/module/marshal/app_marshal.py Log: Richard & Chris: added getbuiltinmodule to objspace. changed marshal's r_long() to always return an int added basic .pyc file check to importing. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jul 26 15:28:08 2005 @@ -128,6 +128,11 @@ w_modules = self.sys.get('modules') self.setitem(w_modules, w_name, w_mod) + def getbuiltinmodule(self, name): + w_name = self.wrap(name) + w_modules = self.sys.get('modules') + return self.getitem(w_modules, w_name) + def make_builtins(self): "NOT_RPYTHON: only for initializing the space." Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 15:28:08 2005 @@ -3,7 +3,6 @@ """ import sys, os -import marshal from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError @@ -309,6 +308,17 @@ return w_mod +# helper, to avoid exposing internals ofmarshal +def r_long(fd): + a = ord(os.read(fd, 1)) + b = ord(os.read(fd, 1)) + c = ord(os.read(fd, 1)) + d = ord(os.read(fd, 1)) + x = a | (b<<8) | (c<<16) | (d<<24) + if d & 0x80 and x > 0: + x = -((1L<<32) - x) + return int(x) + def check_compiled_module(space, pathname, mtime, cpathname): """ Given a pathname for a Python source file, its time of last @@ -318,24 +328,22 @@ the header; if not, return NULL. Doesn't set an exception. """ - + #w_marshal = space.getbuiltinmodule('marshal') fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) # using no defaults - um = marshal.Unmarshaller(fd) - - magic = um.load_int() + magic = r_long(fd) if magic != pyc_magic: # XXX what to do about Py_VerboseFlag ? # PySys_WriteStderr("# %s has bad magic\n", cpathname); - os.close(fp) - return - pyc_mtime = um.load_int() + os.close(fd) + return -1 + pyc_mtime = r_long(fd) if pyc_mtime != mtime: # PySys_WriteStderr("# %s has bad mtime\n", cpathname); - os.close(fp) - return + os.close(fd) + return -1 # if (Py_VerboseFlag) # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); - return fp + return fd def load_compiled_module(space, name, cpathname, fd): """ Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Tue Jul 26 15:28:08 2005 @@ -27,12 +27,12 @@ cls.saved_modules = _setup(cls.space) def teardown_class(cls): # interpreter-level - _teardown(cls.space,cls.saved_modules) + _teardown(cls.space, cls.saved_modules) def test_import_bare_dir_fails(self): def imp(): import notapackage - raises(ImportError,imp) + raises(ImportError, imp) def test_import_sys(self): import sys @@ -152,7 +152,45 @@ def imp_b(): import pkg.pkg2.b raises(ImportError,imp_b) - + +from pypy.module.__builtin__ import importing + +class TestPycStuff: + # ___________________ .pyc related stuff _________________ + + def test_check_compiled_module(self): + import tempfile, marshal + + def getlong(data): + x = marshal.dumps(data) + return x[-4:] + + def testfile(magic, mtime): + fd, cpathname = tempfile.mkstemp() + os.close(fd) + f = file(cpathname, "wb") + f.write(getlong(magic)) + f.write(getlong(mtime)) + f.close() + return cpathname + + pathname = "whatever" + mtime = 12345 + cpathname = testfile(importing.pyc_magic, mtime) + ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) + assert ret >= 0 + assert os.lseek(ret, 0, 1) == 8 + os.close(ret) + # check for wrong mtime + ret = importing.check_compiled_module(self.space, pathname, mtime+1, cpathname) + assert ret < 0 + os.remove(cpathname) + # check for wrong version + cpathname = testfile(importing.pyc_magic+1, mtime) + ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) + assert ret < 0 + os.remove(cpathname) + def test_PYTHONPATH_takes_precedence(space): if sys.platform == "win32": py.test.skip("unresolved issues with win32 shell quoting rules") Modified: pypy/dist/pypy/module/marshal/app_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 15:28:08 2005 @@ -281,7 +281,7 @@ x = a | (b<<8) | (c<<16) | (d<<24) if d & 0x80 and x > 0: x = -((1L<<32) - x) - return x + return int(x) def r_long64(self): a = ord(self._read()) From pedronis at codespeak.net Tue Jul 26 15:35:42 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 26 Jul 2005 15:35:42 +0200 (CEST) Subject: [pypy-svn] r15125 - pypy/dist/pypy/rpython Message-ID: <20050726133542.62C5727B5E@code1.codespeak.net> Author: pedronis Date: Tue Jul 26 15:35:41 2005 New Revision: 15125 Modified: pypy/dist/pypy/rpython/rpbc.py Log: expand what is considered a builtin type Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 26 15:35:41 2005 @@ -48,7 +48,7 @@ if x in userclasses: # user classes choice = ClassesPBCRepr - elif type(x) is type and x.__module__ == '__builtin__': + elif type(x) is type and x.__module__ in sys.builtin_module_names: # special case for built-in types, seen in faking choice = getPyObjRepr else: From hpk at codespeak.net Tue Jul 26 15:55:55 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 15:55:55 +0200 (CEST) Subject: [pypy-svn] r15126 - pypy/extradoc/sprintinfo Message-ID: <20050726135555.27C8827B64@code1.codespeak.net> Author: hpk Date: Tue Jul 26 15:55:53 2005 New Revision: 15126 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: shallow ReST fix Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Tue Jul 26 15:55:53 2005 @@ -47,14 +47,14 @@ - we want to work on pypy/translator/goal/ISSUES.txt pairs:: + Samuele, Carl Friedrich (progressing on External functions) DONE: refactored math and os function out of annotation/builtin and rpython/rbuiltin into the extfunctable, implemented some math.*, os.* functions. fixed os.stat - Open issues: - - RPython string -> C null-terminated string - conversion. The null termination char is not there! + - RPython string -> C null-terminated string + conversion. The null termination char is not there! - The flow space kills exception handling for built-ins, this is not what we want e.g. for os.* functions; From rxe at codespeak.net Tue Jul 26 16:21:23 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 16:21:23 +0200 (CEST) Subject: [pypy-svn] r15127 - in pypy/dist/pypy/tool: . test Message-ID: <20050726142123.CD2FF27B74@code1.codespeak.net> Author: rxe Date: Tue Jul 26 16:21:21 2005 New Revision: 15127 Added: pypy/dist/pypy/tool/osfilewrapper.py pypy/dist/pypy/tool/test/test_osfilewrapper.py Log: Add a very simple os file wrapper. Added: pypy/dist/pypy/tool/osfilewrapper.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/osfilewrapper.py Tue Jul 26 16:21:21 2005 @@ -0,0 +1,36 @@ +import os + +class OsFileWrapper(object): + """ Very simple os file wrapper. + Note user is responsible for closing. + XXX Could add a simple buffer mechanism. """ + + def __init__(self, fd): + self.fd = fd + + def read(self, expected): + readcount = 0 + bufs = [] + while readcount < expected: + # os.read will raise an error itself + buf = os.read(self.fd, expected) + readcount += len(buf) + bufs.append(buf) + return "".join(bufs) + + def write(self, buf): + writecount = 0 + towrite = len(buf) + while writecount < towrite: + # os.write will raise an error itself + writecount += os.write(self.fd, buf) + buf = buf[writecount:] + + def close(self): + os.close(self.fd) + + def create_wrapper(cls, filename, flag, mode=0777): + fd = os.open(filename, flag, mode) + return cls(fd) + + create_wrapper = classmethod(create_wrapper) Added: pypy/dist/pypy/tool/test/test_osfilewrapper.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/test/test_osfilewrapper.py Tue Jul 26 16:21:21 2005 @@ -0,0 +1,32 @@ +import autopath +from pypy.tool.osfilewrapper import OsFileWrapper +from pypy.tool.udir import udir +import os + +def test_reads(): + + p = str(udir.join('test.dat')) + + # As we are testing file writes, only using udir to create a path + buf = "1234567890" + f = open(p, "w") + f.write(buf) + f.close() + + for ii in range(10): + f = OsFileWrapper.create_wrapper(p, os.O_RDONLY) + assert f.read(ii) == buf[:ii] + +def test_writes_reads(): + + # As we are testing file writes, only using udir to create a path + buf = "1234567890" + for ii in range(10): + p = str(udir.join('test.dat')) + f1 = OsFileWrapper.create_wrapper(p, os.O_WRONLY) + f1.write(buf[:ii]) + f1.close() + + f2 = OsFileWrapper.create_wrapper(p, os.O_RDONLY) + assert f2.read(ii) == buf[:ii] + f2.close() From cfbolz at codespeak.net Tue Jul 26 16:38:04 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 16:38:04 +0200 (CEST) Subject: [pypy-svn] r15128 - in pypy/dist/pypy: annotation rpython rpython/module rpython/test translator/c/test Message-ID: <20050726143804.5553327B76@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 16:38:02 2005 New Revision: 15128 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os_path.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/translator/c/test/test_extfunc.py Log: implemented isdir Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jul 26 16:38:02 2005 @@ -284,8 +284,6 @@ #BUILTIN_ANALYZERS[os.path.dirname] = pathpart #BUILTIN_ANALYZERS[os.path.normpath] = pathpart #BUILTIN_ANALYZERS[os.path.join] = pathpart -BUILTIN_ANALYZERS[os.path.exists] = test -BUILTIN_ANALYZERS[os.path.isdir] = test # import BUILTIN_ANALYZERS[__import__] = import_func Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Tue Jul 26 16:38:02 2005 @@ -79,6 +79,7 @@ declare(os.fstat , statannotation, 'll_os/fstat') declare(os.stat , statannotation, 'll_os/stat') declare(os.path.exists, bool , 'll_os_path/exists') +declare(os.path.isdir, bool , 'll_os_path/isdir') declare(time.time , float , 'll_time/time') declare(time.clock , float , 'll_time/clock') declare(time.sleep , noneannotation, 'll_time/sleep') 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 Tue Jul 26 16:38:02 2005 @@ -5,6 +5,7 @@ # see ll_os.py for comments import os +import stat from pypy.rpython.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 @@ -12,15 +13,6 @@ # Does a path exist? # This is false for dangling symbolic links. -## This version produces nonsense, keeping it for reference -## def ll_os_path_exists(path): -## """Test whether a path exists""" -## try: -## st = os.stat(from_rstr(path)) -## except OSError: -## return False -## return True - def ll_os_path_exists(path): """Test whether a path exists""" try: @@ -29,3 +21,10 @@ return False return True +def ll_os_path_isdir(path): + try: + st = ll_os_stat(path) + except OSError: + return False + return stat.S_ISDIR(st.item0) + Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 26 16:38:02 2005 @@ -129,6 +129,14 @@ assert interpret(f, [ to_rstr("strange_filename_that_looks_improbable.sde")]) == False +def test_os_isdir(): + import os + def f(fn): + return os.path.isdir(fn) + assert interpret(f, [to_rstr("/")]) == True + assert interpret(f, [to_rstr(str(py.magic.autopath()))]) == False + assert interpret(f, [to_rstr("another/unlikely/directory/name")]) == False + def test_pbc_isTrue(): class C: Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Tue Jul 26 16:38:02 2005 @@ -114,6 +114,18 @@ return os.path.exists(tmpfile) f = compile(fn, []) open(tmpfile, 'w').close() - assert f() is True + assert f() == True os.unlink(tmpfile) - assert f() is False + assert f() == False + +def test_os_path_isdir(): + directory = "./." + def fn(): + return os.path.isdir(directory) + f = compile(fn, []) + assert f() == True + directory = "some/random/name" + def fn(): + return os.path.isdir(directory) + f = compile(fn, []) + assert f() == False From rxe at codespeak.net Tue Jul 26 17:19:19 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 17:19:19 +0200 (CEST) Subject: [pypy-svn] r15129 - in pypy/dist/pypy/module/marshal: . test Message-ID: <20050726151919.D47BD27B76@code1.codespeak.net> Author: rxe Date: Tue Jul 26 17:19:18 2005 New Revision: 15129 Modified: pypy/dist/pypy/module/marshal/app_marshal.py pypy/dist/pypy/module/marshal/test/test_marshal_extra.py Log: Christian/Richard Use OsFileWrapper for marshal and add some tests to for load/dump and not just loads/dumps. Also show skipped any tests. Modified: pypy/dist/pypy/module/marshal/app_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 17:19:18 2005 @@ -4,6 +4,8 @@ import types import os +from pypy.tool.osfilewrapper import OsFileWrapper + try: import new except ImportError: @@ -37,12 +39,15 @@ dispatch = {} def __init__(self, fd): - self.fd = fd + if fd >= 0: + self.fd_wrapper = OsFileWrapper(fd) + else: + self.fd_wrapper = None self.buffer = [] def _write(self, data): - if self.fd >= 0: - os.write(self.fd, data) + if self.fd_wrapper is not None: + self.fd_wrapper.write(data) else: self.buffer.append(data) @@ -233,22 +238,25 @@ dispatch = {} def __init__(self, fd): - self.fd = fd + if fd >= 0: + self.fd_wrapper = OsFileWrapper(fd) + else: + self.fd_wrapper = None self.bufstr = '' self.bufpos = 0 self._stringtable = [] def _read(self): - if self.fd >= 0: - return self.fd.read(1) + if self.fd_wrapper is not None: + return self.fd_wrapper.read(1) else: ret = self.bufstr[self.bufpos] self.bufpos += 1 return ret def _readn(self, n): - if self.fd >= 0: - return self.fd.read(n) + if self.fd_wrapper is not None: + return self.fd_wrapper.read(n) else: ret = self.bufstr[self.bufpos : self.bufpos+n] self.bufpos += n Modified: pypy/dist/pypy/module/marshal/test/test_marshal_extra.py ============================================================================== --- pypy/dist/pypy/module/marshal/test/test_marshal_extra.py (original) +++ pypy/dist/pypy/module/marshal/test/test_marshal_extra.py Tue Jul 26 17:19:18 2005 @@ -1,8 +1,11 @@ +import py import autopath import sys import marshal as cpy_marshal from pypy.module.marshal import app_marshal as marshal +from pypy.tool.udir import udir + hello = "he" hello += "llo" def func(x): @@ -47,44 +50,90 @@ def test_cases(): for case in TESTCASES: - yield dump_and_reload, case + yield dumps_and_reload, case + yield loads_from_cpython, case + yield dumps_to_cpython, case + yield dumps_subclass, case yield load_from_cpython, case yield dump_to_cpython, case - yield dump_subclass, case -def dump_and_reload(case): +def dumps_and_reload(case): print 'dump_and_reload', `case` s = marshal.dumps(case) obj = marshal.loads(s) assert obj == case -def load_from_cpython(case): +def loads_from_cpython(case): print 'load_from_cpython', `case` try: s = cpy_marshal.dumps(case) except ValueError: - return # this version of CPython doesn't support this object + py.test.skip("this version of CPython doesn't support this object") obj = marshal.loads(s) assert obj == case -def dump_to_cpython(case): +def dumps_to_cpython(case): print 'dump_to_cpython', `case` try: cpy_marshal.dumps(case) except ValueError: - return # this version of CPython doesn't support this object + py.test.skip("this version of CPython doesn't support this object") s = marshal.dumps(case) obj = cpy_marshal.loads(s) assert obj == case -def dump_subclass(case): +def dumps_subclass(case): try: class Subclass(type(case)): pass case = Subclass(case) except TypeError: - return - print 'dump_subclass', `case` + py.test.skip("this version of CPython doesn't support this object") s = marshal.dumps(case) obj = marshal.loads(s) assert obj == case + +def load_from_cpython(case): + p = str(udir.join('test.dat')) + + f1 = open(p, "w") + try: + try: + s = cpy_marshal.dump(case, f1) + finally: + f1.close() + except ValueError: + py.test.skip("this version of CPython doesn't support this object") + + f2 = open(p, "r") + try: + obj = marshal.load(f2) + finally: + f2.close() + assert obj == case + +def dump_to_cpython(case): + + try: + cpy_marshal.dumps(case) + except ValueError: + py.test.skip("this version of CPython doesn't support this object") + + p = str(udir.join('test.dat')) + f1 = open(p, "w") + try: + try: + s = marshal.dump(case, f1) + finally: + f1.close() + except ValueError: + py.test.skip("this version of CPython doesn't support this object") + + f2 = open(p, "r") + try: + obj = cpy_marshal.load(f2) + finally: + f2.close() + assert obj == case + + From tismer at codespeak.net Tue Jul 26 17:38:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 17:38:26 +0200 (CEST) Subject: [pypy-svn] r15130 - in pypy/dist/pypy: module/__builtin__ module/__builtin__/test module/marshal tool Message-ID: <20050726153826.0646127B60@code1.codespeak.net> Author: tismer Date: Tue Jul 26 17:38:23 2005 New Revision: 15130 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py pypy/dist/pypy/module/marshal/__init__.py pypy/dist/pypy/module/marshal/app_marshal.py pypy/dist/pypy/tool/osfilewrapper.py Log: Richard & Chris: finished the binary loading support functions and tests. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 17:38:23 2005 @@ -7,6 +7,7 @@ from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.tool.osfilewrapper import OsFileWrapper # XXX this uses the os.path module at interp-level, which means # XXX that translate_pypy will produce a translated version of @@ -308,12 +309,12 @@ return w_mod -# helper, to avoid exposing internals ofmarshal -def r_long(fd): - a = ord(os.read(fd, 1)) - b = ord(os.read(fd, 1)) - c = ord(os.read(fd, 1)) - d = ord(os.read(fd, 1)) +# helper, to avoid exposing internals of marshal +def _r_long(osfile): + a = ord(osfile.read(1)) + b = ord(osfile.read(1)) + c = ord(osfile.read(1)) + d = ord(osfile.read(1)) x = a | (b<<8) | (c<<16) | (d<<24) if d & 0x80 and x > 0: x = -((1L<<32) - x) @@ -328,15 +329,15 @@ the header; if not, return NULL. Doesn't set an exception. """ - #w_marshal = space.getbuiltinmodule('marshal') fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) # using no defaults - magic = r_long(fd) + osfile = OsFileWrapper(fd) + magic = _r_long(osfile) if magic != pyc_magic: # XXX what to do about Py_VerboseFlag ? # PySys_WriteStderr("# %s has bad magic\n", cpathname); os.close(fd) return -1 - pyc_mtime = r_long(fd) + pyc_mtime = _r_long(osfile) if pyc_mtime != mtime: # PySys_WriteStderr("# %s has bad mtime\n", cpathname); os.close(fd) @@ -345,14 +346,38 @@ # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); return fd -def load_compiled_module(space, name, cpathname, fd): +def read_compiled_module(space, cpathname, fd): + """ Read a code object from a file and check it for validity """ + + w_marshal = space.getbuiltinmodule('marshal') + w_M = space.getattr(w_marshal, space.wrap('_Unmarshaller')) + w_unmarshaller = space.call_function(w_M, space.wrap(fd)) + w_code = space.call_method(w_unmarshaller, 'load') + pycode = space.interpclass_w(w_code) + if pycode is None: + raise OperationError(space.w_ImportError, space.wrap( + "Non-code object in %.200s" % cpathname)) + return pycode + +def load_compiled_module(space, w_modulename, w_mod, cpathname, fd): """ Load a module from a compiled file, execute it, and return its module object. """ - -def read_compiled_module(space, cpathname, fd): - """ Read a code object from a file and check it for validity """ + osfile = OsFileWrapper(fd) + magic = _r_long(osfile) + if magic != pyc_magic: + raise OperationError(space.w_ImportError, space.wrap( + "Bad magic number in %.200s" % cpathname)) + return NULL; + _r_long(osfile) # skip time stamp + code_w = read_compiled_module(space, cpathname, fd) + #if (Py_VerboseFlag) + # PySys_WriteStderr("import %s # precompiled from %s\n", + # name, cpathname); + w_dic = space.getattr(w_mod, space.wrap('__dict__')) + code_w.exec_code(space, w_dic, w_dic) + return w_mod def write_compiled_module(space, co, cpathname, mtime): Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Tue Jul 26 17:38:23 2005 @@ -1,7 +1,10 @@ import py +from pypy.interpreter.module import Module from pypy.interpreter import gateway +import pypy.interpreter.pycode from pypy.tool.udir import udir import sys, os +import tempfile, marshal def _setup(space): dn=os.path.abspath(os.path.join(os.path.dirname(__file__), 'impsubdir')) @@ -155,28 +158,28 @@ from pypy.module.__builtin__ import importing +def _getlong(data): + x = marshal.dumps(data) + return x[-4:] + +def _testfile(magic, mtime, co=None): + fd, cpathname = tempfile.mkstemp() + os.close(fd) + f = file(cpathname, "wb") + f.write(_getlong(magic)) + f.write(_getlong(mtime)) + if co: + marshal.dump(co, f) + f.close() + return cpathname + class TestPycStuff: # ___________________ .pyc related stuff _________________ def test_check_compiled_module(self): - import tempfile, marshal - - def getlong(data): - x = marshal.dumps(data) - return x[-4:] - - def testfile(magic, mtime): - fd, cpathname = tempfile.mkstemp() - os.close(fd) - f = file(cpathname, "wb") - f.write(getlong(magic)) - f.write(getlong(mtime)) - f.close() - return cpathname - pathname = "whatever" mtime = 12345 - cpathname = testfile(importing.pyc_magic, mtime) + cpathname = _testfile(importing.pyc_magic, mtime) ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) assert ret >= 0 assert os.lseek(ret, 0, 1) == 8 @@ -186,11 +189,44 @@ assert ret < 0 os.remove(cpathname) # check for wrong version - cpathname = testfile(importing.pyc_magic+1, mtime) + cpathname = _testfile(importing.pyc_magic+1, mtime) ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) assert ret < 0 os.remove(cpathname) + def test_read_compiled_module(self): + space = self.space + pathname = "whatever" + mtime = 12345 + co = compile('x = 42', '?', 'exec') + cpathname = _testfile(importing.pyc_magic, mtime, co) + fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) + os.lseek(fd, 8, 0) + code_w = importing.read_compiled_module(space, cpathname, fd) + os.close(fd) + assert type(code_w) is pypy.interpreter.pycode.PyCode + w_dic = space.newdict([]) + code_w.exec_code(space, w_dic, w_dic) + w_ret = space.getitem(w_dic, space.wrap('x')) + ret = space.int_w(w_ret) + assert ret == 42 + + def test_load_compiled_module(self): + space = self.space + pathname = "whatever" + mtime = 12345 + co = compile('x = 42', '?', 'exec') + cpathname = _testfile(importing.pyc_magic, mtime, co) + w_modulename = space.wrap('somemodule') + fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) + w_mod = space.wrap(Module(space, w_modulename)) + w_ret = importing.load_compiled_module(space, w_modulename, w_mod, cpathname, fd) + os.close(fd) + assert w_mod is w_ret + w_ret = space.getattr(w_mod, space.wrap('x')) + ret = space.int_w(w_ret) + assert ret == 42 + def test_PYTHONPATH_takes_precedence(space): if sys.platform == "win32": py.test.skip("unresolved issues with win32 shell quoting rules") Modified: pypy/dist/pypy/module/marshal/__init__.py ============================================================================== --- pypy/dist/pypy/module/marshal/__init__.py (original) +++ pypy/dist/pypy/module/marshal/__init__.py Tue Jul 26 17:38:23 2005 @@ -10,6 +10,8 @@ 'dumps' : 'app_marshal.dumps', 'load' : 'app_marshal.load', 'loads' : 'app_marshal.loads', + '_Marshaller' : 'app_marshal.Marshaller', + '_Unmarshaller' : 'app_marshal.Unmarshaller', } interpleveldefs = { Modified: pypy/dist/pypy/module/marshal/app_marshal.py ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/module/marshal/app_marshal.py Tue Jul 26 17:38:23 2005 @@ -271,7 +271,10 @@ c = self._read() if not c: raise EOFError - return self.dispatch[c](self) + try: + return self.dispatch[c](self) + except KeyError: + raise ValueError, "bad marshal code: %c (%d)" % (c, ord(c)) def r_short(self): lo = ord(self._read()) Modified: pypy/dist/pypy/tool/osfilewrapper.py ============================================================================== --- pypy/dist/pypy/tool/osfilewrapper.py (original) +++ pypy/dist/pypy/tool/osfilewrapper.py Tue Jul 26 17:38:23 2005 @@ -29,8 +29,7 @@ def close(self): os.close(self.fd) - def create_wrapper(cls, filename, flag, mode=0777): - fd = os.open(filename, flag, mode) - return cls(fd) - create_wrapper = classmethod(create_wrapper) +def create_wrapper(filename, flag, mode=0777): + fd = os.open(filename, flag, mode) + return OsFileWrapper(fd) From rxe at codespeak.net Tue Jul 26 17:42:29 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 17:42:29 +0200 (CEST) Subject: [pypy-svn] r15131 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050726154229.0E1BF27B60@code1.codespeak.net> Author: rxe Date: Tue Jul 26 17:42:27 2005 New Revision: 15131 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Added BIN_READMASK (linnx doesnt have O_BINARY). Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 17:42:27 2005 @@ -15,6 +15,11 @@ # XXX a frozen version of some routines of only one of the # XXX posixpath/ntpath/macpath modules. +try: + BIN_READMASK = os.O_BINARY | os.O_RDONLY +except AttributeError: + BIN_READMASK = os.O_RDONLY + def try_import_mod(space, w_modulename, filename, w_parent, w_name, pkgdir=None): if os.path.exists(filename): w = space.wrap @@ -262,6 +267,7 @@ header is skipped check for valid code object - load_compiled_module +- parse_source_module - load_source_module - write_compiled_module called by load_source_module (maybe also optional) @@ -281,11 +287,8 @@ its module object. """ -def load_source_module(space, w_modulename, w_mod, pathname, fd): - """ - Load a source module from a given file and return its module - object. XXX Wrong: If there's a matching byte-compiled file, use that instead. - """ +def parse_source_module(space, pathname, fd): + """ Parse a source file and return the corresponding code object """ w = space.wrap try: size = os.fstat(fd)[6] @@ -298,6 +301,15 @@ w_pathname = w(pathname) w_code = space.builtin.call('compile', w_source, w_pathname, w_mode) pycode = space.interpclass_w(w_code) + return pycode + +def load_source_module(space, w_modulename, w_mod, pathname, fd): + """ + Load a source module from a given file and return its module + object. XXX Wrong: If there's a matching byte-compiled file, use that instead. + """ + w = space.wrap + pycode = parse_source_module(space, pathname, fd) w_dict = space.getattr(w_mod, w('__dict__')) space.call_method(w_dict, 'setdefault', @@ -329,7 +341,7 @@ the header; if not, return NULL. Doesn't set an exception. """ - fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) # using no defaults + fd = os.open(cpathname, BIN_READMASK, 0777) # using no defaults osfile = OsFileWrapper(fd) magic = _r_long(osfile) if magic != pyc_magic: Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Tue Jul 26 17:42:27 2005 @@ -6,6 +6,8 @@ import sys, os import tempfile, marshal +from pypy.module.__builtin__.importing import BIN_READMASK + def _setup(space): dn=os.path.abspath(os.path.join(os.path.dirname(__file__), 'impsubdir')) return space.appexec([space.wrap(dn)], """ @@ -200,7 +202,7 @@ mtime = 12345 co = compile('x = 42', '?', 'exec') cpathname = _testfile(importing.pyc_magic, mtime, co) - fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) + fd = os.open(cpathname, BIN_READMASK, 0777) os.lseek(fd, 8, 0) code_w = importing.read_compiled_module(space, cpathname, fd) os.close(fd) @@ -218,7 +220,7 @@ co = compile('x = 42', '?', 'exec') cpathname = _testfile(importing.pyc_magic, mtime, co) w_modulename = space.wrap('somemodule') - fd = os.open(cpathname, os.O_BINARY | os.O_RDONLY, 0777) + fd = os.open(cpathname, BIN_READMASK, 0777) w_mod = space.wrap(Module(space, w_modulename)) w_ret = importing.load_compiled_module(space, w_modulename, w_mod, cpathname, fd) os.close(fd) From cfbolz at codespeak.net Tue Jul 26 18:12:47 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 18:12:47 +0200 (CEST) Subject: [pypy-svn] r15132 - pypy/dist/pypy/module/posix Message-ID: <20050726161247.8384A27B6C@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 18:12:46 2005 New Revision: 15132 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py Log: (pedronis, cfbolz): - added constants to PyPy's posix module - fixed interp_posix: you have to wrap return values! Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Tue Jul 26 18:12:46 2005 @@ -1,6 +1,8 @@ # Package initialisation from pypy.interpreter.mixedmodule import MixedModule - + +import os + class Module(MixedModule): appleveldefs = { 'error' : 'app_posix.error', @@ -20,3 +22,18 @@ '__doc__' : "space.wrap('Posix module')", '__name__' : "space.wrap('The builtin posix module')", } + +for constant in ['EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', + 'EX_NOHOST', 'EX_NOINPUT', 'EX_NOPERM', 'EX_NOUSER', + 'EX_OK', 'EX_OSERR', 'EX_OSFILE', 'EX_PROTOCOL', + 'EX_SOFTWARE', 'EX_TEMPFAIL', 'EX_UNAVAILABLE', 'EX_USAGE', + 'F_OK', 'NGROUPS_MAX', 'O_APPEND', 'O_CREAT', 'O_DIRECT', + 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_LARGEFILE', 'O_NDELAY', + 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_RDONLY', 'O_RDWR', + 'O_RSYNC', 'O_SYNC', 'O_TRUNC', 'O_WRONLY', 'R_OK', 'TMP_MAX', + 'W_OK', 'X_OK']: + try: + Module.interpleveldefs[constant] = ("space.wrap(%s)" % + (getattr(os, constant), )) + except AttributeError: + pass \ No newline at end of file Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Tue Jul 26 18:12:46 2005 @@ -17,15 +17,15 @@ lseek.unwrap_spec = [ObjSpace, int, int, int] def isatty(space, fd): - return os.isatty(w_fd) + return space.wrap(os.isatty(w_fd)) isatty.unwrap_spec = [ObjSpace, int] def read(space, fd, buffersize): - return os.read(fd,buffersize) + return space.wrap(os.read(fd,buffersize)) read.unwrap_spec = [ObjSpace, int, int] def write(space, fd, data): - return os.write( fd, data) + return space.wrap(os.write(fd, data)) write.unwrap_spec = [ObjSpace, int, str] def close(space, fd): @@ -37,17 +37,17 @@ ftruncate.unwrap_spec = [ObjSpace, int, int] def fstat(space, fd): - return os.fstat(fd) + return space.wrap(os.fstat(fd)) fstat.unwrap_spec = [ObjSpace, int] def stat(space, path): - return os.stat(path) + return space.wrap(os.stat(path)) stat.unwrap_spec = [ObjSpace, str] def getcwd(space): - return os.getcwd() + return space.wrap(os.getcwd()) getcwd.unwrap_spec = [ObjSpace] def dup(space, fd): - return os.dup(fd) + return space.wrap(os.dup(fd)) dup.unwrap_spec = [ObjSpace, int] \ No newline at end of file From hpk at codespeak.net Tue Jul 26 18:56:40 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 18:56:40 +0200 (CEST) Subject: [pypy-svn] r15133 - in pypy/dist/pypy: . lib module/__builtin__ module/sys module/sys/test objspace/std objspace/std/test tool translator/goal Message-ID: <20050726165640.A97CA27B6C@code1.codespeak.net> Author: hpk Date: Tue Jul 26 18:56:37 2005 New Revision: 15133 Added: pypy/dist/pypy/module/__builtin__/app_file_stub.py pypy/dist/pypy/module/__builtin__/state.py Removed: pypy/dist/pypy/objspace/std/test/test_nonfakefile.py pypy/dist/pypy/translator/goal/targetpypy.py Modified: pypy/dist/pypy/conftest.py pypy/dist/pypy/lib/_file.py pypy/dist/pypy/module/__builtin__/__init__.py pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/state.py pypy/dist/pypy/module/sys/test/test_sysmodule.py pypy/dist/pypy/objspace/std/fake.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: (arfigo, hufpk) - completely got rid of "faking " when we start py.py --file. - lib-python/conftest.py is a bit broken now. More clean-up is needed regarding the way the options are applied: the object spaces should do their initialization completely based on the 'options' they get instead of being patched from the outside. - another problem is that applevel tests print output is not captured anymore (conftest.py needs enhancements) - removed targetpypy.py because it isn't used anymore Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Tue Jul 26 18:56:37 2005 @@ -42,10 +42,13 @@ try: return _spacecache[name] except KeyError: + import pypy.tool.option + spaceoptions = pypy.tool.option.Options() + spaceoptions.uselibfile = option.uselibfile #py.magic.invoke(compile=True) module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) try: - space = module.Space() + space = module.Space(spaceoptions) except KeyboardInterrupt: raise except OperationError, e: @@ -63,11 +66,6 @@ _spacecache[name] = space if name == 'std' and option.oldstyle: space.enable_old_style_classes_as_default_metaclass() - if option.uselibfile: - space.appexec([], '''(): - from _file import file - __builtins__.file = __builtins__.open = file - ''') if name != 'flow': # not sensible for flow objspace case space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), appsupport.build_pytest_assertion(space)) Modified: pypy/dist/pypy/lib/_file.py ============================================================================== --- pypy/dist/pypy/lib/_file.py (original) +++ pypy/dist/pypy/lib/_file.py Tue Jul 26 18:56:37 2005 @@ -85,13 +85,14 @@ def fdopen(cls, fd, mode='r', buffering=None): f = cls.__new__(cls) - - f.fd = fd - f._name = "" - f._inithelper(mode, buffering) + f._fdopen(fd, mode, buffering, '') return f - fdopen = classmethod(fdopen) + + def _fdopen(self, fd, mode, buffering, name): + self.fd = fd + self._name = name + self._inithelper(mode, buffering) def _inithelper(self, mode, buffering): self._mode = mode Modified: pypy/dist/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/__init__.py (original) +++ pypy/dist/pypy/module/__builtin__/__init__.py Tue Jul 26 18:56:37 2005 @@ -52,6 +52,8 @@ 'set' : 'app_sets.set', 'frozenset' : 'app_sets.frozenset', + + '__filestub' : 'app_file_stub.file', } interpleveldefs = { @@ -64,10 +66,11 @@ '__debug__' : '(space.w_True)', # XXX 'type' : '(space.w_type)', 'object' : '(space.w_object)', - 'file' : '(space.wrap(file))', - 'open' : '(space.wrap(file))', 'unicode' : '(space.w_unicode)', + 'file' : 'state.get(space).w_file', + 'open' : 'state.get(space).w_file', + # old-style classes dummy support '_classobj' : 'space.w_classobj', '_instance' : 'space.w_instance', Added: pypy/dist/pypy/module/__builtin__/app_file_stub.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/app_file_stub.py Tue Jul 26 18:56:37 2005 @@ -0,0 +1,20 @@ +# NOT_RPYTHON + +class file(object): + """file(name[, mode[, buffering]]) -> file object + +Open a file. The mode can be 'r', 'w' or 'a' for reading (default), +writing or appending. The file will be created if it doesn't exist +when opened for writing or appending; it will be truncated when +opened for writing. Add a 'b' to the mode for binary files. +Add a '+' to the mode to allow simultaneous reading and writing. +If the buffering argument is given, 0 means unbuffered, 1 means line +buffered, and larger numbers specify the buffer size. +Add a 'U' to mode to open the file for input with universal newline +support. Any line ending in the input file will be seen as a '\n' +in Python. Also, a file so opened gains the attribute 'newlines'; +the value for this attribute is one of None (no newline read yet), +'\r', '\n', '\r\n' or a tuple containing all the newline types seen. + +Note: open() is an alias for file(). +""" Added: pypy/dist/pypy/module/__builtin__/state.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/state.py Tue Jul 26 18:56:37 2005 @@ -0,0 +1,10 @@ + +class State: + def __init__(self, space): + if space.options.uselibfile: + self.w_file = space.builtin.get('__filestub') + else: + self.w_file = space.wrap(file) + +def get(space): + return space.fromcache(State) Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Tue Jul 26 18:56:37 2005 @@ -20,12 +20,12 @@ 'prefix' : 'space.wrap(sys.prefix)', 'maxunicode' : 'space.wrap(sys.maxunicode)', 'maxint' : 'space.wrap(sys.maxint)', - 'stdin' : 'space.wrap(sys.stdin)', - '__stdin__' : 'space.wrap(sys.stdin)', - 'stdout' : 'space.wrap(sys.stdout)', - '__stdout__' : 'space.wrap(sys.stdout)', - 'stderr' : 'space.wrap(sys.stderr)', - '__stderr__' : 'space.wrap(sys.stderr)', + 'stdin' : 'state.getio(space).w_stdin', + '__stdin__' : 'state.getio(space).w_stdin', + 'stdout' : 'state.getio(space).w_stdout', + '__stdout__' : 'state.getio(space).w_stdout', + 'stderr' : 'state.getio(space).w_stderr', + '__stderr__' : 'state.getio(space).w_stderr', 'pypy_objspaceclass' : 'space.wrap(repr(space))', 'path' : 'state.get(space).w_path', Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Tue Jul 26 18:56:37 2005 @@ -76,6 +76,21 @@ def get(space): return space.fromcache(State) +class IOState: + def __init__(self, space): + self.space = space + if space.options.uselibfile: + self.w_stdout = space.call_function(space.builtin.get('file')) + self.w_stderr = space.call_function(space.builtin.get('file')) + self.w_stdin = space.call_function(space.builtin.get('file')) + else: + self.w_stdout = space.wrap(sys.__stdout__) + self.w_stderr = space.wrap(sys.__stderr__) + self.w_stdin = space.wrap(sys.__stdin__) + +def getio(space): + return space.fromcache(IOState) + def _pypy_getudir(space): """NOT_RPYTHON""" from pypy.tool.udir import udir Modified: pypy/dist/pypy/module/sys/test/test_sysmodule.py ============================================================================== --- pypy/dist/pypy/module/sys/test/test_sysmodule.py (original) +++ pypy/dist/pypy/module/sys/test/test_sysmodule.py Tue Jul 26 18:56:37 2005 @@ -96,6 +96,16 @@ else: raise AssertionError, "ZeroDivisionError not caught" +def app_test_io(): + #space.appexec([], """(): + import sys + assert isinstance(sys.stdout, file) + assert isinstance(sys.__stdout__, file) + assert isinstance(sys.stderr, file) + assert isinstance(sys.__stderr__, file) + assert isinstance(sys.stdin, file) + assert isinstance(sys.__stdin__, file) + #""") class AppTestSysModulePortedFromCPython: Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Tue Jul 26 18:56:37 2005 @@ -12,9 +12,12 @@ def fake_object(space, x): + if isinstance(x, file): + debug_print("fake-wrapping interp file %s" % x) if isinstance(x, type): ft = fake_type(x) return space.gettypeobject(ft.typedef) + #debug_print("faking obj %s" % x) ft = fake_type(type(x)) return ft(space, x) fake_object._annspecialcase_ = "override:fake_object" @@ -56,6 +59,7 @@ def really_build_fake_type(cpy_type): "NOT_RPYTHON (not remotely so!)." + #assert not issubclass(cpy_type, file), cpy_type debug_print('faking %r'%(cpy_type,)) kw = {} Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue Jul 26 18:56:37 2005 @@ -1,6 +1,6 @@ from pypy.objspace.std.register_all import register_all from pypy.interpreter.baseobjspace import ObjSpace, BaseWrappable -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError, debug_print from pypy.interpreter.typedef import get_unique_interplevel_subclass from pypy.interpreter.typedef import instantiate from pypy.interpreter.gateway import PyPyCacheDir @@ -92,6 +92,9 @@ dict.fromkeys = classmethod(fromkeys) """) + if self.options.uselibfile: + self.setuselibfile() + def enable_old_style_classes_as_default_metaclass(self): self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj) @@ -124,26 +127,34 @@ self.w_classobj = w_classobj self.w_instance = w_instance - def unfakefile(self): + def setuselibfile(self): """ NOT_RPYTHON use our application level file implementation including re-wrapping sys.stdout/err/in """ + assert self.options.uselibfile + space = self + # nice print helper if the below does not work + # (we dont have prints working at applevel before + # setuselibfile is complete) + #from pypy.interpreter import gateway + #def printit(space, w_msg): + # s = space.str_w(w_msg) + # print "$", s, + #w_p = space.wrap(gateway.interp2app(printit)) + #self.appexec([w_p], '''(p): self.appexec([], '''(): - from _file import file - __builtins__.file = __builtins__.open = file - import sys - sys.stdout = file.fdopen(sys.stdout.fileno(), - sys.stdout.mode, - buffering=1) - sys.stdin = file.fdopen(sys.stdin.fileno(), - sys.stdin.mode, - buffering=1) - sys.stderr = file.fdopen(sys.stderr.fileno(), - sys.stderr.mode, - buffering=0) - sys.__stdout__ = sys.stdout - sys.__stderr__ = sys.stderr - sys.__stdin__ = sys.stdin + import sys + sys.stdin + sys.stdout + sys.stderr # force unlazifying from mixedmodule + from _file import file as libfile + for name, value in libfile.__dict__.items(): + if (name != '__dict__' and name != '__doc__' + and name != '__module__'): + setattr(file, name, value) + sys.stdin._fdopen(0, "r", 1, '') + sys.stdout._fdopen(1, "w", 1, '') + sys.stderr._fdopen(2, "w", 0, '') ''') def setup_exceptions(self): Deleted: /pypy/dist/pypy/objspace/std/test/test_nonfakefile.py ============================================================================== --- /pypy/dist/pypy/objspace/std/test/test_nonfakefile.py Tue Jul 26 18:56:37 2005 +++ (empty file) @@ -1,24 +0,0 @@ - -import autopath -from pypy.tool.udir import udir -import py -import sys - -pypypath = str(py.path.local(autopath.pypydir).join('bin', 'py.py')) - -def test_nonfake_stdfile(): - """ """ - uselibfile = udir.join('uselibfile.py') - uselibfile.write("""if 1: - import sys - assert not _isfake(sys.stdin) - assert not _isfake(sys.stdout) - assert not _isfake(sys.stderr) - assert not _isfake(sys.__stdin__) - assert not _isfake(sys.__stdout__) - assert not _isfake(sys.__stderr__) - print "ok" - """) - output = py.process.cmdexec( '''"%s" "%s" --file "%s"''' % - (sys.executable, pypypath, uselibfile) ) - assert output.splitlines()[-1] == "ok" Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Tue Jul 26 18:56:37 2005 @@ -89,7 +89,4 @@ space = Space( Options() ) if name == 'std' and Options.oldstyle: space.enable_old_style_classes_as_default_metaclass() - if Options.uselibfile: - space.unfakefile() - return _spacecache.setdefault(name, space) Deleted: /pypy/dist/pypy/translator/goal/targetpypy.py ============================================================================== --- /pypy/dist/pypy/translator/goal/targetpypy.py Tue Jul 26 18:56:37 2005 +++ (empty file) @@ -1,32 +0,0 @@ -import buildcache2 -from pypy.objspace.std.objspace import StdObjSpace, W_Object -from pypy.objspace.std.intobject import W_IntObject - -# __________ Entry point __________ - -def entry_point(): - w_a = W_IntObject(space, -6) - w_b = W_IntObject(space, -7) - return space.mul(w_a, w_b) - -# _____ Define and setup target ___ - -def target(): - global space - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - space = StdObjSpace() - # call cache filling code - buildcache2.buildcache(space) - # further call the entry_point once to trigger building remaining - # caches (as far as analyzing the entry_point is concerned) - entry_point() - - return entry_point, [] - -# _____ Run translated _____ -def run(c_entry_point): - w_result = c_entry_point() - print w_result - print w_result.intval - assert w_result.intval == 42 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Tue Jul 26 18:56:37 2005 @@ -38,8 +38,10 @@ # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False - space = StdObjSpace() - space.unfakefile() + from pypy.tool import Options + options = Options() + options.uselibfile = True + space = StdObjSpace(options) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From rxe at codespeak.net Tue Jul 26 19:28:01 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 19:28:01 +0200 (CEST) Subject: [pypy-svn] r15134 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050726172801.7994827B6C@code1.codespeak.net> Author: rxe Date: Tue Jul 26 19:27:51 2005 New Revision: 15134 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Christian and Richard Added support to try_import_mod() to load pyc or py files depending on the state. Some small mods to the check_compiled_module() and fix tests. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 19:27:51 2005 @@ -20,38 +20,112 @@ except AttributeError: BIN_READMASK = os.O_RDONLY -def try_import_mod(space, w_modulename, filename, w_parent, w_name, pkgdir=None): - if os.path.exists(filename): - w = space.wrap - w_mod = w(Module(space, w_modulename)) - space.sys.setmodule(w_mod) - space.setattr(w_mod, w('__file__'), space.wrap(filename)) - space.setattr(w_mod, w('__doc__'), space.w_None) - if pkgdir is not None: - space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) +NOFILE = 0 +PYFILE = 1 +PYCFILE = 2 - e = None - try: - fd = os.open(filename, os.O_RDONLY, 0777) # XXX newlines? - load_source_module(space, w_modulename, w_mod, filename, fd) +import stat - except OperationError, e: - if e.match(space, space.w_SyntaxError): - w_mods = space.sys.get('modules') - try: - space.delitem(w_mods, w_modulename) - except OperationError, kerr: - if not kerr.match(space, space.w_KeyError): - raise - w_mod = check_sys_modules(space, w_modulename) - if w_mod is not None and w_parent is not None: - space.setattr(w_parent, w_name, w_mod) - if e: - raise e - return w_mod +def info_modtype(filepart): + """ + calculate whether the .py file exists, the .pyc file exists + and whether the .pyc file has the correct mtime entry. + The latter is only true if the .py file exists. + The .pyc file is only considered existing if it has a valid + magic number. + """ + pyfile = filepart + ".py" + pyfile_exist = False + if os.path.exists(pyfile): + pyfile_ts = os.stat(pyfile)[stat.ST_MTIME] + pyfile_exist = True else: + pyfile_ts = 0 + pyfile_exist = False + + pycfile = filepart + ".pyc" + if os.path.exists(pycfile): + pyc_state = check_compiled_module(pyfile, pyfile_ts, pycfile) + pycfile_exists = pyc_state >= 0 + pycfile_ts_valid = pycfile_state > 0 and pyfile_exists + else: + pycfile_exists = False + pycfile_ts_valid = False + + return pyfile_exist, pycfile_exists, pycfile_ts_valid + +def find_modtype(filepart): + """ This is the way pypy does it. A pyc is only used if the py file exists AND + the pyc file contains the timestamp of the py. """ + pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(filepart) + if pycfile_ts_valid: + return PYCFILE + elif pyfile_exist: + return PYFILE + else: + return NOFILE + +def find_modtype_cpython(filepart): + """ This is the way cpython does it (where the py file doesnt exist but there + is a valid pyc file. """ + pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(filepart) + if pycfile_ts_valid: + return PYCFILE + elif pyfile_exist: + return PYFILE + elif pycfile_exists: + return PYCFILE + else: + return NOFILE + +def try_import_mod(space, w_modulename, filepart, w_parent, w_name, pkgdir=None): + + # decide what type we want (pyc/py) + modtype = find_modtype(filepart) + + if modtype == NOFILE: return None + w = space.wrap + w_mod = w(Module(space, w_modulename)) + + e = None + if modtype == PYFILE: + filename = filepart + ".py" + fd = os.open(filename, os.O_RDONLY, 0777) + else: + assert modtype == PYCFILE + filename = filepart + ".pyc" + fd = os.open(filename, os.O_RDONLY, 0777) + + space.sys.setmodule(w_mod) + space.setattr(w_mod, w('__file__'), space.wrap(filename)) + space.setattr(w_mod, w('__doc__'), space.w_None) + if pkgdir is not None: + space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) + + try: + if modtype == PYFILE: + load_source_module(space, w_modulename, w_mod, filename, fd) + else: + load_compiled_module(space, w_modulename, w_mod, filename, fd) + + except OperationError, e: + if e.match(space, space.w_SyntaxError): + w_mods = space.sys.get('modules') + try: + space.delitem(w_mods, w_modulename) + except OperationError, kerr: + if not kerr.match(space, space.w_KeyError): + raise + + w_mod = check_sys_modules(space, w_modulename) + if w_mod is not None and w_parent is not None: + space.setattr(w_parent, w_name, w_mod) + if e: + raise e + return w_mod + def try_getattr(space, w_obj, w_name): try: return space.getattr(w_obj, w_name) @@ -187,12 +261,12 @@ for path in space.unpackiterable(w_path): dir = os.path.join(space.str_w(path), partname) if os.path.isdir(dir): - fn = os.path.join(dir, '__init__.py') + fn = os.path.join(dir, '__init__') w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname), pkgdir=dir) if w_mod is not None: return w_mod - fn = os.path.join(space.str_w(path), partname + '.py') + fn = os.path.join(space.str_w(path), partname) w_mod = try_import_mod(space, w_modulename, fn, w_parent, w(partname)) if w_mod is not None: @@ -286,6 +360,7 @@ Load an external module using the default search path and return its module object. """ + def parse_source_module(space, pathname, fd): """ Parse a source file and return the corresponding code object """ @@ -332,7 +407,7 @@ x = -((1L<<32) - x) return int(x) -def check_compiled_module(space, pathname, mtime, cpathname): +def check_compiled_module(pathname, mtime, cpathname): """ Given a pathname for a Python source file, its time of last modification, and a pathname for a compiled file, check whether the @@ -344,19 +419,20 @@ fd = os.open(cpathname, BIN_READMASK, 0777) # using no defaults osfile = OsFileWrapper(fd) magic = _r_long(osfile) - if magic != pyc_magic: - # XXX what to do about Py_VerboseFlag ? - # PySys_WriteStderr("# %s has bad magic\n", cpathname); - os.close(fd) - return -1 - pyc_mtime = _r_long(osfile) - if pyc_mtime != mtime: - # PySys_WriteStderr("# %s has bad mtime\n", cpathname); + try: + if magic != pyc_magic: + # XXX what to do about Py_VerboseFlag ? + # PySys_WriteStderr("# %s has bad magic\n", cpathname); + return -1 + pyc_mtime = _r_long(osfile) + if pyc_mtime != mtime: + # PySys_WriteStderr("# %s has bad mtime\n", cpathname); + return 0 + # if (Py_VerboseFlag) + # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); + finally: os.close(fd) - return -1 - # if (Py_VerboseFlag) - # PySys_WriteStderr("# %s matches %s\n", cpathname, pathname); - return fd + return 1 def read_compiled_module(space, cpathname, fd): """ Read a code object from a file and check it for validity """ Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Tue Jul 26 19:27:51 2005 @@ -182,18 +182,18 @@ pathname = "whatever" mtime = 12345 cpathname = _testfile(importing.pyc_magic, mtime) - ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) - assert ret >= 0 - assert os.lseek(ret, 0, 1) == 8 - os.close(ret) + ret = importing.check_compiled_module(pathname, mtime, cpathname) + assert ret == 1 + # check for wrong mtime - ret = importing.check_compiled_module(self.space, pathname, mtime+1, cpathname) - assert ret < 0 + ret = importing.check_compiled_module(pathname, mtime+1, cpathname) + assert ret == 0 os.remove(cpathname) + # check for wrong version cpathname = _testfile(importing.pyc_magic+1, mtime) - ret = importing.check_compiled_module(self.space, pathname, mtime, cpathname) - assert ret < 0 + ret = importing.check_compiled_module(pathname, mtime, cpathname) + assert ret == -1 os.remove(cpathname) def test_read_compiled_module(self): From arigo at codespeak.net Tue Jul 26 19:28:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 19:28:46 +0200 (CEST) Subject: [pypy-svn] r15135 - in pypy/dist/pypy/lib: . test2 Message-ID: <20050726172846.295C627B68@code1.codespeak.net> Author: arigo Date: Tue Jul 26 19:28:44 2005 New Revision: 15135 Modified: pypy/dist/pypy/lib/_file.py pypy/dist/pypy/lib/test2/test_file_extra.py Log: Added file.__repr__. Modified: pypy/dist/pypy/lib/_file.py ============================================================================== --- pypy/dist/pypy/lib/_file.py (original) +++ pypy/dist/pypy/lib/_file.py Tue Jul 26 19:28:44 2005 @@ -355,3 +355,10 @@ if self._closed: raise ValueError('I/O operation on closed file') return os.isatty(self.fd) + + def __repr__(self): + return '<%s file %r, mode %r at 0x%x>' % ( + self._closed and 'closed' or 'open', + self._name, + self._mode, + id(self)) Modified: pypy/dist/pypy/lib/test2/test_file_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_file_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_file_extra.py Tue Jul 26 19:28:44 2005 @@ -24,6 +24,12 @@ for i in range(-1, 10): assert self.file.readline(i) == cpyfile.readline(i) + def test_repr(self): + r = repr(self.file) + assert r.find('open file') >= 0 + assert r.find(self.file.name) >= 0 + assert r.find(self.file.mode) >= 0 + class TestFdFile(TestFile): def setup_method(self, method): import os From rxe at codespeak.net Tue Jul 26 19:45:08 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 19:45:08 +0200 (CEST) Subject: [pypy-svn] r15136 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726174508.94F7327B41@code1.codespeak.net> Author: rxe Date: Tue Jul 26 19:45:07 2005 New Revision: 15136 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: typo Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 19:45:07 2005 @@ -47,7 +47,7 @@ if os.path.exists(pycfile): pyc_state = check_compiled_module(pyfile, pyfile_ts, pycfile) pycfile_exists = pyc_state >= 0 - pycfile_ts_valid = pycfile_state > 0 and pyfile_exists + pycfile_ts_valid = pyc_state > 0 and pyfile_exists else: pycfile_exists = False pycfile_ts_valid = False From tismer at codespeak.net Tue Jul 26 19:45:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 19:45:39 +0200 (CEST) Subject: [pypy-svn] r15137 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726174539.2765627B74@code1.codespeak.net> Author: tismer Date: Tue Jul 26 19:45:37 2005 New Revision: 15137 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: pyc file writing support, untested Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 19:45:37 2005 @@ -17,8 +17,10 @@ try: BIN_READMASK = os.O_BINARY | os.O_RDONLY + BIN_WRITEMASK = os.O_BINARY | os.O_RDWR except AttributeError: BIN_READMASK = os.O_RDONLY + BIN_WRITEMASK = os.O_RDWR NOFILE = 0 PYFILE = 1 @@ -329,44 +331,11 @@ pyc_magic = MAGIC -PLAN = """ -have a function that finds a .py or .pyc file and decides what to use. - -CPython: Looks into both and uses .pyc if alone. -We want this option, too, but disabled. - -implement -- check_compiled_module() -- read_compiled_module - header is skipped - check for valid code object -- load_compiled_module -- parse_source_module -- load_source_module -- write_compiled_module - called by load_source_module (maybe also optional) - -- load_module - loads what it gets, flag controls mode decision. - move the module creation stuff from try_import_mod into - load_module. - -modify imp_execfile to accept .pyc files as well. -The decision what to use has been driven, already. -""" - -def load_module(space, name, fd, type): # XXX later: loader): - """ - Load an external module using the default search path and return - its module object. - """ - - def parse_source_module(space, pathname, fd): """ Parse a source file and return the corresponding code object """ w = space.wrap try: - size = os.fstat(fd)[6] + size = os.fstat(fd)[stat.ST_SIZE] source = os.read(fd, size) finally: os.close(fd) @@ -381,7 +350,7 @@ def load_source_module(space, w_modulename, w_mod, pathname, fd): """ Load a source module from a given file and return its module - object. XXX Wrong: If there's a matching byte-compiled file, use that instead. + object. """ w = space.wrap pycode = parse_source_module(space, pathname, fd) @@ -392,7 +361,9 @@ w(space.builtin)) pycode.exec_code(space, w_dict, w_dict) - #XXX write file + mtime = os.stat(fd)[stat.ST_MTIME] + cpathname = pathname + 'c' + write_compiled_module(space, pycode, cpathname, mtime) return w_mod @@ -407,6 +378,16 @@ x = -((1L<<32) - x) return int(x) +def _w_long(osfile, x): + a = x & 0xff + x >> = 8 + b = x & 0xff + x >> = 8 + c = x & 0xff + x >> = 8 + d = x & 0xff + osfile.write(chr(a) + chr(b) + chr(c) + chr(d)) + def check_compiled_module(pathname, mtime, cpathname): """ Given a pathname for a Python source file, its time of last @@ -438,8 +419,8 @@ """ Read a code object from a file and check it for validity """ w_marshal = space.getbuiltinmodule('marshal') - w_M = space.getattr(w_marshal, space.wrap('_Unmarshaller')) - w_unmarshaller = space.call_function(w_M, space.wrap(fd)) + w_U = space.getattr(w_marshal, space.wrap('_Unmarshaller')) + w_unmarshaller = space.call_function(w_U, space.wrap(fd)) w_code = space.call_method(w_unmarshaller, 'load') pycode = space.interpclass_w(w_code) if pycode is None: @@ -475,3 +456,12 @@ Errors are ignored, if a write error occurs an attempt is made to remove the file. """ + fd = os.open(cpathname, BIN_WRITEMASK, 0777) + osfile = OsFileWrapper(fd) + _w_long(osfile, pyc_magic) + _w_long(osfile, mtime) + w_marshal = space.getbuiltinmodule('marshal') + w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) + w_marshaller = space.call_function(w_U, space.wrap(fd)) + space.call_method(w_unmarshaller, 'dump', space.wrap(co)) + os.close(fd) From hpk at codespeak.net Tue Jul 26 19:48:59 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 19:48:59 +0200 (CEST) Subject: [pypy-svn] r15138 - in pypy/dist/pypy: rpython translator/goal Message-ID: <20050726174859.2757F27B74@code1.codespeak.net> Author: hpk Date: Tue Jul 26 19:48:58 2005 New Revision: 15138 Modified: pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: print less warnings in the rtyper. import bug fix. Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 26 19:48:58 2005 @@ -73,10 +73,8 @@ def __getattr__(self, name): # Assume that when an attribute is missing, it's because setup() needs # to be called - if name[:2] != '__' or name[-2:] != '__': + if not (name[:2] == '__' == name[-2:]): if self._initialized != setupstate.NOTINITIALIZED: - warning("__getattr__ %r in strange state %r" %(name, self,)) - else: self.setup() try: return self.__dict__[name] Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Tue Jul 26 19:48:58 2005 @@ -38,7 +38,7 @@ # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False - from pypy.tool import Options + from pypy.tool.option import Options options = Options() options.uselibfile = True space = StdObjSpace(options) From tismer at codespeak.net Tue Jul 26 19:49:31 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 26 Jul 2005 19:49:31 +0200 (CEST) Subject: [pypy-svn] r15139 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050726174931.43D8627B74@code1.codespeak.net> Author: tismer Date: Tue Jul 26 19:49:30 2005 New Revision: 15139 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: check-in just for sync Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 19:49:30 2005 @@ -361,7 +361,7 @@ w(space.builtin)) pycode.exec_code(space, w_dict, w_dict) - mtime = os.stat(fd)[stat.ST_MTIME] + mtime = os.fstat(fd)[stat.ST_MTIME] cpathname = pathname + 'c' write_compiled_module(space, pycode, cpathname, mtime) @@ -380,11 +380,11 @@ def _w_long(osfile, x): a = x & 0xff - x >> = 8 + x >>= 8 b = x & 0xff - x >> = 8 + x >>= 8 c = x & 0xff - x >> = 8 + x >>= 8 d = x & 0xff osfile.write(chr(a) + chr(b) + chr(c) + chr(d)) From arigo at codespeak.net Tue Jul 26 20:00:48 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 20:00:48 +0200 (CEST) Subject: [pypy-svn] r15140 - pypy/dist/pypy/objspace Message-ID: <20050726180048.A088327B6C@code1.codespeak.net> Author: arigo Date: Tue Jul 26 20:00:47 2005 New Revision: 15140 Modified: pypy/dist/pypy/objspace/proxy.py Log: Temporary hack to fix the thunk objspace. Modified: pypy/dist/pypy/objspace/proxy.py ============================================================================== --- pypy/dist/pypy/objspace/proxy.py (original) +++ pypy/dist/pypy/objspace/proxy.py Tue Jul 26 20:00:47 2005 @@ -10,10 +10,15 @@ """ Will create a proxy object space if no space supplied. Otherwise will patch the supplied space.""" + options = None + if space is not None and not isinstance(space, ObjSpace): + options = space # XXX temporary hack + space = None + if space is None: # make up a StdObjSpace by default from pypy.objspace import std - space = std.Space() + space = std.Space(options) if operations is None: operations = get_operations() From arigo at codespeak.net Tue Jul 26 20:06:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 20:06:01 +0200 (CEST) Subject: [pypy-svn] r15141 - pypy/dist/pypy/tool/test Message-ID: <20050726180601.DCDB927B5B@code1.codespeak.net> Author: arigo Date: Tue Jul 26 20:06:00 2005 New Revision: 15141 Modified: pypy/dist/pypy/tool/test/test_osfilewrapper.py Log: Fixed the test. Modified: pypy/dist/pypy/tool/test/test_osfilewrapper.py ============================================================================== --- pypy/dist/pypy/tool/test/test_osfilewrapper.py (original) +++ pypy/dist/pypy/tool/test/test_osfilewrapper.py Tue Jul 26 20:06:00 2005 @@ -1,5 +1,5 @@ import autopath -from pypy.tool.osfilewrapper import OsFileWrapper +from pypy.tool.osfilewrapper import OsFileWrapper, create_wrapper from pypy.tool.udir import udir import os @@ -14,7 +14,7 @@ f.close() for ii in range(10): - f = OsFileWrapper.create_wrapper(p, os.O_RDONLY) + f = create_wrapper(p, os.O_RDONLY) assert f.read(ii) == buf[:ii] def test_writes_reads(): @@ -23,10 +23,10 @@ buf = "1234567890" for ii in range(10): p = str(udir.join('test.dat')) - f1 = OsFileWrapper.create_wrapper(p, os.O_WRONLY) + f1 = create_wrapper(p, os.O_WRONLY) f1.write(buf[:ii]) f1.close() - f2 = OsFileWrapper.create_wrapper(p, os.O_RDONLY) + f2 = create_wrapper(p, os.O_RDONLY) assert f2.read(ii) == buf[:ii] f2.close() From arigo at codespeak.net Tue Jul 26 20:07:41 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 20:07:41 +0200 (CEST) Subject: [pypy-svn] r15142 - in pypy/dist/pypy/tool: . test Message-ID: <20050726180741.ECA8B27B5B@code1.codespeak.net> Author: arigo Date: Tue Jul 26 20:07:39 2005 New Revision: 15142 Modified: pypy/dist/pypy/tool/osfilewrapper.py (contents, props changed) pypy/dist/pypy/tool/run_translation.py (props changed) pypy/dist/pypy/tool/test/slowtest_run_translation.py (props changed) pypy/dist/pypy/tool/test/test_osfilewrapper.py (props changed) Log: fixeol Modified: pypy/dist/pypy/tool/osfilewrapper.py ============================================================================== --- pypy/dist/pypy/tool/osfilewrapper.py (original) +++ pypy/dist/pypy/tool/osfilewrapper.py Tue Jul 26 20:07:39 2005 @@ -30,6 +30,6 @@ os.close(self.fd) -def create_wrapper(filename, flag, mode=0777): - fd = os.open(filename, flag, mode) - return OsFileWrapper(fd) +def create_wrapper(filename, flag, mode=0777): + fd = os.open(filename, flag, mode) + return OsFileWrapper(fd) From arigo at codespeak.net Tue Jul 26 20:11:10 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 20:11:10 +0200 (CEST) Subject: [pypy-svn] r15143 - pypy/dist/pypy/tool Message-ID: <20050726181110.400F427B5B@code1.codespeak.net> Author: arigo Date: Tue Jul 26 20:11:09 2005 New Revision: 15143 Modified: pypy/dist/pypy/tool/osfilewrapper.py Log: Bug fix in OsFileWrapper.write() -- not easy to test partial write()s... Modified: pypy/dist/pypy/tool/osfilewrapper.py ============================================================================== --- pypy/dist/pypy/tool/osfilewrapper.py (original) +++ pypy/dist/pypy/tool/osfilewrapper.py Tue Jul 26 20:11:09 2005 @@ -23,8 +23,7 @@ towrite = len(buf) while writecount < towrite: # os.write will raise an error itself - writecount += os.write(self.fd, buf) - buf = buf[writecount:] + writecount += os.write(self.fd, buf[writecount:]) def close(self): os.close(self.fd) From hpk at codespeak.net Tue Jul 26 20:11:42 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 26 Jul 2005 20:11:42 +0200 (CEST) Subject: [pypy-svn] r15144 - in pypy/dist/pypy: interpreter/astcompiler interpreter/pyparser interpreter/pyparser/test interpreter/pyparser/test/samples lib module/__builtin__ translator/c/src translator/goal translator/llvm2 translator/llvm2/module translator/llvm2/test translator/llvm2/tool translator/test Message-ID: <20050726181142.58A0D27B5B@code1.codespeak.net> Author: hpk Date: Tue Jul 26 20:11:36 2005 New Revision: 15144 Modified: pypy/dist/pypy/interpreter/astcompiler/ast.txt (props changed) pypy/dist/pypy/interpreter/astcompiler/astgen.py (props changed) pypy/dist/pypy/interpreter/pyparser/astbuilder.py (props changed) pypy/dist/pypy/interpreter/pyparser/pysymbol.py (props changed) pypy/dist/pypy/interpreter/pyparser/pytoken.py (props changed) pypy/dist/pypy/interpreter/pyparser/test/samples/snippet_several_statements.py (props changed) pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py (props changed) pypy/dist/pypy/lib/collections.py (props changed) pypy/dist/pypy/module/__builtin__/app_file_stub.py (props changed) pypy/dist/pypy/module/__builtin__/state.py (props changed) pypy/dist/pypy/translator/c/src/ (props changed) pypy/dist/pypy/translator/goal/targetparser.py (props changed) pypy/dist/pypy/translator/llvm2/arraynode.py (props changed) pypy/dist/pypy/translator/llvm2/atomic.py (props changed) pypy/dist/pypy/translator/llvm2/extfuncnode.py (props changed) pypy/dist/pypy/translator/llvm2/module/ (props changed) pypy/dist/pypy/translator/llvm2/module/__init__.py (props changed) pypy/dist/pypy/translator/llvm2/module/extfunction.py (props changed) pypy/dist/pypy/translator/llvm2/node.py (props changed) pypy/dist/pypy/translator/llvm2/opaquenode.py (props changed) pypy/dist/pypy/translator/llvm2/opwriter.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_class.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_exception.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_gc.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_lltype.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_seq.py (props changed) pypy/dist/pypy/translator/llvm2/test/test_snippet.py (props changed) pypy/dist/pypy/translator/llvm2/tool/ (props changed) pypy/dist/pypy/translator/llvm2/tool/autopath.py (props changed) pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (props changed) pypy/dist/pypy/translator/test/test_backendoptimization.py (props changed) Log: fixeol From rxe at codespeak.net Tue Jul 26 20:13:13 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 20:13:13 +0200 (CEST) Subject: [pypy-svn] r15145 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050726181313.E154F27B5B@code1.codespeak.net> Author: rxe Date: Tue Jul 26 20:13:12 2005 New Revision: 15145 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Disable write_compiled_module() and use OsFileWrapper throughout. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Tue Jul 26 20:13:12 2005 @@ -17,10 +17,10 @@ try: BIN_READMASK = os.O_BINARY | os.O_RDONLY - BIN_WRITEMASK = os.O_BINARY | os.O_RDWR + BIN_WRITEMASK = os.O_BINARY | os.O_RDWR | os.O_CREAT except AttributeError: BIN_READMASK = os.O_RDONLY - BIN_WRITEMASK = os.O_RDWR + BIN_WRITEMASK = os.O_RDWR | os.O_CREAT NOFILE = 0 PYFILE = 1 @@ -49,7 +49,7 @@ if os.path.exists(pycfile): pyc_state = check_compiled_module(pyfile, pyfile_ts, pycfile) pycfile_exists = pyc_state >= 0 - pycfile_ts_valid = pyc_state > 0 and pyfile_exists + pycfile_ts_valid = pyc_state > 0 and pyfile_exist else: pycfile_exists = False pycfile_ts_valid = False @@ -107,11 +107,15 @@ space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) try: - if modtype == PYFILE: - load_source_module(space, w_modulename, w_mod, filename, fd) - else: - load_compiled_module(space, w_modulename, w_mod, filename, fd) - + try: + osfile = OsFileWrapper(fd) + if modtype == PYFILE: + load_source_module(space, w_modulename, w_mod, filename, osfile) + else: + load_compiled_module(space, w_modulename, w_mod, filename, osfile) + finally: + osfile.close() + except OperationError, e: if e.match(space, space.w_SyntaxError): w_mods = space.sys.get('modules') @@ -331,15 +335,11 @@ pyc_magic = MAGIC -def parse_source_module(space, pathname, fd): +def parse_source_module(space, pathname, osfile): """ Parse a source file and return the corresponding code object """ w = space.wrap - try: - size = os.fstat(fd)[stat.ST_SIZE] - source = os.read(fd, size) - finally: - os.close(fd) - + size = os.fstat(osfile.fd)[stat.ST_SIZE] + source = osfile.read(size) w_source = w(source) w_mode = w("exec") w_pathname = w(pathname) @@ -347,13 +347,13 @@ pycode = space.interpclass_w(w_code) return pycode -def load_source_module(space, w_modulename, w_mod, pathname, fd): +def load_source_module(space, w_modulename, w_mod, pathname, osfile): """ Load a source module from a given file and return its module object. """ w = space.wrap - pycode = parse_source_module(space, pathname, fd) + pycode = parse_source_module(space, pathname, osfile) w_dict = space.getattr(w_mod, w('__dict__')) space.call_method(w_dict, 'setdefault', @@ -361,9 +361,9 @@ w(space.builtin)) pycode.exec_code(space, w_dict, w_dict) - mtime = os.fstat(fd)[stat.ST_MTIME] + mtime = os.fstat(osfile.fd)[stat.ST_MTIME] cpathname = pathname + 'c' - write_compiled_module(space, pycode, cpathname, mtime) + #XXXwrite_compiled_module(space, pycode, cpathname, mtime) return w_mod @@ -415,12 +415,12 @@ os.close(fd) return 1 -def read_compiled_module(space, cpathname, fd): +def read_compiled_module(space, cpathname, osfile): """ Read a code object from a file and check it for validity """ w_marshal = space.getbuiltinmodule('marshal') w_U = space.getattr(w_marshal, space.wrap('_Unmarshaller')) - w_unmarshaller = space.call_function(w_U, space.wrap(fd)) + w_unmarshaller = space.call_function(w_U, space.wrap(osfile.fd)) w_code = space.call_method(w_unmarshaller, 'load') pycode = space.interpclass_w(w_code) if pycode is None: @@ -428,19 +428,18 @@ "Non-code object in %.200s" % cpathname)) return pycode -def load_compiled_module(space, w_modulename, w_mod, cpathname, fd): +def load_compiled_module(space, w_modulename, w_mod, cpathname, osfile): """ Load a module from a compiled file, execute it, and return its module object. """ - osfile = OsFileWrapper(fd) magic = _r_long(osfile) if magic != pyc_magic: raise OperationError(space.w_ImportError, space.wrap( "Bad magic number in %.200s" % cpathname)) return NULL; _r_long(osfile) # skip time stamp - code_w = read_compiled_module(space, cpathname, fd) + code_w = read_compiled_module(space, cpathname, osfile) #if (Py_VerboseFlag) # PySys_WriteStderr("import %s # precompiled from %s\n", # name, cpathname); Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Tue Jul 26 20:13:12 2005 @@ -5,6 +5,7 @@ from pypy.tool.udir import udir import sys, os import tempfile, marshal +from pypy.tool.osfilewrapper import OsFileWrapper from pypy.module.__builtin__.importing import BIN_READMASK @@ -204,7 +205,7 @@ cpathname = _testfile(importing.pyc_magic, mtime, co) fd = os.open(cpathname, BIN_READMASK, 0777) os.lseek(fd, 8, 0) - code_w = importing.read_compiled_module(space, cpathname, fd) + code_w = importing.read_compiled_module(space, cpathname, OsFileWrapper(fd)) os.close(fd) assert type(code_w) is pypy.interpreter.pycode.PyCode w_dic = space.newdict([]) @@ -222,7 +223,7 @@ w_modulename = space.wrap('somemodule') fd = os.open(cpathname, BIN_READMASK, 0777) w_mod = space.wrap(Module(space, w_modulename)) - w_ret = importing.load_compiled_module(space, w_modulename, w_mod, cpathname, fd) + w_ret = importing.load_compiled_module(space, w_modulename, w_mod, cpathname, OsFileWrapper(fd)) os.close(fd) assert w_mod is w_ret w_ret = space.getattr(w_mod, space.wrap('x')) From rxe at codespeak.net Tue Jul 26 20:39:26 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Tue, 26 Jul 2005 20:39:26 +0200 (CEST) Subject: [pypy-svn] r15146 - pypy/dist/pypy/interpreter/test Message-ID: <20050726183926.746C327B64@code1.codespeak.net> Author: rxe Date: Tue Jul 26 20:39:24 2005 New Revision: 15146 Modified: pypy/dist/pypy/interpreter/test/test_pyframe.py Log: Looks like a mischeckin from DC sprint. Sensible test_f_back() test. Reenable test_f_locals() & test_f_globals(). Modified: pypy/dist/pypy/interpreter/test/test_pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pyframe.py (original) +++ pypy/dist/pypy/interpreter/test/test_pyframe.py Tue Jul 26 20:39:24 2005 @@ -1,19 +1,18 @@ import autopath - class AppTestPyFrame: # test for the presence of the attributes, not functionality -## def test_f_locals(self): -## import sys -## f = sys._getframe() -## assert f.f_locals is locals() - -## def test_f_globals(self): -## import sys -## f = sys._getframe() -## assert f.f_globals is globals() + def test_f_locals(self): + import sys + f = sys._getframe() + assert f.f_locals is locals() + + def test_f_globals(self): + import sys + f = sys._getframe() + assert f.f_globals is globals() def test_f_builtins(self): import sys, __builtin__ @@ -46,17 +45,11 @@ def test_f_back(self): import sys - def trace(a,b,c): return trace def f(): - f_frame = sys._getframe() - return g(f_frame) - def g(f_frame): - g_frame = sys._getframe() - print g_frame - print g_frame.f_back - print g_frame.f_back.f_code.co_name, f_frame.f_code.co_name - sys.settrace(trace) - f() # XXX actually test something? + assert sys._getframe().f_code.co_name == g() + def g(): + return sys._getframe().f_back.f_code.co_name + f() def test_f_exc_xxx(self): import sys From arigo at codespeak.net Tue Jul 26 20:40:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 26 Jul 2005 20:40:36 +0200 (CEST) Subject: [pypy-svn] r15147 - pypy/dist/pypy/rpython Message-ID: <20050726184036.EE54427B6C@code1.codespeak.net> Author: arigo Date: Tue Jul 26 20:40:36 2005 New Revision: 15147 Modified: pypy/dist/pypy/rpython/rmodel.py Log: Oups! Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Jul 26 20:40:36 2005 @@ -74,7 +74,7 @@ # Assume that when an attribute is missing, it's because setup() needs # to be called if not (name[:2] == '__' == name[-2:]): - if self._initialized != setupstate.NOTINITIALIZED: + if self._initialized == setupstate.NOTINITIALIZED: self.setup() try: return self.__dict__[name] From cfbolz at codespeak.net Tue Jul 26 20:49:17 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 20:49:17 +0200 (CEST) Subject: [pypy-svn] r15148 - in pypy/dist/pypy: interpreter module/sys tool Message-ID: <20050726184917.BF40827B64@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 20:49:16 2005 New Revision: 15148 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/module/sys/state.py pypy/dist/pypy/tool/option.py Log: (pedronis, cfbolz): started to clean PyPy faked module handling. added a --nofakedmodule option. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jul 26 20:49:16 2005 @@ -97,7 +97,7 @@ class ObjSpace(object): """Base class for the interpreter-level implementations of object spaces. - http://codespeak.net/moin/pypy/moin.cgi/ObjectSpace""" + http://codespeak.net/pypy/index.cgi?doc/objspace.html""" full_exceptions = True # full support for exceptions (normalization & more) @@ -133,6 +133,28 @@ w_modules = self.sys.get('modules') return self.getitem(w_modules, w_name) + # change this to influence which of our own + # mixed modules should be used + def get_builtinmodule_list(self): + """NOT_RPYTHON""" + try: + return self._builtinmodule_list + except AttributeError: + builtinmodule_list = [('sys', None), ('__builtin__', None), + ('exceptions', None)] + builtinmodule_list.append(('unicodedata', None)) + # Uncomment the following line to enable the builtin _codecs module + builtinmodule_list.append(('_codecs', None)) + builtinmodule_list.append(('marshal', None)) + if self.options.useparsermodule == "recparser": + builtinmodule_list.append(('parser', 'recparser')) + elif self.options.useparsermodule == "parser": + builtinmodule_list.append(('parser', None)) + #builtinmodule_list.append(('posix', None)) + #builtinmodule_list.append(('math', None)) + self._builtinmodule_list = builtinmodule_list + return self._builtinmodule_list + def make_builtins(self): "NOT_RPYTHON: only for initializing the space." @@ -148,18 +170,11 @@ w_builtin = self.wrap(self.builtin) self.setitem(w_modules, w_name, w_builtin) self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin) - self.setbuiltinmodule('unicodedata') - # Uncomment the following line to enable the builtin _codecs module - self.setbuiltinmodule('_codecs') - # XXX we need to resolve unwrapping issues to - # make this the default _sre module - #self.setbuiltinmodule("_sre", "_sre_pypy") - self.setbuiltinmodule('marshal') - if self.options.useparsermodule == "recparser": - self.setbuiltinmodule('parser', 'recparser') - elif self.options.useparsermodule == "parser": - self.setbuiltinmodule('parser') - #self.setbuiltinmodule('posix') + + for modname, mixedname in self.get_builtinmodule_list(): + if modname not in ('sys', '__builtin__', 'exceptions'): + self.setbuiltinmodule(modname, mixedname) + # initialize with "bootstrap types" from objspace (e.g. w_None) for name, value in self.__dict__.items(): if name.startswith('w_') and not name.endswith('Type'): Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Tue Jul 26 20:49:16 2005 @@ -508,7 +508,7 @@ name at app-level.""" hidden_applevel = True - use_geninterp = True # change this to disable geninterp globally + use_geninterp = False # change this to disable geninterp globally def __init__(self, source, filename = None, modname = '__builtin__'): self.filename = filename Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Tue Jul 26 20:49:16 2005 @@ -7,7 +7,7 @@ import sys, os -def hack_cpython_module(modname): +def load_cpython_module(modname): "NOT_RPYTHON. Steal a module from CPython." cpy_module = __import__(modname, globals(), locals(), None) return cpy_module @@ -15,45 +15,53 @@ # ____________________________________________________________ # -builtin_module_names = ['__builtin__', 'sys', 'exceptions'] - -# Create the builtin_modules dictionary, mapping names to Module instances -builtin_modules = {} -for fn in builtin_module_names: - builtin_modules[fn] = None - -# The following built-in modules are not written in PyPy, so we -# steal them from Python. -for fn in ['posix', 'nt', 'os2', 'mac', 'ce', 'riscos', - 'math', 'array', 'select', - '_random', '_sre', 'time', '_socket', 'errno', - 'unicodedata', - 'parser', 'fcntl', '_codecs', 'binascii' - ]: - if fn not in builtin_modules and not os.path.exists( - os.path.join(os.path.dirname(pypy.__file__), - 'lib', fn+'.py')): - try: - builtin_modules[fn] = hack_cpython_module(fn) - except ImportError: - pass - else: - builtin_module_names.append(fn) - -builtin_module_names.sort() +ALL_BUILTIN_MODULES = [ + 'posix', 'nt', 'os2', 'mac', 'ce', 'riscos', + 'math', 'array', 'select', + '_random', '_sre', 'time', '_socket', 'errno', + 'unicodedata', + 'parser', 'fcntl', '_codecs', 'binascii' +] class State: def __init__(self, space): self.space = space - self.w_builtin_module_names = space.newtuple( - [space.wrap(fn) for fn in builtin_module_names]) + self.w_modules = space.newdict([]) - for fn, module in builtin_modules.items(): - space.setitem(self.w_modules, space.wrap(fn), space.wrap(module)) + self.complete_builtinmodules() + self.w_warnoptions = space.newlist([]) self.w_argv = space.newlist([]) self.setinitialpath(space) + def install_faked_module(self, modname): + space = self.space + try: + module = load_cpython_module(modname) + except ImportError: + return False + else: + space.setitem(self.w_modules, space.wrap(modname), + space.wrap(module)) + return True + + def complete_builtinmodules(self): + space = self.space + builtinmodule_list = self.space.get_builtinmodule_list() + builtinmodule_names = [name for name, mixedname in builtinmodule_list] + + if not space.options.nofakedmodules: + for modname in ALL_BUILTIN_MODULES: + if modname not in builtinmodule_names: + if not (os.path.exists( + os.path.join(os.path.dirname(pypy.__file__), + 'lib', modname+'.py'))): + if self.install_faked_module(modname): + builtinmodule_names.append(modname) + builtinmodule_names.sort() + self.w_builtin_module_names = space.newtuple( + [space.wrap(fn) for fn in builtinmodule_names]) + def setinitialpath(self, space): # Initialize the default path from pypy.interpreter import autopath Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Tue Jul 26 20:49:16 2005 @@ -10,6 +10,7 @@ spaces = [] oldstyle = 0 uselibfile = 0 + nofakedmodules = 0 useparsermodule = "recparser" # "cpython" / "recparser" / "parser" compiler = "pyparse" # "cpython" # "pyparse" pypy parser, cpython's compiler package @@ -39,6 +40,9 @@ '--file', action="store_true",dest="uselibfile", help="enable our custom file implementation")) options.append(make_option( + '--nofakedmodules', action="store_true",dest="nofakedmodules", + help="don't fake any module")) + options.append(make_option( '-w', action="store_true", dest="showwarning", help="enable warnings (disabled by default)")) options.append(make_option( From cfbolz at codespeak.net Tue Jul 26 20:51:13 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 20:51:13 +0200 (CEST) Subject: [pypy-svn] r15149 - pypy/dist/pypy/module/math Message-ID: <20050726185113.46CCA27B64@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 20:51:12 2005 New Revision: 15149 Added: pypy/dist/pypy/module/math/ pypy/dist/pypy/module/math/__init__.py Log: start of a mixed-module math impl, empty and disabled for now Added: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/math/__init__.py Tue Jul 26 20:51:12 2005 @@ -0,0 +1,9 @@ +# Package initialisation +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + appleveldefs = { + } + + interpleveldefs = { + } From cfbolz at codespeak.net Tue Jul 26 20:58:22 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Jul 2005 20:58:22 +0200 (CEST) Subject: [pypy-svn] r15150 - pypy/dist/pypy/interpreter Message-ID: <20050726185822.7495D27B64@code1.codespeak.net> Author: cfbolz Date: Tue Jul 26 20:58:21 2005 New Revision: 15150 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: we need our own modules if we use --file and --nofakemodules Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jul 26 20:58:21 2005 @@ -150,8 +150,9 @@ builtinmodule_list.append(('parser', 'recparser')) elif self.options.useparsermodule == "parser": builtinmodule_list.append(('parser', None)) - #builtinmodule_list.append(('posix', None)) - #builtinmodule_list.append(('math', None)) + if self.options.uselibfile and self.options.nofakedmodules: + builtinmodule_list.append(('posix', None)) + builtinmodule_list.append(('math', None)) self._builtinmodule_list = builtinmodule_list return self._builtinmodule_list From ericvrp at codespeak.net Tue Jul 26 23:43:46 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 26 Jul 2005 23:43:46 +0200 (CEST) Subject: [pypy-svn] r15151 - pypy/dist/pypy/translator/llvm2/tool Message-ID: <20050726214346.343BA27B6A@code1.codespeak.net> Author: ericvrp Date: Tue Jul 26 23:43:45 2005 New Revision: 15151 Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Log: - show missing primitives only - split-up per module/ll_* file - (minor) using Set instead of dicts Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (original) +++ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Tue Jul 26 23:43:45 2005 @@ -1,28 +1,19 @@ #!/usr/bin/python import autopath -import os +from sets import Set from pypy.rpython.module import ll_os, ll_os_path, ll_time, ll_math #XXX keep this list up-to-date from pypy.translator.llvm2.module.extfunction import extfunctions def main(): - suggested_primitives = [] for module in (ll_os, ll_os_path, ll_time, ll_math): #XXX keep this list up-to-date too - suggested_primitives += [func for func in dir(module) if getattr(module.__dict__[func], 'suggested_primitive', False)] - - implemented_primitives = [f[1:] for f in extfunctions.keys()] - - missing_primitives = [func for func in suggested_primitives if func not in implemented_primitives] - - print 'rpython suggested primitives:' - print suggested_primitives - print - print 'llvm implemented primitives:' - print implemented_primitives - print - print 'llvm missing primitives:' - print missing_primitives + suggested_primitives = Set( [func for func in dir(module) if getattr(module.__dict__[func], 'suggested_primitive', False)] ) + implemented_primitives = Set( [f[1:] for f in extfunctions.keys()] ) + missing_primitives = suggested_primitives - implemented_primitives + print 'Missing llvm primitives for %s:' % module.__name__ + for m in missing_primitives: + print ' %s' % m if __name__ == '__main__': main() From ericvrp at codespeak.net Wed Jul 27 00:17:25 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 27 Jul 2005 00:17:25 +0200 (CEST) Subject: [pypy-svn] r15152 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050726221725.C6FF227B6A@code1.codespeak.net> Author: ericvrp Date: Wed Jul 27 00:17:24 2005 New Revision: 15152 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: - added some missing casts - fixed shift (count was not corectly llvm-formatted (1L)) - removed some unused imports - hunted down an issue with same_as((<* None>)) being removed, but also propagated to the next block, where it fails at the phi node. - enabled one passing test - added skipped tests that would cause a segfault Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Wed Jul 27 00:17:24 2005 @@ -125,7 +125,8 @@ assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" value = const_or_var.value._obj - self.addpending(const_or_var, self.create_constant_node(ct.TO, value)) + if value: #XXX for test/test_dict_creation (how to handle this better?) + self.addpending(const_or_var, self.create_constant_node(ct.TO, value)) else: log.prepare(const_or_var, type(const_or_var)) @@ -211,7 +212,14 @@ if isinstance(arg.concretetype, lltype.Primitive): return primitive_to_str(arg.concretetype, arg.value) else: - node = self.obj2node[arg] + try: + node = self.obj2node[arg] + except KeyError: + #XXX related to llvm2/test/test_genllvm/test_dict_creation + #XXX "v962 = same_as((<* None>))" + #XXX this <* None> gets propagated to the next block and fails at the phi node! + #XXX Need better way to test for this only! + return 'null' if hasattr(node, "castref"): return node.castref else: Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfuncnode.py (original) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Wed Jul 27 00:17:24 2005 @@ -1,11 +1,5 @@ import py -from pypy.objspace.flow.model import Block, Constant, Variable, Link -from pypy.objspace.flow.model import flatten, mkentrymap, traverse -from pypy.rpython import lltype -from pypy.translator.backendoptimization import remove_same_as -from pypy.translator.unsimplify import remove_double_links -from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode -from pypy.translator.llvm2.atomic import is_atomic +from pypy.translator.llvm2.node import LLVMNode from pypy.translator.llvm2.log import log log = log.extfuncnode Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Wed Jul 27 00:17:24 2005 @@ -6,7 +6,6 @@ from pypy.translator.unsimplify import remove_double_links from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.opwriter import OpWriter -from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log nextnum = py.std.itertools.count().next log = log.funcnode @@ -68,12 +67,6 @@ def writeimpl(self, codewriter): assert self._issetup graph = self.graph - #dir(graph)==['__class__', '__delattr__', '__dict__', '__doc__', - # '__getattribute__', '__hash__', '__init__', '__module__', - # '__new__', '__reduce__', '__reduce_ex__', '__repr__', - # '__setattr__', '__str__', '__weakref__', 'exceptblock', - # 'func', 'getargs', 'getreturnvar', 'name', 'returnblock', - # 'show', 'source', 'startblock'] log.writeimpl(graph.name) codewriter.openfunc(self.getdecl()) nextblock = graph.startblock Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Wed Jul 27 00:17:24 2005 @@ -1,10 +1,6 @@ import py -from pypy.objspace.flow.model import Block, Constant, Variable, Link -from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.objspace.flow.model import Constant from pypy.rpython import lltype -from pypy.translator.backendoptimization import remove_same_as -from pypy.translator.unsimplify import remove_double_links -from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log nextexclabel = py.std.itertools.count().next @@ -116,7 +112,7 @@ name = self.shift_operations[op.opname] assert len(op.args) == 2 if isinstance(op.args[1], Constant): - tmpvar = op.args[1] + tmpvar = self.db.repr_arg(op.args[1]) else: tmpvar = self.db.repr_tmpvar() self.codewriter.cast(tmpvar, self.db.repr_arg_type(op.args[1]), self.db.repr_arg(op.args[1]), 'ubyte') @@ -134,11 +130,12 @@ fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) + cast_bool_to_char = cast_bool_to_int = cast_bool_to_uint = cast_primitive + cast_char_to_bool = cast_char_to_int = cast_char_to_uint = cast_primitive + cast_int_to_bool = cast_int_to_char = cast_int_to_uint = cast_primitive + cast_uint_to_bool = cast_uint_to_char = cast_uint_to_int = cast_primitive cast_pointer = cast_primitive - cast_bool_to_int = cast_primitive - cast_bool_to_uint = uint_is_true = cast_primitive - cast_int_to_char = cast_char_to_int = cast_primitive - cast_int_to_uint = cast_primitive + same_as = cast_primitive def int_is_true(self, op): self.codewriter.binaryop("setne", Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Wed Jul 27 00:17:24 2005 @@ -25,10 +25,11 @@ l = [f1, f2] def pointersimple(i): - return l[i] + return l[i](i) - f = compile_function(pointersimple, [int]) - assert f + f = compile_function(pointersimple, [int], True) + assert f(0) == pointersimple(0) + assert f(1) == pointersimple(1) def test_simple_branching(): def simple5(b): @@ -333,7 +334,6 @@ assert f() == 4 def test_dict_creation(): - py.test.skip("not working yet") d = {'hello' : 23, 'world' : 21} l = ["hello", "world"] From hpk at codespeak.net Wed Jul 27 10:13:34 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 10:13:34 +0200 (CEST) Subject: [pypy-svn] r15154 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727081334.65B1B27B62@code1.codespeak.net> Author: hpk Date: Wed Jul 27 10:13:33 2005 New Revision: 15154 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: - fix small rtyper related issues - remove some C-isms Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 10:13:33 2005 @@ -107,8 +107,8 @@ space.setattr(w_mod, w('__path__'), space.newlist([w(pkgdir)])) try: + osfile = OsFileWrapper(fd) try: - osfile = OsFileWrapper(fd) if modtype == PYFILE: load_source_module(space, w_modulename, w_mod, filename, osfile) else: @@ -425,7 +425,7 @@ pycode = space.interpclass_w(w_code) if pycode is None: raise OperationError(space.w_ImportError, space.wrap( - "Non-code object in %.200s" % cpathname)) + "Non-code object in %s" % cpathname)) return pycode def load_compiled_module(space, w_modulename, w_mod, cpathname, osfile): @@ -436,7 +436,7 @@ magic = _r_long(osfile) if magic != pyc_magic: raise OperationError(space.w_ImportError, space.wrap( - "Bad magic number in %.200s" % cpathname)) + "Bad magic number in %s" % cpathname)) return NULL; _r_long(osfile) # skip time stamp code_w = read_compiled_module(space, cpathname, osfile) From hpk at codespeak.net Wed Jul 27 10:14:31 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 10:14:31 +0200 (CEST) Subject: [pypy-svn] r15155 - pypy/dist/pypy/interpreter Message-ID: <20050727081431.6151A27B62@code1.codespeak.net> Author: hpk Date: Wed Jul 27 10:14:30 2005 New Revision: 15155 Modified: pypy/dist/pypy/interpreter/gateway.py Log: turn geninterp default to be on Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Wed Jul 27 10:14:30 2005 @@ -508,7 +508,7 @@ name at app-level.""" hidden_applevel = True - use_geninterp = False # change this to disable geninterp globally + use_geninterp = True # change this to disable geninterp globally def __init__(self, source, filename = None, modname = '__builtin__'): self.filename = filename From hpk at codespeak.net Wed Jul 27 10:15:19 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 10:15:19 +0200 (CEST) Subject: [pypy-svn] r15156 - pypy/dist/pypy/module/posix Message-ID: <20050727081519.6031127B68@code1.codespeak.net> Author: hpk Date: Wed Jul 27 10:15:18 2005 New Revision: 15156 Modified: pypy/dist/pypy/module/posix/interp_posix.py Log: fix typo (in untested code) Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Wed Jul 27 10:15:18 2005 @@ -17,7 +17,7 @@ lseek.unwrap_spec = [ObjSpace, int, int, int] def isatty(space, fd): - return space.wrap(os.isatty(w_fd)) + return space.wrap(os.isatty(fd)) isatty.unwrap_spec = [ObjSpace, int] def read(space, fd, buffersize): @@ -50,4 +50,4 @@ def dup(space, fd): return space.wrap(os.dup(fd)) -dup.unwrap_spec = [ObjSpace, int] \ No newline at end of file +dup.unwrap_spec = [ObjSpace, int] From tismer at codespeak.net Wed Jul 27 11:29:42 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 11:29:42 +0200 (CEST) Subject: [pypy-svn] r15158 - pypy/extradoc/sprintinfo Message-ID: <20050727092942.34E3627B60@code1.codespeak.net> Author: tismer Date: Wed Jul 27 11:29:41 2005 New Revision: 15158 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: updated sprint planning for today (until tomorrow noon) Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Wed Jul 27 11:29:41 2005 @@ -52,17 +52,19 @@ DONE: refactored math and os function out of annotation/builtin and rpython/rbuiltin into the extfunctable, implemented some math.*, os.* functions. fixed os.stat + Open issues: - - RPython string -> C null-terminated string + - DONE (for C) RPython string -> C null-terminated string conversion. The null termination char is not there! - - - The flow space kills exception handling for built-ins, + + - DONE (__builtin__/* don't raise, the rest does) + The flow space kills exception handling for built-ins, this is not what we want e.g. for os.* functions; decide new criteria. Maybe only for thing in __builtin__ or list only the built-ins we want exception handling suppressed. - - finish os.path.exists and os.path.isdir support + - DONE finish os.path.exists and os.path.isdir support (Armin, Carl Friedrich) @@ -72,11 +74,20 @@ up to wrap/unwrap issues related to faking. The hope is that we can get rid of faking. - Completing marshal, made it into a mixed-module - that can be geinterped. - + DONE Completing marshal, made it into a mixed-module + that can be geninterped. + (chris wishes to redo it in interplevel) + + DONE modulo some problems. + Inconsistency about problems on different machines. + PYC still untested. More tests needed. Plan: enable pyc loading to bootstrap compiler at app-level (Christian, Richard) + Todo: + Choose a PYC file version for PyPy (2.4.1) + Using this version is ok, because our compiler + exactly produces these. The extra functionality in + our marshal is not related to magic numbers. Richard, Holger (getting rid of faked files) DONE: importing uses only os.* functions at @@ -84,4 +95,52 @@ use our own app-level implementation of files. --file is on by default now when translating - + Remaining problem list: + + - Samuele, Holger + make py.py --file --nofakedmodules work + (crashes somehow) + + - Samuele, Holger + allways enforce geninterping of marshal, maybe + similar to what we did with exceptions + + - Samuele, Holger + primitive math is done. Implement applevel math, + have many tests. + + - Samuele, Holger, transitional + unify the way stdobjspace is configured. + the basic objspace configuration interface + becomes a set of keyword arguments. The current + command line arguments will be mapped onto this + interface. + This also includes configuration of which modules + should be loaded. + + - Samuele, eleumaS + extend the testing framework to allow to specify + a space with options for a test. Related to the latter. + + - Holger, Armin + bug to be fixed: applevel test stdout is no longer + captured. + + - Armin, and everybody else, please + run translation and try to avoid any faking at all. + An example where it still happens is EllipsisType + which gets wrapped by geninterplevel. + + - Richard, Chris + Choose a PYC file version for PyPy (2.4.1) + Using this version is ok, because our compiler + exactly produces these. The extra functionality in + our marshal is not related to magic numbers. + + - Richard, Chris + track down remaining .pyc file issues. + +Concerning the sync meeting of tomorrow, and given that +we stop working this afternoon, we agreed now for +tomorrow, that Anders should be asked to work on the +complicancy test failures. From arigo at codespeak.net Wed Jul 27 11:30:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 11:30:22 +0200 (CEST) Subject: [pypy-svn] r15159 - pypy/dist/pypy/objspace/std Message-ID: <20050727093022.E4EC327B60@code1.codespeak.net> Author: arigo Date: Wed Jul 27 11:30:08 2005 New Revision: 15159 Modified: pypy/dist/pypy/objspace/std/dictobject.py pypy/dist/pypy/objspace/std/dicttype.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/objspace.py Log: issue20 resolved - Implemented dictionary iterators. - Asserts that we don't forget to put object implementations in objspace/std/model.py -- we indeed forgot dictproxyobject. Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Wed Jul 27 11:30:08 2005 @@ -170,10 +170,8 @@ dict_has_key__Dict_ANY = contains__Dict_ANY def iter__Dict(space, w_dict): - from pypy.objspace.std import iterobject - w_keys = dict_keys__Dict(space, w_dict) - return iterobject.W_SeqIterObject(space, w_keys) - + return W_DictIter_Keys(space, w_dict) + def eq__Dict_Dict(space, w_left, w_right): if space.is_true(space.is_(w_left, w_right)): return space.w_True @@ -255,6 +253,15 @@ for entry in w_self.data if entry.w_value is not None]) +def dict_iteritems__Dict(space, w_self): + return W_DictIter_Items(space, w_self) + +def dict_iterkeys__Dict(space, w_self): + return W_DictIter_Keys(space, w_self) + +def dict_itervalues__Dict(space, w_self): + return W_DictIter_Values(space, w_self) + def dict_clear__Dict(space, w_self): w_self.data = [Entry()] w_self.used = 0 @@ -298,5 +305,58 @@ repr__Dict = str__Dict + +# ____________________________________________________________ +# Iteration + +class W_DictIterObject(W_Object): + 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.w_dictobject = w_dictobject + w_self.len = w_dictobject.used + w_self.pos = 0 + +registerimplementation(W_DictIterObject) + +class W_DictIter_Keys(W_DictIterObject): + def return_entry(w_self, entry): + return entry.w_key + +class W_DictIter_Values(W_DictIterObject): + def return_entry(w_self, entry): + return entry.w_value + +class W_DictIter_Items(W_DictIterObject): + def return_entry(w_self, entry): + return w_self.space.newtuple([entry.w_key, entry.w_value]) + + +def iter__DictIterObject(space, w_dictiter): + return w_dictiter + +def next__DictIterObject(space, w_dictiter): + w_dict = w_dictiter.w_dictobject + if w_dict is not None: + if w_dictiter.len != w_dict.used: + w_dictiter.len = -1 # Make this error state sticky + raise OperationError(space.w_RuntimeError, + space.wrap("dictionary changed size during iteration")) + # look for the next entry + i = w_dictiter.pos + data = w_dict.data + while i < len(data): + entry = data[i] + i += 1 + if entry.w_value is not None: + w_dictiter.pos = i + return w_dictiter.return_entry(entry) + # no more entries + w_dictiter.w_dictobject = None + raise OperationError(space.w_StopIteration, space.w_None) + +# ____________________________________________________________ + from pypy.objspace.std import dicttype register_all(vars(), dicttype) Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Wed Jul 27 11:30:08 2005 @@ -100,3 +100,7 @@ unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), ) dict_typedef.registermethods(globals()) + + +dictiter_typedef = StdTypeDef("dictionaryiterator", + ) Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Wed Jul 27 11:30:08 2005 @@ -49,6 +49,7 @@ from pypy.objspace.std import noneobject from pypy.objspace.std import iterobject from pypy.objspace.std import unicodeobject + from pypy.objspace.std import dictproxyobject from pypy.objspace.std import fake import pypy.objspace.std.default # register a few catch-all multimethods @@ -61,6 +62,7 @@ tupleobject.W_TupleObject: [], listobject.W_ListObject: [], dictobject.W_DictObject: [], + dictobject.W_DictIterObject: [], stringobject.W_StringObject: [], typeobject.W_TypeObject: [], sliceobject.W_SliceObject: [], @@ -68,10 +70,17 @@ noneobject.W_NoneObject: [], iterobject.W_SeqIterObject: [], unicodeobject.W_UnicodeObject: [], + dictproxyobject.W_DictProxyObject: [], } for type in self.typeorder: self.typeorder[type].append((type, None)) + # check if we missed implementations + from pypy.objspace.std.objspace import _registered_implementations + for implcls in _registered_implementations: + assert implcls in self.typeorder, ( + "please add %r in StdTypeModel.typeorder" % (implcls,)) + # 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 Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Jul 27 11:30:08 2005 @@ -14,11 +14,11 @@ import sys import os +_registered_implementations = {} def registerimplementation(implcls): - # this function should ultimately register the implementation class somewhere - # it may be modified to take 'typedef' instead of requiring it to be - # stored in 'implcls' itself + # hint to objspace.std.model to register the implementation class assert issubclass(implcls, W_Object) + _registered_implementations[implcls] = True ################################################################## From hpk at codespeak.net Wed Jul 27 11:41:52 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 11:41:52 +0200 (CEST) Subject: [pypy-svn] r15164 - pypy/dist/pypy/translator/goal Message-ID: <20050727094152.BDBF027B60@code1.codespeak.net> Author: hpk Date: Wed Jul 27 11:41:51 2005 New Revision: 15164 Added: pypy/dist/pypy/translator/goal/runtranslate.sh (contents, props changed) Log: add a small helper shell script to run translation as we want it at the moment Added: pypy/dist/pypy/translator/goal/runtranslate.sh ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/runtranslate.sh Wed Jul 27 11:41:51 2005 @@ -0,0 +1,5 @@ +export RTYPERORDER=order,module-list.pedronis +# stopping on the first error +#python translate_pypy.py -no-c -no-o -text -no-snapshot -fork +# running it all +python translate_pypy.py -no-c -no-o -text -t-insist -no-snapshot -fork From arigo at codespeak.net Wed Jul 27 11:50:10 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 11:50:10 +0200 (CEST) Subject: [pypy-svn] r15166 - in pypy/dist/pypy: interpreter lib lib/test2 module/__builtin__ module/marshal tool Message-ID: <20050727095010.DBE4327B60@code1.codespeak.net> Author: arigo Date: Wed Jul 27 11:50:00 2005 New Revision: 15166 Added: pypy/dist/pypy/lib/marshal.py - copied, changed from r15163, pypy/dist/pypy/module/marshal/app_marshal.py pypy/dist/pypy/lib/osfilewrapper.py - copied unchanged from r15163, pypy/dist/pypy/tool/osfilewrapper.py pypy/dist/pypy/lib/test2/autopath.py - copied unchanged from r15163, pypy/dist/pypy/tool/autopath.py pypy/dist/pypy/lib/test2/test_marshal_extra.py - copied, changed from r15163, pypy/dist/pypy/module/marshal/test/test_marshal_extra.py Removed: pypy/dist/pypy/module/marshal/ pypy/dist/pypy/tool/osfilewrapper.py Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/__builtin__/importing.py Log: * moved marshal back into lib. It doesn't have to be a mixed module to be geninterped, after all. * moved osfilewrapper to lib as well, so that it can be imported at app-level from marshal. (It is also imported at interp-level from importing.py.) Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Jul 27 11:50:00 2005 @@ -145,7 +145,6 @@ builtinmodule_list.append(('unicodedata', None)) # Uncomment the following line to enable the builtin _codecs module builtinmodule_list.append(('_codecs', None)) - builtinmodule_list.append(('marshal', None)) if self.options.useparsermodule == "recparser": builtinmodule_list.append(('parser', 'recparser')) elif self.options.useparsermodule == "parser": Copied: pypy/dist/pypy/lib/marshal.py (from r15163, pypy/dist/pypy/module/marshal/app_marshal.py) ============================================================================== --- pypy/dist/pypy/module/marshal/app_marshal.py (original) +++ pypy/dist/pypy/lib/marshal.py Wed Jul 27 11:50:00 2005 @@ -1,10 +1,10 @@ -"""Marshal module written in Python. +"""Internal Python object serialization + +This module contains functions that can read and write Python values in a binary format. The format is specific to Python, but independent of machine architecture issues (e.g., you can write a Python value to a file on a PC, transport the file to a Sun, and read it back there). Details of the format may change between Python versions. """ import types -import os - -from pypy.tool.osfilewrapper import OsFileWrapper +from osfilewrapper import OsFileWrapper try: import new Copied: pypy/dist/pypy/lib/test2/test_marshal_extra.py (from r15163, pypy/dist/pypy/module/marshal/test/test_marshal_extra.py) ============================================================================== --- pypy/dist/pypy/module/marshal/test/test_marshal_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_marshal_extra.py Wed Jul 27 11:50:00 2005 @@ -1,8 +1,8 @@ -import py import autopath +import py import sys import marshal as cpy_marshal -from pypy.module.marshal import app_marshal as marshal +from pypy.lib import marshal from pypy.tool.udir import udir Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 11:50:00 2005 @@ -7,7 +7,7 @@ from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace -from pypy.tool.osfilewrapper import OsFileWrapper +from pypy.lib.osfilewrapper import OsFileWrapper # XXX this uses the os.path module at interp-level, which means # XXX that translate_pypy will produce a translated version of Deleted: /pypy/dist/pypy/tool/osfilewrapper.py ============================================================================== --- /pypy/dist/pypy/tool/osfilewrapper.py Wed Jul 27 11:50:00 2005 +++ (empty file) @@ -1,34 +0,0 @@ -import os - -class OsFileWrapper(object): - """ Very simple os file wrapper. - Note user is responsible for closing. - XXX Could add a simple buffer mechanism. """ - - def __init__(self, fd): - self.fd = fd - - def read(self, expected): - readcount = 0 - bufs = [] - while readcount < expected: - # os.read will raise an error itself - buf = os.read(self.fd, expected) - readcount += len(buf) - bufs.append(buf) - return "".join(bufs) - - def write(self, buf): - writecount = 0 - towrite = len(buf) - while writecount < towrite: - # os.write will raise an error itself - writecount += os.write(self.fd, buf[writecount:]) - - def close(self): - os.close(self.fd) - - -def create_wrapper(filename, flag, mode=0777): - fd = os.open(filename, flag, mode) - return OsFileWrapper(fd) From arigo at codespeak.net Wed Jul 27 12:18:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 12:18:53 +0200 (CEST) Subject: [pypy-svn] r15167 - pypy/dist/pypy/interpreter Message-ID: <20050727101853.D1C0527B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 12:18:50 2005 New Revision: 15167 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: Use the posix and math built-in modules whenever --nofakedmodules is specified, not only if --file is specified as well. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Jul 27 12:18:50 2005 @@ -149,7 +149,7 @@ builtinmodule_list.append(('parser', 'recparser')) elif self.options.useparsermodule == "parser": builtinmodule_list.append(('parser', None)) - if self.options.uselibfile and self.options.nofakedmodules: + if self.options.nofakedmodules: builtinmodule_list.append(('posix', None)) builtinmodule_list.append(('math', None)) self._builtinmodule_list = builtinmodule_list From hpk at codespeak.net Wed Jul 27 12:46:30 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 12:46:30 +0200 (CEST) Subject: [pypy-svn] r15169 - in pypy/dist/pypy: interpreter module/math Message-ID: <20050727104630.D890427B61@code1.codespeak.net> Author: hpk Date: Wed Jul 27 12:46:29 2005 New Revision: 15169 Added: pypy/dist/pypy/module/math/_genmath.py (contents, props changed) pypy/dist/pypy/module/math/interp_math.py (contents, props changed) pypy/dist/pypy/module/math/readme.test Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/math/ (props changed) pypy/dist/pypy/module/math/__init__.py (contents, props changed) Log: (hpk,pedronis) - generated/made an almost complete math module (mixedmodule) - compliance 2.4.1 test_math.py passes - _genmath.py is only there if we need to regenerate it at some point (e.g. regarding exceptions) - use 'math' now by default (even without --nofakedmodules) - not unlikely we need to revisit the math module when it comes to exceptions Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Jul 27 12:46:29 2005 @@ -151,7 +151,7 @@ builtinmodule_list.append(('parser', None)) if self.options.nofakedmodules: builtinmodule_list.append(('posix', None)) - builtinmodule_list.append(('math', None)) + builtinmodule_list.append(('math', None)) self._builtinmodule_list = builtinmodule_list return self._builtinmodule_list Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Wed Jul 27 12:46:29 2005 @@ -1,9 +1,37 @@ + # Package initialisation from pypy.interpreter.mixedmodule import MixedModule - + class Module(MixedModule): appleveldefs = { } - interpleveldefs = { - } + 'e' : 'interp_math.get(space).w_e', + 'pi' : 'interp_math.get(space).w_pi', + 'pow' : 'interp_math.pow', + 'cosh' : 'interp_math.cosh', + 'ldexp' : 'interp_math.ldexp', + 'hypot' : 'interp_math.hypot', + 'tan' : 'interp_math.tan', + 'asin' : 'interp_math.asin', + 'log' : 'interp_math.log', + 'fabs' : 'interp_math.fabs', + 'floor' : 'interp_math.floor', + 'sqrt' : 'interp_math.sqrt', + 'frexp' : 'interp_math.frexp', + 'degrees' : 'interp_math.degrees', + 'log10' : 'interp_math.log10', + 'fmod' : 'interp_math.fmod', + 'atan' : 'interp_math.atan', + 'ceil' : 'interp_math.ceil', + 'sinh' : 'interp_math.sinh', + 'cos' : 'interp_math.cos', + 'tanh' : 'interp_math.tanh', + 'radians' : 'interp_math.radians', + 'sin' : 'interp_math.sin', + 'atan2' : 'interp_math.atan2', + 'modf' : 'interp_math.modf', + 'exp' : 'interp_math.exp', + 'acos' : 'interp_math.acos', + +} Added: pypy/dist/pypy/module/math/_genmath.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/math/_genmath.py Wed Jul 27 12:46:29 2005 @@ -0,0 +1,62 @@ +# ONESHOT SCRIPT (probably can go away soon) +# to generate the mixed module 'math' (see same directory) +import py +import math +import re +import sys +rex_arg = re.compile(".*\((.*)\).*") + +if __name__ == '__main__': + print py.code.Source(""" + import math + from pypy.interpreter.gateway import ObjSpace + + """) + names = [] + for name, func in math.__dict__.items(): + if not callable(func): + continue + sig = func.__doc__.split('\n')[0].strip() + sig = sig.split('->')[0].strip() + m = rex_arg.match(sig) + assert m + args = m.group(1) + args = ", ".join(args.split(',')) + sig = sig.replace('(', '(space,') + sig = ", ".join(sig.split(',')) + argc = len(args.split(',')) + unwrap_spec = ['ObjSpace'] + unwrap_spec += ['float'] * argc + unwrap_spec = ", ".join(unwrap_spec) + doc = func.__doc__.replace('\n', '\n ') + + print py.code.Source(''' + def %(sig)s: + """%(doc)s + """ + return space.wrap(math.%(name)s(%(args)s)) + %(name)s.unwrap_spec = [%(unwrap_spec)s] + ''' % locals()) + names.append(name) + + print >>sys.stderr, py.code.Source(""" + # Package initialisation + from pypy.interpreter.mixedmodule import MixedModule + + class Module(MixedModule): + appleveldefs = { + } + interpleveldefs = { + """) + + for name in names: + space = " " * (15-len(name)) + print >>sys.stderr, ( + " %(name)r%(space)s: 'interp_math.%(name)s'," % locals()) + print >>sys.stderr, py.code.Source(""" + } + """) + + + + Added: pypy/dist/pypy/module/math/interp_math.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/math/interp_math.py Wed Jul 27 12:46:29 2005 @@ -0,0 +1,209 @@ + +import math +from pypy.interpreter.gateway import ObjSpace + +class State: + def __init__(self, space): + self.w_e = space.wrap(math.e) + self.w_pi = space.wrap(math.pi) +def get(space): + return space.fromcache(State) + +def pow(space, x, y): + """pow(x,y) + + Return x**y (x to the power of y). + """ + return space.wrap(math.pow(x, y)) +pow.unwrap_spec = [ObjSpace, float, float] + +def cosh(space, x): + """cosh(x) + + Return the hyperbolic cosine of x. + """ + return space.wrap(math.cosh(x)) +cosh.unwrap_spec = [ObjSpace, float] + +def ldexp(space, x, i): + """ldexp(x, i) -> x * (2**i) + """ + return space.wrap(math.ldexp(x, i)) +ldexp.unwrap_spec = [ObjSpace, float, int] + +def hypot(space, x, y): + """hypot(x,y) + + Return the Euclidean distance, sqrt(x*x + y*y). + """ + return space.wrap(math.hypot(x, y)) +hypot.unwrap_spec = [ObjSpace, float, float] + +def tan(space, x): + """tan(x) + + Return the tangent of x (measured in radians). + """ + return space.wrap(math.tan(x)) +tan.unwrap_spec = [ObjSpace, float] + +def asin(space, x): + """asin(x) + + Return the arc sine (measured in radians) of x. + """ + return space.wrap(math.asin(x)) +asin.unwrap_spec = [ObjSpace, float] + +def log(space, x, base=math.e): + """log(x[, base]) -> the logarithm of x to the given base. + If the base not specified, returns the natural logarithm (base e) of x. + """ + return space.wrap(math.log(x, base)) +log.unwrap_spec = [ObjSpace, float, float] + +def fabs(space, x): + """fabs(x) + + Return the absolute value of the float x. + """ + return space.wrap(math.fabs(x)) +fabs.unwrap_spec = [ObjSpace, float] + +def floor(space, x): + """floor(x) + + Return the floor of x as a float. + This is the largest integral value <= x. + """ + return space.wrap(math.floor(x)) +floor.unwrap_spec = [ObjSpace, float] + +def sqrt(space, x): + """sqrt(x) + + Return the square root of x. + """ + return space.wrap(math.sqrt(x)) +sqrt.unwrap_spec = [ObjSpace, float] + +def frexp(space, x): + """frexp(x) + + Return the mantissa and exponent of x, as pair (m, e). + m is a float and e is an int, such that x = m * 2.**e. + If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0. + """ + mant, expo = math.frexp(x) + return space.newtuple([space.wrap(mant), space.wrap(expo)]) +frexp.unwrap_spec = [ObjSpace, float] + +def degrees(space, x): + """degrees(x) -> converts angle x from radians to degrees + """ + return space.wrap(math.degrees(x)) +degrees.unwrap_spec = [ObjSpace, float] + +def log10(space, x): + """log10(x) -> the base 10 logarithm of x. + """ + return space.wrap(math.log10(x)) +log10.unwrap_spec = [ObjSpace, float] + +def fmod(space, x, y): + """fmod(x,y) + + Return fmod(x, y), according to platform C. x % y may differ. + """ + return space.wrap(math.fmod(x, y)) +fmod.unwrap_spec = [ObjSpace, float, float] + +def atan(space, x): + """atan(x) + + Return the arc tangent (measured in radians) of x. + """ + return space.wrap(math.atan(x)) +atan.unwrap_spec = [ObjSpace, float] + +def ceil(space, x): + """ceil(x) + + Return the ceiling of x as a float. + This is the smallest integral value >= x. + """ + return space.wrap(math.ceil(x)) +ceil.unwrap_spec = [ObjSpace, float] + +def sinh(space, x): + """sinh(x) + + Return the hyperbolic sine of x. + """ + return space.wrap(math.sinh(x)) +sinh.unwrap_spec = [ObjSpace, float] + +def cos(space, x): + """cos(x) + + Return the cosine of x (measured in radians). + """ + return space.wrap(math.cos(x)) +cos.unwrap_spec = [ObjSpace, float] + +def tanh(space, x): + """tanh(x) + + Return the hyperbolic tangent of x. + """ + return space.wrap(math.tanh(x)) +tanh.unwrap_spec = [ObjSpace, float] + +def radians(space, x): + """radians(x) -> converts angle x from degrees to radians + """ + return space.wrap(math.radians(x)) +radians.unwrap_spec = [ObjSpace, float] + +def sin(space, x): + """sin(x) + + Return the sine of x (measured in radians). + """ + return space.wrap(math.sin(x)) +sin.unwrap_spec = [ObjSpace, float] + +def atan2(space, y, x): + """atan2(y, x) + + Return the arc tangent (measured in radians) of y/x. + Unlike atan(y/x), the signs of both x and y are considered. + """ + return space.wrap(math.atan2(y, x)) +atan2.unwrap_spec = [ObjSpace, float, float] + +def modf(space, x): + """modf(x) + + Return the fractional and integer parts of x. Both results carry the sign + of x. The integer part is returned as a real. + """ + frac, intpart = math.modf(x) + return space.newtuple([space.wrap(frac), space.wrap(intpart)]) +modf.unwrap_spec = [ObjSpace, float] + +def exp(space, x): + """exp(x) + + Return e raised to the power of x. + """ + return space.wrap(math.exp(x)) +exp.unwrap_spec = [ObjSpace, float] + +def acos(space, x): + """acos(x) + + Return the arc cosine (measured in radians) of x. + """ + return space.wrap(math.acos(x)) +acos.unwrap_spec = [ObjSpace, float] Added: pypy/dist/pypy/module/math/readme.test ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/math/readme.test Wed Jul 27 12:46:29 2005 @@ -0,0 +1,6 @@ +# please run the compliance test like e.g. + +# py.test lib-python/2.4.1/test/test_math.py +# +# if you change the math module +# From hpk at codespeak.net Wed Jul 27 12:48:30 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 12:48:30 +0200 (CEST) Subject: [pypy-svn] r15170 - pypy/extradoc/sprintinfo Message-ID: <20050727104830.A9ADF27B61@code1.codespeak.net> Author: hpk Date: Wed Jul 27 12:48:29 2005 New Revision: 15170 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: small update after some work done Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Wed Jul 27 12:48:29 2005 @@ -97,17 +97,17 @@ Remaining problem list: - - Samuele, Holger + - DONE Samuele, Holger make py.py --file --nofakedmodules work (crashes somehow) - - Samuele, Holger + - ? allways enforce geninterping of marshal, maybe similar to what we did with exceptions - - Samuele, Holger + - DONE Samuele, Holger primitive math is done. Implement applevel math, - have many tests. + have many tests (we are using compliance tests only). - Samuele, Holger, transitional unify the way stdobjspace is configured. From arigo at codespeak.net Wed Jul 27 12:52:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 12:52:37 +0200 (CEST) Subject: [pypy-svn] r15171 - pypy/dist/pypy/translator Message-ID: <20050727105237.C79D027B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 12:52:34 2005 New Revision: 15171 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: For now, ignore from geninterp references to pypy/lib/ modules. Needed to avoid the "faking " messages with py.py --nofakedmodules. As far as I see no test is unhappy about that. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Jul 27 12:52:34 2005 @@ -410,6 +410,10 @@ return bltinmod_helper(self, value) # we might have createda reference to a module # that is non-standard. + + # SKIPPING + return "space.w_None" + # check whether we can import try: import value From arigo at codespeak.net Wed Jul 27 12:59:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 12:59:44 +0200 (CEST) Subject: [pypy-svn] r15172 - pypy/dist/pypy/translator Message-ID: <20050727105944.EFCE227B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 12:59:44 2005 New Revision: 15172 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: Oups, forgot to bump the geninterplevel version number. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Jul 27 12:59:44 2005 @@ -77,7 +77,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.4' # bump this for substantial changes +GI_VERSION = '1.1.5' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): From hpk at codespeak.net Wed Jul 27 13:02:47 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 27 Jul 2005 13:02:47 +0200 (CEST) Subject: [pypy-svn] r15173 - pypy/dist/pypy/module/math Message-ID: <20050727110247.BD80627B60@code1.codespeak.net> Author: hpk Date: Wed Jul 27 13:02:47 2005 New Revision: 15173 Modified: pypy/dist/pypy/module/math/__init__.py Log: (pedronis,hpk) commented out the math functions that are not fully supported by the translation chain. Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Wed Jul 27 13:02:47 2005 @@ -5,33 +5,37 @@ class Module(MixedModule): appleveldefs = { } + + # XXX the reason for the commented out names + # is that we need to add support to + # extfunctable/translation interpleveldefs = { 'e' : 'interp_math.get(space).w_e', 'pi' : 'interp_math.get(space).w_pi', - 'pow' : 'interp_math.pow', - 'cosh' : 'interp_math.cosh', + #'pow' : 'interp_math.pow', + #'cosh' : 'interp_math.cosh', 'ldexp' : 'interp_math.ldexp', - 'hypot' : 'interp_math.hypot', - 'tan' : 'interp_math.tan', - 'asin' : 'interp_math.asin', - 'log' : 'interp_math.log', - 'fabs' : 'interp_math.fabs', + #'hypot' : 'interp_math.hypot', + #'tan' : 'interp_math.tan', + #'asin' : 'interp_math.asin', + #'log' : 'interp_math.log', + #'fabs' : 'interp_math.fabs', 'floor' : 'interp_math.floor', - 'sqrt' : 'interp_math.sqrt', + #'sqrt' : 'interp_math.sqrt', 'frexp' : 'interp_math.frexp', - 'degrees' : 'interp_math.degrees', + #'degrees' : 'interp_math.degrees', 'log10' : 'interp_math.log10', 'fmod' : 'interp_math.fmod', - 'atan' : 'interp_math.atan', + #'atan' : 'interp_math.atan', 'ceil' : 'interp_math.ceil', - 'sinh' : 'interp_math.sinh', - 'cos' : 'interp_math.cos', - 'tanh' : 'interp_math.tanh', - 'radians' : 'interp_math.radians', - 'sin' : 'interp_math.sin', + #'sinh' : 'interp_math.sinh', + #'cos' : 'interp_math.cos', + #'tanh' : 'interp_math.tanh', + #'radians' : 'interp_math.radians', + #'sin' : 'interp_math.sin', 'atan2' : 'interp_math.atan2', 'modf' : 'interp_math.modf', 'exp' : 'interp_math.exp', - 'acos' : 'interp_math.acos', + #'acos' : 'interp_math.acos', } From tismer at codespeak.net Wed Jul 27 13:10:58 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 13:10:58 +0200 (CEST) Subject: [pypy-svn] r15174 - pypy/dist/pypy/lib Message-ID: <20050727111058.70A0727B60@code1.codespeak.net> Author: tismer Date: Wed Jul 27 13:10:55 2005 New Revision: 15174 Modified: pypy/dist/pypy/lib/osfilewrapper.py Log: small fix of osfilewrapper. - windows behavior is different. check for the case that we read0 bytes (exit condition) - logical error fixed as well. Modified: pypy/dist/pypy/lib/osfilewrapper.py ============================================================================== --- pypy/dist/pypy/lib/osfilewrapper.py (original) +++ pypy/dist/pypy/lib/osfilewrapper.py Wed Jul 27 13:10:55 2005 @@ -13,7 +13,9 @@ bufs = [] while readcount < expected: # os.read will raise an error itself - buf = os.read(self.fd, expected) + buf = os.read(self.fd, expected - readcount) + if not buf: + break readcount += len(buf) bufs.append(buf) return "".join(bufs) From tismer at codespeak.net Wed Jul 27 14:02:05 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:02:05 +0200 (CEST) Subject: [pypy-svn] r15175 - in pypy/dist/pypy: lib lib/test2 module/__builtin__/test objspace/std Message-ID: <20050727120205.CF87E27B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:02:01 2005 New Revision: 15175 Added: pypy/dist/pypy/lib/_marshal.py - copied, changed from r15173, pypy/dist/pypy/lib/marshal.py pypy/dist/pypy/lib/_osfilewrapper.py - copied unchanged from r15174, pypy/dist/pypy/lib/osfilewrapper.py Removed: pypy/dist/pypy/lib/marshal.py pypy/dist/pypy/lib/osfilewrapper.py Modified: pypy/dist/pypy/lib/test2/test_marshal_extra.py pypy/dist/pypy/module/__builtin__/test/test_import.py pypy/dist/pypy/objspace/std/objspace.py Log: made marshal an early builtin module. - changed marshal to _marshal - changed osfilewrapper to _osfilewrapper - adjusted tests - refactored std/objspace to use some helper functions, because there are now several applications of this I will doo a little more folding of stuff. Copied: pypy/dist/pypy/lib/_marshal.py (from r15173, pypy/dist/pypy/lib/marshal.py) ============================================================================== --- pypy/dist/pypy/lib/marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Wed Jul 27 14:02:01 2005 @@ -4,7 +4,7 @@ """ import types -from osfilewrapper import OsFileWrapper +from _osfilewrapper import OsFileWrapper try: import new Deleted: /pypy/dist/pypy/lib/marshal.py ============================================================================== --- /pypy/dist/pypy/lib/marshal.py Wed Jul 27 14:02:01 2005 +++ (empty file) @@ -1,475 +0,0 @@ -"""Internal Python object serialization - -This module contains functions that can read and write Python values in a binary format. The format is specific to Python, but independent of machine architecture issues (e.g., you can write a Python value to a file on a PC, transport the file to a Sun, and read it back there). Details of the format may change between Python versions. -""" - -import types -from osfilewrapper import OsFileWrapper - -try: - import new -except ImportError: - new = None - -TYPE_NULL = '0' -TYPE_NONE = 'N' -TYPE_FALSE = 'F' -TYPE_TRUE = 'T' -TYPE_STOPITER = 'S' -TYPE_ELLIPSIS = '.' -TYPE_INT = 'i' -TYPE_INT64 = 'I' -TYPE_FLOAT = 'f' -TYPE_COMPLEX = 'x' -TYPE_LONG = 'l' -TYPE_STRING = 's' -TYPE_INTERNED = 't' -TYPE_STRINGREF= 'R' -TYPE_TUPLE = '(' -TYPE_LIST = '[' -TYPE_DICT = '{' -TYPE_CODE = 'c' -TYPE_UNICODE = 'u' -TYPE_UNKNOWN = '?' -TYPE_SET = '<' -TYPE_FROZENSET= '>' - -class Marshaller: - - dispatch = {} - - def __init__(self, fd): - if fd >= 0: - self.fd_wrapper = OsFileWrapper(fd) - else: - self.fd_wrapper = None - self.buffer = [] - - def _write(self, data): - if self.fd_wrapper is not None: - self.fd_wrapper.write(data) - else: - self.buffer.append(data) - - def getvalue(self): - return ''.join(self.buffer) - - def dump(self, x): - try: - self.dispatch[type(x)](self, x) - except KeyError: - for tp in type(x).mro(): - func = self.dispatch.get(tp) - if func: - break - else: - raise ValueError, "unmarshallable object" - func(self, x) - - def w_long64(self, x): - self.w_long(x) - self.w_long(x>>32) - - def w_long(self, x): - self._write(chr((x) & 0xff)) - self._write(chr((x>> 8) & 0xff)) - self._write(chr((x>>16) & 0xff)) - self._write(chr((x>>24) & 0xff)) - - def w_short(self, x): - self._write(chr((x) & 0xff)) - self._write(chr((x>> 8) & 0xff)) - - def dump_none(self, x): - self._write(TYPE_NONE) - dispatch[types.NoneType] = dump_none - - def dump_bool(self, x): - if x: - self._write(TYPE_TRUE) - else: - self._write(TYPE_FALSE) - dispatch[bool] = dump_bool - - def dump_stopiter(self, x): - if x is not StopIteration: - raise ValueError, "unmarshallable object" - self._write(TYPE_STOPITER) - dispatch[type(StopIteration)] = dump_stopiter - - def dump_ellipsis(self, x): - self._write(TYPE_ELLIPSIS) - - try: - dispatch[types.EllipsisType] = dump_ellipsis - except NameError: - pass - - def dump_int(self, x): - y = x>>31 - if y and y != -1: - self._write(TYPE_INT64) - self.w_long64(x) - else: - self._write(TYPE_INT) - self.w_long(x) - dispatch[types.IntType] = dump_int - - def dump_long(self, x): - self._write(TYPE_LONG) - sign = 1 - if x < 0: - sign = -1 - x = -x - digits = [] - while x: - digits.append(x & 0x7FFF) - x = x>>15 - self.w_long(len(digits) * sign) - for d in digits: - self.w_short(d) - dispatch[types.LongType] = dump_long - - def dump_float(self, x): - write = self._write - write(TYPE_FLOAT) - s = `x` - write(chr(len(s))) - write(s) - dispatch[types.FloatType] = dump_float - - def dump_complex(self, x): - write = self._write - write(TYPE_COMPLEX) - s = `x.real` - write(chr(len(s))) - write(s) - s = `x.imag` - write(chr(len(s))) - write(s) - try: - dispatch[types.ComplexType] = dump_complex - except NameError: - pass - - def dump_string(self, x): - # XXX we can't check for interned strings, yet, - # so we (for now) never create TYPE_INTERNED or TYPE_STRINGREF - self._write(TYPE_STRING) - self.w_long(len(x)) - self._write(x) - dispatch[types.StringType] = dump_string - - def dump_unicode(self, x): - self._write(TYPE_UNICODE) - s = x.encode('utf8') - self.w_long(len(s)) - self._write(s) - dispatch[types.UnicodeType] = dump_unicode - - def dump_tuple(self, x): - self._write(TYPE_TUPLE) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[types.TupleType] = dump_tuple - - def dump_list(self, x): - self._write(TYPE_LIST) - self.w_long(len(x)) - for item in x: - self.dump(item) - dispatch[types.ListType] = dump_list - - def dump_dict(self, x): - self._write(TYPE_DICT) - for key, value in x.items(): - self.dump(key) - self.dump(value) - self._write(TYPE_NULL) - dispatch[types.DictionaryType] = dump_dict - - def dump_code(self, x): - self._write(TYPE_CODE) - self.w_long(x.co_argcount) - self.w_long(x.co_nlocals) - self.w_long(x.co_stacksize) - self.w_long(x.co_flags) - self.dump(x.co_code) - self.dump(x.co_consts) - self.dump(x.co_names) - self.dump(x.co_varnames) - self.dump(x.co_freevars) - self.dump(x.co_cellvars) - self.dump(x.co_filename) - self.dump(x.co_name) - self.w_long(x.co_firstlineno) - self.dump(x.co_lnotab) - try: - dispatch[types.CodeType] = dump_code - except NameError: - pass - - def dump_set(self, x): - self._write(TYPE_SET) - self.w_long(len(x)) - for each in x: - self.dump(each) - try: - dispatch[set] = dump_set - except NameError: - pass - - def dump_frozenset(self, x): - self._write(TYPE_FROZENSET) - self.w_long(len(x)) - for each in x: - self.dump(each) - try: - dispatch[frozenset] = dump_frozenset - except NameError: - pass - -class NULL: - pass - -class Unmarshaller: - - dispatch = {} - - def __init__(self, fd): - if fd >= 0: - self.fd_wrapper = OsFileWrapper(fd) - else: - self.fd_wrapper = None - self.bufstr = '' - self.bufpos = 0 - self._stringtable = [] - - def _read(self): - if self.fd_wrapper is not None: - return self.fd_wrapper.read(1) - else: - ret = self.bufstr[self.bufpos] - self.bufpos += 1 - return ret - - def _readn(self, n): - if self.fd_wrapper is not None: - return self.fd_wrapper.read(n) - else: - ret = self.bufstr[self.bufpos : self.bufpos+n] - self.bufpos += n - if self.bufpos > len(self.bufstr): - raise EOFError, "read past buffer" - return ret - - def setvalue(self, data): - self.bufstr = data - - def load(self): - c = self._read() - if not c: - raise EOFError - try: - return self.dispatch[c](self) - except KeyError: - raise ValueError, "bad marshal code: %c (%d)" % (c, ord(c)) - - def r_short(self): - lo = ord(self._read()) - hi = ord(self._read()) - x = lo | (hi<<8) - if x & 0x8000: - x = x - 0x10000 - return x - - def r_long(self): - a = ord(self._read()) - b = ord(self._read()) - c = ord(self._read()) - d = ord(self._read()) - x = a | (b<<8) | (c<<16) | (d<<24) - if d & 0x80 and x > 0: - x = -((1L<<32) - x) - return int(x) - - def r_long64(self): - a = ord(self._read()) - b = ord(self._read()) - c = ord(self._read()) - d = ord(self._read()) - e = long(ord(self._read())) - f = long(ord(self._read())) - g = long(ord(self._read())) - h = long(ord(self._read())) - x = a | (b<<8) | (c<<16) | (d<<24) - x = x | (e<<32) | (f<<40) | (g<<48) | (h<<56) - if h & 0x80 and x > 0: - x = -((1L<<64) - x) - return x - - def load_null(self): - return NULL - dispatch[TYPE_NULL] = load_null - - def load_none(self): - return None - dispatch[TYPE_NONE] = load_none - - def load_true(self): - return True - dispatch[TYPE_TRUE] = load_true - - def load_false(self): - return False - dispatch[TYPE_FALSE] = load_false - - def load_stopiter(self): - return StopIteration - dispatch[TYPE_STOPITER] = load_stopiter - - def load_ellipsis(self): - return Ellipsis - dispatch[TYPE_ELLIPSIS] = load_ellipsis - - def load_int(self): - return self.r_long() - dispatch[TYPE_INT] = load_int - - def load_int64(self): - return self.r_long64() - dispatch[TYPE_INT64] = load_int64 - - def load_long(self): - size = self.r_long() - sign = 1 - if size < 0: - sign = -1 - size = -size - x = 0L - for i in range(size): - d = self.r_short() - x = x | (d<<(i*15L)) - return x * sign - dispatch[TYPE_LONG] = load_long - - def load_float(self): - n = ord(self._read()) - s = self._readn(n) - return float(s) - dispatch[TYPE_FLOAT] = load_float - - def load_complex(self): - n = ord(self._read()) - s = self._readn(n) - real = float(s) - n = ord(self._read()) - s = self._readn(n) - imag = float(s) - return complex(real, imag) - dispatch[TYPE_COMPLEX] = load_complex - - def load_string(self): - n = self.r_long() - return self._readn(n) - dispatch[TYPE_STRING] = load_string - - def load_interned(self): - n = self.r_long() - ret = intern(self._readn(n)) - self._stringtable.append(ret) - return ret - dispatch[TYPE_INTERNED] = load_interned - - def load_stringref(self): - n = self.r_long() - return self._stringtable[n] - dispatch[TYPE_STRINGREF] = load_stringref - - def load_unicode(self): - n = self.r_long() - s = self._readn(n) - ret = s.decode('utf8') - return ret - dispatch[TYPE_UNICODE] = load_unicode - - def load_tuple(self): - return tuple(self.load_list()) - dispatch[TYPE_TUPLE] = load_tuple - - def load_list(self): - n = self.r_long() - list = [] - for i in range(n): - list.append(self.load()) - return list - dispatch[TYPE_LIST] = load_list - - def load_dict(self): - d = {} - while 1: - key = self.load() - if key is NULL: - break - value = self.load() - d[key] = value - return d - dispatch[TYPE_DICT] = load_dict - - def load_code(self): - argcount = self.r_long() - nlocals = self.r_long() - stacksize = self.r_long() - flags = self.r_long() - code = self.load() - consts = self.load() - names = self.load() - varnames = self.load() - freevars = self.load() - cellvars = self.load() - filename = self.load() - name = self.load() - firstlineno = self.r_long() - lnotab = self.load() - if not new: - raise RuntimeError, "can't unmarshal code objects; no 'new' module" - return new.code(argcount, nlocals, stacksize, flags, code, consts, - names, varnames, filename, name, firstlineno, lnotab, - freevars, cellvars) - dispatch[TYPE_CODE] = load_code - - def load_set(self): - n = self.r_long() - args = [self.load() for i in range(n)] - return set(args) - dispatch[TYPE_SET] = load_set - - def load_frozenset(self): - n = self.r_long() - args = [self.load() for i in range(n)] - return frozenset(args) - dispatch[TYPE_FROZENSET] = load_frozenset - -try: - set -except NameError: - def set(x): - raise ValueError("cannot unmarshal set objects on Python < 2.4") - frozenset = set - -def dump(x, f): - Marshaller(f.fileno()).dump(x) - -def load(f): - return Unmarshaller(f.fileno()).load() - -def dumps(x): - m = Marshaller(-1) - m.dump(x) - return m.getvalue() - -def loads(s): - um = Unmarshaller(-1) - um.setvalue(s) - return um.load() Deleted: /pypy/dist/pypy/lib/osfilewrapper.py ============================================================================== --- /pypy/dist/pypy/lib/osfilewrapper.py Wed Jul 27 14:02:01 2005 +++ (empty file) @@ -1,36 +0,0 @@ -import os - -class OsFileWrapper(object): - """ Very simple os file wrapper. - Note user is responsible for closing. - XXX Could add a simple buffer mechanism. """ - - def __init__(self, fd): - self.fd = fd - - def read(self, expected): - readcount = 0 - bufs = [] - while readcount < expected: - # os.read will raise an error itself - buf = os.read(self.fd, expected - readcount) - if not buf: - break - readcount += len(buf) - bufs.append(buf) - return "".join(bufs) - - def write(self, buf): - writecount = 0 - towrite = len(buf) - while writecount < towrite: - # os.write will raise an error itself - writecount += os.write(self.fd, buf[writecount:]) - - def close(self): - os.close(self.fd) - - -def create_wrapper(filename, flag, mode=0777): - fd = os.open(filename, flag, mode) - return OsFileWrapper(fd) Modified: pypy/dist/pypy/lib/test2/test_marshal_extra.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_marshal_extra.py (original) +++ pypy/dist/pypy/lib/test2/test_marshal_extra.py Wed Jul 27 14:02:01 2005 @@ -2,7 +2,7 @@ import py import sys import marshal as cpy_marshal -from pypy.lib import marshal +from pypy.lib import _marshal as marshal from pypy.tool.udir import udir Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Wed Jul 27 14:02:01 2005 @@ -5,7 +5,7 @@ from pypy.tool.udir import udir import sys, os import tempfile, marshal -from pypy.tool.osfilewrapper import OsFileWrapper +from pypy.lib._osfilewrapper import OsFileWrapper from pypy.module.__builtin__.importing import BIN_READMASK Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Jul 27 14:02:01 2005 @@ -80,6 +80,10 @@ self.w_instance = W_TypeObject(self, 'instance', [self.w_object], {}) self.setup_old_style_classes() + #early bootstrap for marshal + mod = self.setup_marshal() + self.sys.setmodule(self.wrap(mod)) + # fix up a problem where multimethods apparently don't # like to define this at interp-level self.appexec([self.w_dict], """ @@ -111,21 +115,34 @@ # sanity check that this approach is working and is not too late assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_classobj'))),"app-level code has seen dummy old style classes" assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_instance'))),"app-level code has seen dummy old style classes" + mod, w_dic = self.create_builtin_module('_classobj.py', 'classobj') + w_purify = self.getitem(w_dic, self.wrap('purify')) + w_classobj = self.getitem(w_dic, self.wrap('classobj')) + w_instance = self.getitem(w_dic, self.wrap('instance')) + self.call_function(w_purify) + self.w_classobj = w_classobj + self.w_instance = w_instance + + def setup_marshal(self): + mod, w_dic = self.create_builtin_module('_marshal.py', 'marshal') + return mod + + def create_builtin_module(self, pyname, publicname): + """NOT_RPYTHON + helper function which returns the new unwrapped module and its waapped dict. + """ # generate on-the-fly class Fake: pass fake = Fake() import pypy.lib as lib - fname = os.path.join(os.path.split(lib.__file__)[0], '_classobj.py') + fname = os.path.join(os.path.split(lib.__file__)[0], pyname) fake.filename = fname fake.source = file(fname).read() - fake.modname = 'classobj' + fake.modname = publicname w_dic = PyPyCacheDir.build_applevelinterp_dict(fake, self) - w_purify = self.getitem(w_dic, self.wrap('purify')) - w_classobj = self.getitem(w_dic, self.wrap('classobj')) - w_instance = self.getitem(w_dic, self.wrap('instance')) - self.call_function(w_purify) - self.w_classobj = w_classobj - self.w_instance = w_instance + from pypy.interpreter.module import Module + mod = Module(self, self.wrap(publicname), w_dic) + return mod, w_dic def setuselibfile(self): """ NOT_RPYTHON use our application level file implementation @@ -172,18 +189,10 @@ bases = [space.w_object] res = W_TypeObject(space, name, bases, dic) return res - # generate on-the-fly - class Fake: pass - fake = Fake() - import pypy.lib as lib - fname = os.path.join(os.path.split(lib.__file__)[0], '_exceptions.py') - fake.filename = fname - fake.source = file(fname).read() - fake.modname = 'exceptions' try: # note that we hide the real call method by an instance variable! self.call = call - w_dic = PyPyCacheDir.build_applevelinterp_dict(fake, self) + mod, w_dic = self.create_builtin_module('_exceptions.py', 'exceptions') self.w_IndexError = self.getitem(w_dic, self.wrap("IndexError")) self.w_StopIteration = self.getitem(w_dic, self.wrap("StopIteration")) @@ -198,11 +207,8 @@ excname = name w_exc = self.getitem(w_dic, w_name) setattr(self, "w_"+excname, w_exc) - - # XXX refine things, clean up, create a builtin module... - # but for now, we do a regular one. - from pypy.interpreter.module import Module - return Module(self, self.wrap("exceptions"), w_dic) + + return mod def createexecutioncontext(self): # add space specific fields to execution context From arigo at codespeak.net Wed Jul 27 14:02:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 14:02:46 +0200 (CEST) Subject: [pypy-svn] r15176 - pypy/dist/pypy/module/posix Message-ID: <20050727120246.260CE27B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 14:02:42 2005 New Revision: 15176 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/app_posix.py pypy/dist/pypy/module/posix/interp_posix.py Log: A few fixes to our posix modules, and support for stat_result classes. Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Wed Jul 27 14:02:42 2005 @@ -4,8 +4,14 @@ import os class Module(MixedModule): + """This module provides access to operating system functionality that is +standardized by the C Standard and the POSIX standard (a thinly +disguised Unix interface). Refer to the library manual and +corresponding Unix manual entries for more information on calls.""" + appleveldefs = { - 'error' : 'app_posix.error', + 'error' : 'app_posix.error', + 'stat_result': 'app_posix.stat_result', } interpleveldefs = { @@ -19,8 +25,6 @@ 'fstat' : 'interp_posix.fstat', 'stat' : 'interp_posix.stat', 'dup' : 'interp_posix.dup', - '__doc__' : "space.wrap('Posix module')", - '__name__' : "space.wrap('The builtin posix module')", } for constant in ['EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', @@ -36,4 +40,4 @@ Module.interpleveldefs[constant] = ("space.wrap(%s)" % (getattr(os, constant), )) except AttributeError: - pass \ No newline at end of file + pass Modified: pypy/dist/pypy/module/posix/app_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/app_posix.py (original) +++ pypy/dist/pypy/module/posix/app_posix.py Wed Jul 27 14:02:42 2005 @@ -1,5 +1,24 @@ +# NOT_RPYTHON -class OSError(Exception): - pass +error = OSError -error = OSError \ No newline at end of file + +def tuple_item_getter(n): # helper to make properties + def getter(self): + return self[n] + return property(getter) + + +class stat_result(tuple): + __slots__ = [] + + st_mode = tuple_item_getter(0) + st_ino = tuple_item_getter(1) + st_dev = tuple_item_getter(2) + st_nlink = tuple_item_getter(3) + st_uid = tuple_item_getter(4) + st_gid = tuple_item_getter(5) + st_size = tuple_item_getter(6) + st_atime = tuple_item_getter(7) + st_mtime = tuple_item_getter(8) + st_ctime = tuple_item_getter(9) Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Wed Jul 27 14:02:42 2005 @@ -1,19 +1,16 @@ from pypy.interpreter.baseobjspace import ObjSpace +from pypy.rpython.rarithmetic import intmask import os from os import * -def open(space, w_fname, w_flag, w_mode=0777): - fname = space.str_w(w_fname) - flag = space.int_w(w_flag) - mode = space.int_w(w_mode) - # notice that an unwrap_spec attached to open could be used to the same effect +def open(space, fname, flag, mode=0777): fd = os.open(fname, flag, mode) return space.wrap(fd) - +open.unwrap_spec = [ObjSpace, str, int, int] def lseek(space, fd, pos, how): - os.lseek(fd,pos,how) + return space.wrap(os.lseek(fd, pos, how)) lseek.unwrap_spec = [ObjSpace, int, int, int] def isatty(space, fd): @@ -21,7 +18,7 @@ isatty.unwrap_spec = [ObjSpace, int] def read(space, fd, buffersize): - return space.wrap(os.read(fd,buffersize)) + return space.wrap(os.read(fd, buffersize)) read.unwrap_spec = [ObjSpace, int, int] def write(space, fd, data): @@ -36,12 +33,21 @@ os.ftruncate(fd, length) ftruncate.unwrap_spec = [ObjSpace, int, int] +def build_stat_result(space, st): + # cannot index tuples with a variable... + lst = [st[0], st[1], st[2], st[3], st[4], + st[5], st[6], st[7], st[8], st[9]] + w_tuple = space.newtuple([space.wrap(intmask(x)) for x in lst]) + w_stat_result = space.getattr(space.getbuiltinmodule('posix'), + space.wrap('stat_result')) + return space.call_function(w_stat_result, w_tuple) + def fstat(space, fd): - return space.wrap(os.fstat(fd)) + return build_stat_result(space, os.fstat(fd)) fstat.unwrap_spec = [ObjSpace, int] def stat(space, path): - return space.wrap(os.stat(path)) + return build_stat_result(space, os.stat(path)) stat.unwrap_spec = [ObjSpace, str] def getcwd(space): From arigo at codespeak.net Wed Jul 27 14:06:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 14:06:33 +0200 (CEST) Subject: [pypy-svn] r15177 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727120633.DF25C27B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 14:06:31 2005 New Revision: 15177 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Missing fix. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 14:06:31 2005 @@ -7,7 +7,7 @@ from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace -from pypy.lib.osfilewrapper import OsFileWrapper +from pypy.lib._osfilewrapper import OsFileWrapper # XXX this uses the os.path module at interp-level, which means # XXX that translate_pypy will produce a translated version of From arigo at codespeak.net Wed Jul 27 14:08:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 14:08:16 +0200 (CEST) Subject: [pypy-svn] r15178 - in pypy/dist/pypy: lib/test2 tool/test Message-ID: <20050727120816.7CF8327B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 14:08:11 2005 New Revision: 15178 Added: pypy/dist/pypy/lib/test2/test_osfilewrapper.py - copied, changed from r15167, pypy/dist/pypy/tool/test/test_osfilewrapper.py Removed: pypy/dist/pypy/tool/test/test_osfilewrapper.py Log: Moved this test file to follow osfilewrapper.py. Copied: pypy/dist/pypy/lib/test2/test_osfilewrapper.py (from r15167, pypy/dist/pypy/tool/test/test_osfilewrapper.py) ============================================================================== --- pypy/dist/pypy/tool/test/test_osfilewrapper.py (original) +++ pypy/dist/pypy/lib/test2/test_osfilewrapper.py Wed Jul 27 14:08:11 2005 @@ -1,5 +1,5 @@ import autopath -from pypy.tool.osfilewrapper import OsFileWrapper, create_wrapper +from pypy.lib._osfilewrapper import OsFileWrapper, create_wrapper from pypy.tool.udir import udir import os Deleted: /pypy/dist/pypy/tool/test/test_osfilewrapper.py ============================================================================== --- /pypy/dist/pypy/tool/test/test_osfilewrapper.py Wed Jul 27 14:08:11 2005 +++ (empty file) @@ -1,32 +0,0 @@ -import autopath -from pypy.tool.osfilewrapper import OsFileWrapper, create_wrapper -from pypy.tool.udir import udir -import os - -def test_reads(): - - p = str(udir.join('test.dat')) - - # As we are testing file writes, only using udir to create a path - buf = "1234567890" - f = open(p, "w") - f.write(buf) - f.close() - - for ii in range(10): - f = create_wrapper(p, os.O_RDONLY) - assert f.read(ii) == buf[:ii] - -def test_writes_reads(): - - # As we are testing file writes, only using udir to create a path - buf = "1234567890" - for ii in range(10): - p = str(udir.join('test.dat')) - f1 = create_wrapper(p, os.O_WRONLY) - f1.write(buf[:ii]) - f1.close() - - f2 = create_wrapper(p, os.O_RDONLY) - assert f2.read(ii) == buf[:ii] - f2.close() From tismer at codespeak.net Wed Jul 27 14:10:52 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:10:52 +0200 (CEST) Subject: [pypy-svn] r15179 - pypy/dist/pypy/lib Message-ID: <20050727121052.E611327B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:10:51 2005 New Revision: 15179 Modified: pypy/dist/pypy/lib/_marshal.py Log: fixed marshal to use _ for its internal classes Modified: pypy/dist/pypy/lib/_marshal.py ============================================================================== --- pypy/dist/pypy/lib/_marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Wed Jul 27 14:10:51 2005 @@ -34,7 +34,7 @@ TYPE_SET = '<' TYPE_FROZENSET= '>' -class Marshaller: +class _Marshaller: dispatch = {} @@ -230,10 +230,10 @@ except NameError: pass -class NULL: +class _NULL: pass -class Unmarshaller: +class _Unmarshaller: dispatch = {} @@ -310,7 +310,7 @@ return x def load_null(self): - return NULL + return _NULL dispatch[TYPE_NULL] = load_null def load_none(self): @@ -410,7 +410,7 @@ d = {} while 1: key = self.load() - if key is NULL: + if key is _NULL: break value = self.load() d[key] = value @@ -459,17 +459,17 @@ frozenset = set def dump(x, f): - Marshaller(f.fileno()).dump(x) + _Marshaller(f.fileno()).dump(x) def load(f): - return Unmarshaller(f.fileno()).load() + return _Unmarshaller(f.fileno()).load() def dumps(x): - m = Marshaller(-1) + m = _Marshaller(-1) m.dump(x) return m.getvalue() def loads(s): - um = Unmarshaller(-1) + um = _Unmarshaller(-1) um.setvalue(s) return um.load() From arigo at codespeak.net Wed Jul 27 14:13:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 14:13:08 +0200 (CEST) Subject: [pypy-svn] r15180 - in pypy/dist/pypy/translator: . goal Message-ID: <20050727121308.AC51327B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 14:13:07 2005 New Revision: 15180 Modified: pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: * enable -nofakedmodules by default while translate_pypy'ing. * support for the Ellipsis instance in geninterplevel.py. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Jul 27 14:13:07 2005 @@ -77,7 +77,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.5' # bump this for substantial changes +GI_VERSION = '1.1.6' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): @@ -147,6 +147,7 @@ self.rpynames = {Constant(None).key: 'space.w_None', Constant(False).key: 'space.w_False', Constant(True).key: 'space.w_True', + Constant(Ellipsis).key: 'space.w_Ellipsis', Constant(OperationError).key: late_OperationError, Constant(Arguments).key: late_Arguments, } Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Wed Jul 27 14:13:07 2005 @@ -41,6 +41,7 @@ from pypy.tool.option import Options options = Options() options.uselibfile = True + options.nofakedmodules = True space = StdObjSpace(options) # manually imports app_main.py From rxe at codespeak.net Wed Jul 27 14:16:30 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 27 Jul 2005 14:16:30 +0200 (CEST) Subject: [pypy-svn] r15181 - in pypy/dist/pypy/module/__builtin__: . test test/impsubdir/compiled Message-ID: <20050727121630.37DBD27B61@code1.codespeak.net> Author: rxe Date: Wed Jul 27 14:16:27 2005 New Revision: 15181 Added: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/ pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/__init__.py pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.py Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Add some more tests. Small fixes to write_compiled_module() Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 14:16:27 2005 @@ -461,6 +461,6 @@ _w_long(osfile, mtime) w_marshal = space.getbuiltinmodule('marshal') w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) - w_marshaller = space.call_function(w_U, space.wrap(fd)) - space.call_method(w_unmarshaller, 'dump', space.wrap(co)) + w_unmarshaller = space.call_function(w_M, space.wrap(fd)) + w_res = space.call_method(w_unmarshaller, 'dump', space.wrap(co)) os.close(fd) Added: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/__init__.py ============================================================================== Added: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.py Wed Jul 27 14:16:27 2005 @@ -0,0 +1 @@ +x = 84 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Wed Jul 27 14:16:27 2005 @@ -7,10 +7,30 @@ import tempfile, marshal from pypy.lib._osfilewrapper import OsFileWrapper -from pypy.module.__builtin__.importing import BIN_READMASK +from pypy.module.__builtin__ import importing + -def _setup(space): - dn=os.path.abspath(os.path.join(os.path.dirname(__file__), 'impsubdir')) +def compile_pyfile(space, pathname): + import time + fd = os.open(pathname, importing.BIN_READMASK, 0777) + osfile = OsFileWrapper(fd) + w_ret = importing.parse_source_module(space, + pathname, + osfile) + osfile.close() + pycode = space.interpclass_w(w_ret) + assert type(pycode) is pypy.interpreter.pycode.PyCode + + importing.write_compiled_module(space, + pycode, + pathname + "c", + int(time.time())) + +def _setup(space): + j = os.path.join + dn = os.path.abspath(j(os.path.dirname(__file__), 'impsubdir')) + compile_pyfile(space, j(j(dn, "compiled"), "x.py")) + return space.appexec([space.wrap(dn)], """ (dn): import sys @@ -31,7 +51,9 @@ def setup_class(cls): # interpreter-level cls.saved_modules = _setup(cls.space) + #XXX Compile class + def teardown_class(cls): # interpreter-level _teardown(cls.space, cls.saved_modules) @@ -159,15 +181,17 @@ import pkg.pkg2.b raises(ImportError,imp_b) -from pypy.module.__builtin__ import importing + def Xtest_pyc(self): + import sys + import compiled.x + assert compiled.x == sys.modules.get('compiled.x') def _getlong(data): x = marshal.dumps(data) return x[-4:] def _testfile(magic, mtime, co=None): - fd, cpathname = tempfile.mkstemp() - os.close(fd) + cpathname = str(udir.join('test.pyc')) f = file(cpathname, "wb") f.write(_getlong(magic)) f.write(_getlong(mtime)) @@ -176,6 +200,13 @@ f.close() return cpathname +def _testfilesource(): + pathname = str(udir.join('test.py')) + f = file(pathname, "wb") + f.write("x=42") + f.close() + return pathname + class TestPycStuff: # ___________________ .pyc related stuff _________________ @@ -203,13 +234,14 @@ mtime = 12345 co = compile('x = 42', '?', 'exec') cpathname = _testfile(importing.pyc_magic, mtime, co) - fd = os.open(cpathname, BIN_READMASK, 0777) + fd = os.open(cpathname, importing.BIN_READMASK, 0777) os.lseek(fd, 8, 0) - code_w = importing.read_compiled_module(space, cpathname, OsFileWrapper(fd)) + w_code = importing.read_compiled_module(space, cpathname, OsFileWrapper(fd)) + pycode = space.interpclass_w(w_code) os.close(fd) - assert type(code_w) is pypy.interpreter.pycode.PyCode + assert type(pycode) is pypy.interpreter.pycode.PyCode w_dic = space.newdict([]) - code_w.exec_code(space, w_dic, w_dic) + pycode.exec_code(space, w_dic, w_dic) w_ret = space.getitem(w_dic, space.wrap('x')) ret = space.int_w(w_ret) assert ret == 42 @@ -221,15 +253,110 @@ co = compile('x = 42', '?', 'exec') cpathname = _testfile(importing.pyc_magic, mtime, co) w_modulename = space.wrap('somemodule') - fd = os.open(cpathname, BIN_READMASK, 0777) + fd = os.open(cpathname, importing.BIN_READMASK, 0777) w_mod = space.wrap(Module(space, w_modulename)) - w_ret = importing.load_compiled_module(space, w_modulename, w_mod, cpathname, OsFileWrapper(fd)) + w_ret = importing.load_compiled_module(space, + w_modulename, + w_mod, + cpathname, + OsFileWrapper(fd)) os.close(fd) assert w_mod is w_ret w_ret = space.getattr(w_mod, space.wrap('x')) ret = space.int_w(w_ret) assert ret == 42 + def test_parse_source_module(self): + space = self.space + pathname = _testfilesource() + fd = os.open(pathname, importing.BIN_READMASK, 0777) + osfile = OsFileWrapper(fd) + w_ret = importing.parse_source_module(space, + pathname, + osfile) + osfile.close() + pycode = space.interpclass_w(w_ret) + assert type(pycode) is pypy.interpreter.pycode.PyCode + w_dic = space.newdict([]) + pycode.exec_code(space, w_dic, w_dic) + w_ret = space.getitem(w_dic, space.wrap('x')) + ret = space.int_w(w_ret) + assert ret == 42 + + def test_long_writes(self): + pathname = str(udir.join('test.dat')) + f = file(pathname, "wb") + osfile = OsFileWrapper(f.fileno()) + importing._w_long(osfile, 42) + importing._w_long(osfile, 12312) + importing._w_long(osfile, 128397198) + f.close() + f = file(pathname, "r") + osfile = OsFileWrapper(f.fileno()) + assert importing._r_long(osfile) == 42 + assert importing._r_long(osfile) == 12312 + assert importing._r_long(osfile) == 128397198 + + def test_load_source_module(self): + space = self.space + w_modulename = space.wrap('somemodule') + w_mod = space.wrap(Module(space, w_modulename)) + pathname = _testfilesource() + fd = os.open(pathname, importing.BIN_READMASK, 0777) + osfile = OsFileWrapper(fd) + w_ret = importing.load_source_module(space, + w_modulename, + w_mod, + pathname, + osfile) + osfile.close() + assert w_mod is w_ret + w_ret = space.getattr(w_mod, space.wrap('x')) + ret = space.int_w(w_ret) + assert ret == 42 + + #XXX Note tested while no writing + + def test_write_compiled_module(self): + space = self.space + pathname = _testfilesource() + fd = os.open(pathname, importing.BIN_READMASK, 0777) + osfile = OsFileWrapper(fd) + w_ret = importing.parse_source_module(space, + pathname, + osfile) + osfile.close() + pycode = space.interpclass_w(w_ret) + assert type(pycode) is pypy.interpreter.pycode.PyCode + + cpathname = str(udir.join('cpathname.pyc')) + mtime = 12345 + importing.write_compiled_module(space, + pycode, + cpathname, + mtime) + + # check + pathname = str(udir.join('cpathname.py')) + ret = importing.check_compiled_module(pathname, mtime, cpathname) + assert ret == 1 + + # read compile module + fd = os.open(cpathname, importing.BIN_READMASK, 0777) + os.lseek(fd, 8, 0) + osfile = OsFileWrapper(fd) + w_code = importing.read_compiled_module(space, cpathname, osfile) + pycode = space.interpclass_w(w_code) + os.close(fd) + + # check value of load + w_dic = space.newdict([]) + pycode.exec_code(space, w_dic, w_dic) + w_ret = space.getitem(w_dic, space.wrap('x')) + ret = space.int_w(w_ret) + assert ret == 42 + + def test_PYTHONPATH_takes_precedence(space): if sys.platform == "win32": py.test.skip("unresolved issues with win32 shell quoting rules") From tismer at codespeak.net Wed Jul 27 14:18:25 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:18:25 +0200 (CEST) Subject: [pypy-svn] r15182 - pypy/dist/pypy/objspace/std Message-ID: <20050727121825.C364527B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:18:24 2005 New Revision: 15182 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: a little bit of refactoring. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Jul 27 14:18:24 2005 @@ -71,18 +71,17 @@ setattr(self, 'w_' + typedef.name, w_type) # exceptions & builtins - mod = self.setup_exceptions() + w_mod = self.setup_exceptions() self.make_builtins() - self.sys.setmodule(self.wrap(mod)) + self.sys.setmodule(w_mod) # dummy old-style classes types self.w_classobj = W_TypeObject(self, 'classobj', [self.w_object], {}) self.w_instance = W_TypeObject(self, 'instance', [self.w_object], {}) self.setup_old_style_classes() - #early bootstrap for marshal - mod = self.setup_marshal() - self.sys.setmodule(self.wrap(mod)) + # early bootstrap for marshal + self.sys.setmodule(self.setup_marshal()) # fix up a problem where multimethods apparently don't # like to define this at interp-level @@ -115,7 +114,7 @@ # sanity check that this approach is working and is not too late assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_classobj'))),"app-level code has seen dummy old style classes" assert not self.is_true(self.contains(self.builtin.w_dict,self.wrap('_instance'))),"app-level code has seen dummy old style classes" - mod, w_dic = self.create_builtin_module('_classobj.py', 'classobj') + w_mod, w_dic = self.create_builtin_module('_classobj.py', 'classobj') w_purify = self.getitem(w_dic, self.wrap('purify')) w_classobj = self.getitem(w_dic, self.wrap('classobj')) w_instance = self.getitem(w_dic, self.wrap('instance')) @@ -124,12 +123,12 @@ self.w_instance = w_instance def setup_marshal(self): - mod, w_dic = self.create_builtin_module('_marshal.py', 'marshal') - return mod + w_mod, w_dic = self.create_builtin_module('_marshal.py', 'marshal') + return w_mod def create_builtin_module(self, pyname, publicname): """NOT_RPYTHON - helper function which returns the new unwrapped module and its waapped dict. + helper function which returns the wrapped module and its dict. """ # generate on-the-fly class Fake: pass @@ -142,7 +141,8 @@ w_dic = PyPyCacheDir.build_applevelinterp_dict(fake, self) from pypy.interpreter.module import Module mod = Module(self, self.wrap(publicname), w_dic) - return mod, w_dic + w_mod = self.wrap(mod) + return w_mod, w_dic def setuselibfile(self): """ NOT_RPYTHON use our application level file implementation From tismer at codespeak.net Wed Jul 27 14:20:54 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:20:54 +0200 (CEST) Subject: [pypy-svn] r15183 - pypy/extradoc/sprintinfo Message-ID: <20050727122054.BD41327B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:20:53 2005 New Revision: 15183 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: actualized the working list Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Wed Jul 27 14:20:53 2005 @@ -101,7 +101,7 @@ make py.py --file --nofakedmodules work (crashes somehow) - - ? + - DONE (chris) allways enforce geninterping of marshal, maybe similar to what we did with exceptions From tismer at codespeak.net Wed Jul 27 14:30:18 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:30:18 +0200 (CEST) Subject: [pypy-svn] r15184 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727123018.BA16F27B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:30:17 2005 New Revision: 15184 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: small namingglitch Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 14:30:17 2005 @@ -322,9 +322,10 @@ Python 2.4a0: 62041 Python 2.4a3: 62051 Python 2.4b1: 62061 + Python 2.5a0: 62071 """ -# XXX how do we configure this ??? +# we decided to use the magic of 2.4.1 MAGIC = 62061 | (ord('\r')<<16) | (ord('\n')<<24) """Magic word as global; note that _PyImport_Init() can change the @@ -461,6 +462,6 @@ _w_long(osfile, mtime) w_marshal = space.getbuiltinmodule('marshal') w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) - w_unmarshaller = space.call_function(w_M, space.wrap(fd)) - w_res = space.call_method(w_unmarshaller, 'dump', space.wrap(co)) + w_marshaller = space.call_function(w_M, space.wrap(fd)) + w_res = space.call_method(w_marshaller, 'dump', space.wrap(co)) os.close(fd) From tismer at codespeak.net Wed Jul 27 14:32:53 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:32:53 +0200 (CEST) Subject: [pypy-svn] r15185 - pypy/extradoc/sprintinfo Message-ID: <20050727123253.4408427B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:32:51 2005 New Revision: 15185 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: updated issues Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Wed Jul 27 14:32:51 2005 @@ -131,7 +131,8 @@ An example where it still happens is EllipsisType which gets wrapped by geninterplevel. - - Richard, Chris + - DONE + Richard, Chris Choose a PYC file version for PyPy (2.4.1) Using this version is ok, because our compiler exactly produces these. The extra functionality in From arigo at codespeak.net Wed Jul 27 14:48:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 14:48:26 +0200 (CEST) Subject: [pypy-svn] r15186 - in pypy/dist/pypy: interpreter interpreter/test module/__builtin__ Message-ID: <20050727124826.EBEAA27B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 14:48:21 2005 New Revision: 15186 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/test/test_compiler.py pypy/dist/pypy/module/__builtin__/compiling.py Log: Properly implemented the built-in compile() on unicode sources. (The pyparser works fine on encoded strings, processing the -*- coding -*- declaration.) Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Wed Jul 27 14:48:21 2005 @@ -178,11 +178,6 @@ the whole source after having only added a new '\n') """ def compile(self, source, filename, mode, flags): - assert isinstance(source, str) # xxx__builtin__.compile is cheating in the unicode case - # we need to do something about that - # CPython encode unicode for compilation into utf-8 - # and use a special internal flag to control behavior! - from pyparser.error import ParseError from pyparser.pythonutil import internal_pypy_parse flags |= __future__.generators.compiler_flag # always on (2.2 compat) Modified: pypy/dist/pypy/interpreter/test/test_compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_compiler.py (original) +++ pypy/dist/pypy/interpreter/test/test_compiler.py Wed Jul 27 14:48:21 2005 @@ -17,6 +17,10 @@ w_res = code.exec_code(space, space.newdict([]), space.newdict([])) assert space.int_w(w_res) == 42 + def test_eval_unicode(self): + assert (eval(unicode('u"\xc3\xa5"', 'utf8')) == + unicode('\xc3\xa5', 'utf8')) + def test_compile_command(self): c0 = self.compiler.compile_command('\t # hello\n ', '?', 'exec', 0) c1 = self.compiler.compile_command('print 6*7', '?', 'exec', 0) Modified: pypy/dist/pypy/module/__builtin__/compiling.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/compiling.py (original) +++ pypy/dist/pypy/module/__builtin__/compiling.py Wed Jul 27 14:48:21 2005 @@ -9,7 +9,11 @@ def compile(space, w_source, filename, mode, flags=0, dont_inherit=0): if space.is_true(space.isinstance(w_source, space.w_unicode)): - str_ = space.unwrap(w_source) # Bad exposing of unicode internals + # hack: encode the unicode string as UTF-8 and attach a 'coding' + # declaration at the start + w_source = space.call_method(w_source, 'encode', space.wrap('utf-8')) + str_ = space.str_w(w_source) + str_ = "# -*- coding: utf-8 -*-\n" + str_ else: str_ = space.str_w(w_source) From rxe at codespeak.net Wed Jul 27 14:50:35 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 27 Jul 2005 14:50:35 +0200 (CEST) Subject: [pypy-svn] r15187 - in pypy/dist/pypy/module/__builtin__/test: . impsubdir/compiled Message-ID: <20050727125035.5C47827B61@code1.codespeak.net> Author: rxe Date: Wed Jul 27 14:50:33 2005 New Revision: 15187 Added: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.pyc (contents, props changed) Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py Log: All tests pass! Added: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.pyc ============================================================================== Binary file. No diff available. Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Wed Jul 27 14:50:33 2005 @@ -9,28 +9,13 @@ from pypy.module.__builtin__ import importing - -def compile_pyfile(space, pathname): - import time - fd = os.open(pathname, importing.BIN_READMASK, 0777) - osfile = OsFileWrapper(fd) - w_ret = importing.parse_source_module(space, - pathname, - osfile) - osfile.close() - pycode = space.interpclass_w(w_ret) - assert type(pycode) is pypy.interpreter.pycode.PyCode - - importing.write_compiled_module(space, - pycode, - pathname + "c", - int(time.time())) +def get_import_path(): + j = os.path.join + p = os.path.abspath(j(os.path.dirname(__file__), 'impsubdir')) + return p def _setup(space): - j = os.path.join - dn = os.path.abspath(j(os.path.dirname(__file__), 'impsubdir')) - compile_pyfile(space, j(j(dn, "compiled"), "x.py")) - + dn = get_import_path() return space.appexec([space.wrap(dn)], """ (dn): import sys @@ -181,7 +166,7 @@ import pkg.pkg2.b raises(ImportError,imp_b) - def Xtest_pyc(self): + def test_pyc(self): import sys import compiled.x assert compiled.x == sys.modules.get('compiled.x') From tismer at codespeak.net Wed Jul 27 14:52:24 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 14:52:24 +0200 (CEST) Subject: [pypy-svn] r15188 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727125224.1BA9827B61@code1.codespeak.net> Author: tismer Date: Wed Jul 27 14:52:22 2005 New Revision: 15188 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: just a comment why we don't use the marshaller's w_long Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 14:52:22 2005 @@ -368,7 +368,8 @@ return w_mod -# helper, to avoid exposing internals of marshal +# helper, to avoid exposing internals of marshal and the +# difficulties of using it though applevel. def _r_long(osfile): a = ord(osfile.read(1)) b = ord(osfile.read(1)) @@ -462,6 +463,6 @@ _w_long(osfile, mtime) w_marshal = space.getbuiltinmodule('marshal') w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) - w_marshaller = space.call_function(w_M, space.wrap(fd)) - w_res = space.call_method(w_marshaller, 'dump', space.wrap(co)) + w_unmarshaller = space.call_function(w_M, space.wrap(fd)) + w_res = space.call_method(w_unmarshaller, 'dump', space.wrap(co)) os.close(fd) From rxe at codespeak.net Wed Jul 27 15:00:31 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 27 Jul 2005 15:00:31 +0200 (CEST) Subject: [pypy-svn] r15190 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727130031.CA58127B61@code1.codespeak.net> Author: rxe Date: Wed Jul 27 15:00:30 2005 New Revision: 15190 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: re - small namingglitch Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 15:00:30 2005 @@ -463,6 +463,6 @@ _w_long(osfile, mtime) w_marshal = space.getbuiltinmodule('marshal') w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) - w_unmarshaller = space.call_function(w_M, space.wrap(fd)) - w_res = space.call_method(w_unmarshaller, 'dump', space.wrap(co)) + w_marshaller = space.call_function(w_M, space.wrap(fd)) + w_res = space.call_method(w_marshaller, 'dump', space.wrap(co)) os.close(fd) From arigo at codespeak.net Wed Jul 27 15:42:06 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 15:42:06 +0200 (CEST) Subject: [pypy-svn] r15194 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727134206.3807627B61@code1.codespeak.net> Author: arigo Date: Wed Jul 27 15:42:03 2005 New Revision: 15194 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Removed the last SomeObject from the source of PyPy :-) Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 15:42:03 2005 @@ -8,6 +8,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace from pypy.lib._osfilewrapper import OsFileWrapper +from pypy.rpython.rarithmetic import intmask # XXX this uses the os.path module at interp-level, which means # XXX that translate_pypy will produce a translated version of @@ -370,14 +371,15 @@ # helper, to avoid exposing internals of marshal and the # difficulties of using it though applevel. +_r_correction = intmask(1L<<32) # == 0 on 32-bit machines def _r_long(osfile): a = ord(osfile.read(1)) b = ord(osfile.read(1)) c = ord(osfile.read(1)) d = ord(osfile.read(1)) x = a | (b<<8) | (c<<16) | (d<<24) - if d & 0x80 and x > 0: - x = -((1L<<32) - x) + if _r_correction and d & 0x80 and x > 0: + x -= _r_correction return int(x) def _w_long(osfile, x): From nik at codespeak.net Wed Jul 27 18:24:40 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Wed, 27 Jul 2005 18:24:40 +0200 (CEST) Subject: [pypy-svn] r15198 - pypy/dist/pypy/translator Message-ID: <20050727162440.A00C827B61@code1.codespeak.net> Author: nik Date: Wed Jul 27 18:24:39 2005 New Revision: 15198 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: added buffer, set and frozenset types to typename_mapping. buffer because i need it for geniterping the work-in-progress array module. the sets because _marshal seems to need it, at least py.py wouldn't start up anymore for me without them. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Jul 27 18:24:39 2005 @@ -791,6 +791,9 @@ "type((lambda:42).__get__(42))"), property: (eval_helper, "property", 'property'), type(Ellipsis): (eval_helper, 'EllipsisType', 'types.EllipsisType'), + set: (eval_helper, "set", "set"), + frozenset: (eval_helper, "frozenset", "frozenset"), + buffer: (eval_helper, "buffer", "buffer"), } def nameof_type(self, cls): From pedronis at codespeak.net Wed Jul 27 19:12:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Jul 2005 19:12:55 +0200 (CEST) Subject: [pypy-svn] r15201 - pypy/dist/pypy/interpreter Message-ID: <20050727171255.974AF27B61@code1.codespeak.net> Author: pedronis Date: Wed Jul 27 19:12:32 2005 New Revision: 15201 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: list marshal builtin module Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Jul 27 19:12:32 2005 @@ -141,7 +141,7 @@ return self._builtinmodule_list except AttributeError: builtinmodule_list = [('sys', None), ('__builtin__', None), - ('exceptions', None)] + ('exceptions', None), ('marshal', None)] builtinmodule_list.append(('unicodedata', None)) # Uncomment the following line to enable the builtin _codecs module builtinmodule_list.append(('_codecs', None)) @@ -172,7 +172,7 @@ self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin) for modname, mixedname in self.get_builtinmodule_list(): - if modname not in ('sys', '__builtin__', 'exceptions'): + if modname not in ('sys', '__builtin__', 'exceptions', 'marshal'): self.setbuiltinmodule(modname, mixedname) # initialize with "bootstrap types" from objspace (e.g. w_None) From tismer at codespeak.net Wed Jul 27 21:42:54 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 27 Jul 2005 21:42:54 +0200 (CEST) Subject: [pypy-svn] r15208 - in pypy/dist/pypy: lib module/__builtin__ Message-ID: <20050727194254.BD3FD27B6C@code1.codespeak.net> Author: tismer Date: Wed Jul 27 21:42:52 2005 New Revision: 15208 Modified: pypy/dist/pypy/lib/_marshal.py pypy/dist/pypy/module/__builtin__/importing.py Log: quite some speedup to marshal. marshal is completely decoupled from os level file access, now. Modified: pypy/dist/pypy/lib/_marshal.py ============================================================================== --- pypy/dist/pypy/lib/_marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Wed Jul 27 21:42:52 2005 @@ -4,7 +4,6 @@ """ import types -from _osfilewrapper import OsFileWrapper try: import new @@ -38,21 +37,8 @@ dispatch = {} - def __init__(self, fd): - if fd >= 0: - self.fd_wrapper = OsFileWrapper(fd) - else: - self.fd_wrapper = None - self.buffer = [] - - def _write(self, data): - if self.fd_wrapper is not None: - self.fd_wrapper.write(data) - else: - self.buffer.append(data) - - def getvalue(self): - return ''.join(self.buffer) + def __init__(self, writefunc): + self._write = writefunc def dump(self, x): try: @@ -71,10 +57,14 @@ self.w_long(x>>32) def w_long(self, x): - self._write(chr((x) & 0xff)) - self._write(chr((x>> 8) & 0xff)) - self._write(chr((x>>16) & 0xff)) - self._write(chr((x>>24) & 0xff)) + a = chr(x & 0xff) + x >>= 8 + b = chr(x & 0xff) + x >>= 8 + c = chr(x & 0xff) + x >>= 8 + d = chr(x & 0xff) + self._write(a + b + c + d) def w_short(self, x): self._write(chr((x) & 0xff)) @@ -233,42 +223,29 @@ class _NULL: pass +class _StringBuffer: + def __init__(self, value): + self.bufstr = value + self.bufpos = 0 + + def read(self, n): + ret = self.bufstr[self.bufpos : self.bufpos+n] + self.bufpos += n + if self.bufpos > len(self.bufstr): + raise EOFError, "read past buffer" + return ret + + class _Unmarshaller: dispatch = {} - def __init__(self, fd): - if fd >= 0: - self.fd_wrapper = OsFileWrapper(fd) - else: - self.fd_wrapper = None - self.bufstr = '' - self.bufpos = 0 + def __init__(self, readfunc): + self._read = readfunc self._stringtable = [] - def _read(self): - if self.fd_wrapper is not None: - return self.fd_wrapper.read(1) - else: - ret = self.bufstr[self.bufpos] - self.bufpos += 1 - return ret - - def _readn(self, n): - if self.fd_wrapper is not None: - return self.fd_wrapper.read(n) - else: - ret = self.bufstr[self.bufpos : self.bufpos+n] - self.bufpos += n - if self.bufpos > len(self.bufstr): - raise EOFError, "read past buffer" - return ret - - def setvalue(self, data): - self.bufstr = data - def load(self): - c = self._read() + c = self._read(1) if not c: raise EOFError try: @@ -277,32 +254,33 @@ raise ValueError, "bad marshal code: %c (%d)" % (c, ord(c)) def r_short(self): - lo = ord(self._read()) - hi = ord(self._read()) + lo = ord(self._read(1)) + hi = ord(self._read(1)) x = lo | (hi<<8) if x & 0x8000: x = x - 0x10000 return x def r_long(self): - a = ord(self._read()) - b = ord(self._read()) - c = ord(self._read()) - d = ord(self._read()) + s = self._read(4) + a = ord(s[0]) + b = ord(s[1]) + c = ord(s[2]) + d = ord(s[3]) x = a | (b<<8) | (c<<16) | (d<<24) if d & 0x80 and x > 0: x = -((1L<<32) - x) return int(x) def r_long64(self): - a = ord(self._read()) - b = ord(self._read()) - c = ord(self._read()) - d = ord(self._read()) - e = long(ord(self._read())) - f = long(ord(self._read())) - g = long(ord(self._read())) - h = long(ord(self._read())) + a = ord(self._read(1)) + b = ord(self._read(1)) + c = ord(self._read(1)) + d = ord(self._read(1)) + e = long(ord(self._read(1))) + f = long(ord(self._read(1))) + g = long(ord(self._read(1))) + h = long(ord(self._read(1))) x = a | (b<<8) | (c<<16) | (d<<24) x = x | (e<<32) | (f<<40) | (g<<48) | (h<<56) if h & 0x80 and x > 0: @@ -355,29 +333,29 @@ dispatch[TYPE_LONG] = load_long def load_float(self): - n = ord(self._read()) - s = self._readn(n) + n = ord(self._read(1)) + s = self._read(n) return float(s) dispatch[TYPE_FLOAT] = load_float def load_complex(self): - n = ord(self._read()) - s = self._readn(n) + n = ord(self._read(1)) + s = self._read(n) real = float(s) - n = ord(self._read()) - s = self._readn(n) + n = ord(self._read(1)) + s = self._read(n) imag = float(s) return complex(real, imag) dispatch[TYPE_COMPLEX] = load_complex def load_string(self): n = self.r_long() - return self._readn(n) + return self._read(n) dispatch[TYPE_STRING] = load_string def load_interned(self): n = self.r_long() - ret = intern(self._readn(n)) + ret = intern(self._read(n)) self._stringtable.append(ret) return ret dispatch[TYPE_INTERNED] = load_interned @@ -389,7 +367,7 @@ def load_unicode(self): n = self.r_long() - s = self._readn(n) + s = self._read(n) ret = s.decode('utf8') return ret dispatch[TYPE_UNICODE] = load_unicode @@ -459,17 +437,20 @@ frozenset = set def dump(x, f): - _Marshaller(f.fileno()).dump(x) + m = _Marshaller(f.write) + m.dump(x) def load(f): - return _Unmarshaller(f.fileno()).load() + um = _Unmarshaller(f.read) + return um.load() def dumps(x): - m = _Marshaller(-1) + buffer = [] + m = _Marshaller(buffer.append) m.dump(x) - return m.getvalue() + return ''.join(buffer) def loads(s): - um = _Unmarshaller(-1) - um.setvalue(s) + buffer = _StringBuffer(s) + um = _Unmarshaller(buffer.read) return um.load() Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 21:42:52 2005 @@ -2,11 +2,12 @@ Implementation of the interpreter-level default import logic. """ -import sys, os +import sys, os, stat from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import W_Root, ObjSpace +from pypy.interpreter.eval import Code from pypy.lib._osfilewrapper import OsFileWrapper from pypy.rpython.rarithmetic import intmask @@ -99,7 +100,7 @@ else: assert modtype == PYCFILE filename = filepart + ".pyc" - fd = os.open(filename, os.O_RDONLY, 0777) + fd = os.open(filename, BIN_READMASK, 0777) space.sys.setmodule(w_mod) space.setattr(w_mod, w('__file__'), space.wrap(filename)) @@ -347,6 +348,7 @@ w_pathname = w(pathname) w_code = space.builtin.call('compile', w_source, w_pathname, w_mode) pycode = space.interpclass_w(w_code) + assert isinstance(pycode, Code) # hint to the annotator return pycode def load_source_module(space, w_modulename, w_mod, pathname, osfile): @@ -365,7 +367,7 @@ mtime = os.fstat(osfile.fd)[stat.ST_MTIME] cpathname = pathname + 'c' - #XXXwrite_compiled_module(space, pycode, cpathname, mtime) + write_compiled_module(space, pycode, cpathname, mtime) return w_mod @@ -423,11 +425,12 @@ """ Read a code object from a file and check it for validity """ w_marshal = space.getbuiltinmodule('marshal') - w_U = space.getattr(w_marshal, space.wrap('_Unmarshaller')) - w_unmarshaller = space.call_function(w_U, space.wrap(osfile.fd)) - w_code = space.call_method(w_unmarshaller, 'load') + fd = osfile.fd + size = os.fstat(fd)[stat.ST_SIZE] - os.lseek(fd, 0, 1) + strbuf = osfile.read(size) + w_code = space.call_method(w_marshal, 'loads', space.wrap(strbuf)) pycode = space.interpclass_w(w_code) - if pycode is None: + if pycode is None or not isinstance(pycode, Code): raise OperationError(space.w_ImportError, space.wrap( "Non-code object in %s" % cpathname)) return pycode @@ -437,9 +440,10 @@ Load a module from a compiled file, execute it, and return its module object. """ + w = space.wrap magic = _r_long(osfile) if magic != pyc_magic: - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(space.w_ImportError, w( "Bad magic number in %s" % cpathname)) return NULL; _r_long(osfile) # skip time stamp @@ -447,7 +451,10 @@ #if (Py_VerboseFlag) # PySys_WriteStderr("import %s # precompiled from %s\n", # name, cpathname); - w_dic = space.getattr(w_mod, space.wrap('__dict__')) + w_dic = space.getattr(w_mod, w('__dict__')) + space.call_method(w_dic, 'setdefault', + w('__builtins__'), + w(space.builtin)) code_w.exec_code(space, w_dic, w_dic) return w_mod @@ -459,12 +466,21 @@ Errors are ignored, if a write error occurs an attempt is made to remove the file. """ + # see if marshal exists, already. + # if not, skip the writing. + try: + w_marshal = space.getbuiltinmodule('marshal') + except OperationError: + print "skipped writing of", cpathname + return + else: + print "indeed writing", cpathname fd = os.open(cpathname, BIN_WRITEMASK, 0777) osfile = OsFileWrapper(fd) _w_long(osfile, pyc_magic) _w_long(osfile, mtime) - w_marshal = space.getbuiltinmodule('marshal') - w_M = space.getattr(w_marshal, space.wrap('_Marshaller')) - w_marshaller = space.call_function(w_M, space.wrap(fd)) - w_res = space.call_method(w_marshaller, 'dump', space.wrap(co)) + w_M = space.getattr(w_marshal, space.wrap('dumps')) + w_str = space.call_method(w_marshal, 'dumps', space.wrap(co)) + strbuf = space.str_w(w_str) + osfile.write(strbuf) os.close(fd) From pedronis at codespeak.net Wed Jul 27 21:50:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Jul 2005 21:50:31 +0200 (CEST) Subject: [pypy-svn] r15209 - pypy/dist/pypy/translator Message-ID: <20050727195031.90EDE27B6C@code1.codespeak.net> Author: pedronis Date: Wed Jul 27 21:50:30 2005 New Revision: 15209 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: make geninterp of marshal work on top of 2.3 too Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Jul 27 21:50:30 2005 @@ -77,9 +77,24 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.6' # bump this for substantial changes +GI_VERSION = '1.1.7' # bump this for substantial changes # ____________________________________________________________ +try: + set +except NameError: + class fake_set(object): + pass + class fake_frozenset(object): + pass + builtin_set = fake_set + builtin_frozenset = fake_frozenset + faked_set = True +else: + builtin_set = set + builtin_frozenset = frozenset + faked_set = False + def eval_helper(self, typename, expr): name = self.uniquename("gtype_%s" % typename) unique = self.uniquenameofprebuilt("eval_helper", eval_helper) @@ -791,8 +806,8 @@ "type((lambda:42).__get__(42))"), property: (eval_helper, "property", 'property'), type(Ellipsis): (eval_helper, 'EllipsisType', 'types.EllipsisType'), - set: (eval_helper, "set", "set"), - frozenset: (eval_helper, "frozenset", "frozenset"), + builtin_set: (eval_helper, "set", "set"), + builtin_frozenset: (eval_helper, "frozenset", "frozenset"), buffer: (eval_helper, "buffer", "buffer"), } @@ -1344,16 +1359,27 @@ raise Exception, "cannot find pypy/lib directory" sys.path.insert(0, libdir) try: - exec code in dic + if faked_set: + import __builtin__ + __builtin__.set = fake_set + __builtin__.frozenset = fake_frozenset + try: + exec code in dic + finally: + if libdir in sys.path: + sys.path.remove(libdir) + + entrypoint = dic + t = Translator(None, verbose=False, simplifying=needed_passes, + do_imports_immediately=do_imports_immediately, + builtins_can_raise_exceptions=True) + gen = GenRpy(t, entrypoint, modname, dic) + finally: - if libdir in sys.path: - sys.path.remove(libdir) + if faked_set: + del __builtin__.set + del __builtin__.frozenset - entrypoint = dic - t = Translator(None, verbose=False, simplifying=needed_passes, - do_imports_immediately=do_imports_immediately, - builtins_can_raise_exceptions=True) - gen = GenRpy(t, entrypoint, modname, dic) if tmpname: _file = file else: @@ -1361,7 +1387,16 @@ tmpname = 'nada' out = _file(tmpname, 'w') gen.f = out - gen.gen_source(tmpname, file=_file) + try: + if faked_set: + import __builtin__ + __builtin__.set = fake_set + __builtin__.frozenset = fake_frozenset + gen.gen_source(tmpname, file=_file) + finally: + if faked_set: + del __builtin__.set + del __builtin__.frozenset out.close() newsrc = _file(tmpname).read() code = py.code.Source(newsrc).compile() From ericvrp at codespeak.net Wed Jul 27 22:00:47 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 27 Jul 2005 22:00:47 +0200 (CEST) Subject: [pypy-svn] r15211 - in pypy/dist/pypy/translator/llvm2: . module test Message-ID: <20050727200047.2609027B60@code1.codespeak.net> Author: ericvrp Date: Wed Jul 27 22:00:45 2005 New Revision: 15211 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/module/extfunction.py pypy/dist/pypy/translator/llvm2/opaquenode.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: - made llvm output more verbose, it is so hard to read already - refactored build_llvm_module a little - funcnode.py phi node blocknames modified when coming from an invoke (because I needed to add a block when an exception occured) All in all exceptions are getting real close (or so it seems) Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Wed Jul 27 22:00:45 2005 @@ -22,7 +22,7 @@ # constructor_decl is used to declare the constructor # for the array type (see writeimpl) c = nextnum() - self.ref = "%%array.%s.%s" % (c, self.arraytype) + self.ref = "%%arraytype.%s.%s" % (c, self.arraytype) self.constructor_ref = "%%new.array.%s" % c self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -101,7 +101,18 @@ typeval, ", ".join(arrayvalues)) - return "%s {%s}" % (self.get_typerepr(), value) + s = "%s {%s}" % (self.get_typerepr(), value) + #XXX this does not work for arrays inlined in struct. How else to do this? + #if typeval == 'sbyte': #give more feedback for strings + # limited_printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-.' + # s += ' ;"' + # for item in items: + # if item in limited_printable: + # s += item + # else: + # s += '_' + # s += '" ' + return s # ______________________________________________________________________ # entry points from genllvm Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Wed Jul 27 22:00:45 2005 @@ -18,6 +18,7 @@ pass OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline" +EXCEPTIONS_SWITCHES = "-enable-correct-eh-support" def compile_module(module, source_files, object_files, library_files): open("%s_setup.py" % module, "w").write(str(py.code.Source( @@ -52,10 +53,10 @@ if optimize: cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), - "llc -enable-correct-eh-support %s_optimized.bc -f -o %s.s" % (b, b)] + "llc %s %s_optimized.bc -f -o %s.s" % (EXCEPTIONS_SWITCHES, b, b)] else: cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), - "llc -enable-correct-eh-support %s.bc -f -o %s.s" % (b, b)] + "llc %s %s.bc -f -o %s.s" % (EXCEPTIONS_SWITCHES, b, b)] cmds.append("as %s.s -o %s.o" % (b, b)) object_files.append("%s.o" % b) else: #assume 64 bit platform (x86-64?) @@ -63,10 +64,10 @@ if optimize: cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), "opt %s -f %s.bc -o %s_optimized.bc" % (OPTIMIZATION_SWITCHES, b, b), - "llc -enable-correct-eh-support %s_optimized.bc -march=c -f -o %s.c" % (b, b)] + "llc %s %s_optimized.bc -march=c -f -o %s.c" % (EXCEPTIONS_SWITCHES, b, b)] else: cmds = ["llvm-as %s.ll -f -o %s.bc" % (b, b), - "llc -enable-correct-eh-support %s.bc -march=c -f -o %s.c" % (b, b)] + "llc %s %s.bc -march=c -f -o %s.c" % (EXCEPTIONS_SWITCHES, b, b)] source_files.append("%s.c" % b) try: Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Wed Jul 27 22:00:45 2005 @@ -16,7 +16,7 @@ self._lines.append(line) log(line) - def comment(self, line, indent=False): + def comment(self, line, indent=True): line = ";; " + line if indent: self.indent(line) @@ -30,6 +30,7 @@ self.append(" " + line) def label(self, name): + self.newline() self.append(" %s:" % name) def globalinstance(self, name, typeandata): @@ -49,18 +50,26 @@ self.append("declare %s" %(decl,)) def startimpl(self): - self.append("") + self.newline() self.append("implementation") - self.append("") + self.newline() def br_uncond(self, blockname): self.indent("br label %%%s" %(blockname,)) - def br(self, switch, blockname_false, blockname_true): + def br(self, cond, blockname_false, blockname_true): self.indent("br bool %s, label %%%s, label %%%s" - % (switch, blockname_true, blockname_false)) + % (cond, blockname_true, blockname_false)) + + def switch(self, intty, cond, defaultdest, value_label): + labels = '' + for value, label in value_label: + labels += ' %s %s, label %%%s' % (intty, value, label) + self.indent("switch %s %s, label %%%s [%s ]" + % (intty, cond, defaultdest, labels)) def openfunc(self, decl): + self.newline() self.append("%s {" % (decl,)) def closefunc(self): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Wed Jul 27 22:00:45 2005 @@ -17,7 +17,7 @@ self.type_ = type_ # XXX Make simplier for now, it is far too hard to read otherwise #self.ref = 'ft.%s.%s' % (type_, nextnum()) - self.ref = '%%ft.%s' % (nextnum(),) + self.ref = '%%functiontype.%s' % (nextnum(),) def __str__(self): return "" % self.ref @@ -114,6 +114,10 @@ names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] + for i, link in enumerate(entrylinks): + if link.prevblock.exitswitch == Constant(last_exception) and \ + link.prevblock.exits[0].target != block: + blocknames[i] += '_exception' if type_ != "void": codewriter.phi(arg, type_, names, blocknames) @@ -137,7 +141,7 @@ opwriter = OpWriter(self.db, codewriter, self, block) last_direct_call_index = self._last_operation(block, 'direct_call') for op_index, op in enumerate(block.operations): - codewriter.comment(str(op), indent=True) + codewriter.comment(str(op)) if op_index == last_direct_call_index and block.exitswitch == Constant(last_exception): op.opname = 'direct_invoke' opwriter.write_operation(op) @@ -189,4 +193,5 @@ # Which is already stored in the global variables. # So nothing needs to happen here! + codewriter.comment('reraise last exception') codewriter.unwind() Modified: pypy/dist/pypy/translator/llvm2/module/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/module/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/module/extfunction.py Wed Jul 27 22:00:45 2005 @@ -12,7 +12,7 @@ declare int %read(int, sbyte*, int) declare sbyte* %strncpy(sbyte*, sbyte*, int) -%st.rpy_string.0 = type {int, {int, [0 x sbyte]}} +%structtype.rpy_string = type {int, {int, [0 x sbyte]}} %last_exception_type = global long 0 %last_exception_value = global long 0 @@ -50,14 +50,14 @@ extfunctions = {} #dependencies, llvm-code extfunctions["%cast"] = ((), """ -sbyte* %cast(%st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 +sbyte* %cast(%structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr %length = add int %reallength, 1 %ulength = cast int %length to uint %dest = call sbyte* %gc_malloc_atomic(uint %ulength) - %source1ptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 + %source1ptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 %source1 = cast [0 x sbyte]* %source1ptr to sbyte* %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) @@ -117,8 +117,8 @@ """) extfunctions["%ll_os_open"] = (("%cast",), """ -int %ll_os_open(%st.rpy_string.0* %structstring, int %flag, int %mode) { - %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) +int %ll_os_open(%structtype.rpy_string* %structstring, int %flag, int %mode) { + %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) %fd = call int %open(sbyte* %dest, int %flag, int %mode) ret int %fd } @@ -126,10 +126,10 @@ """) extfunctions["%ll_os_write"] = (("%cast",), """ -int %ll_os_write(int %fd, %st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 +int %ll_os_write(int %fd, %structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr - %dest = call sbyte* %cast(%st.rpy_string.0* %structstring) + %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) ret int %byteswritten } @@ -137,11 +137,11 @@ """) extfunctions["%ll_read_into"] = ((), """ -int %ll_read_into(int %fd, %st.rpy_string.0* %structstring) { - %reallengthptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 0 +int %ll_read_into(int %fd, %structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 %reallength = load int* %reallengthptr - %destptr = getelementptr %st.rpy_string.0* %structstring, int 0, uint 1, uint 1 + %destptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 %dest = cast [0 x sbyte]* %destptr to sbyte* %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength) Modified: pypy/dist/pypy/translator/llvm2/opaquenode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opaquenode.py (original) +++ pypy/dist/pypy/translator/llvm2/opaquenode.py Wed Jul 27 22:00:45 2005 @@ -7,7 +7,7 @@ assert isinstance(opaquetype, lltype.OpaqueType) self.db = db self.opaquetype = opaquetype - self.ref = "%%opaque.%s" % (opaquetype.tag) + self.ref = "%%opaquetype.%s" % (opaquetype.tag) def __str__(self): return "" %(self.ref,) Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Wed Jul 27 22:00:45 2005 @@ -3,7 +3,6 @@ from pypy.rpython import lltype from pypy.translator.llvm2.atomic import is_atomic from pypy.translator.llvm2.log import log -nextexclabel = py.std.itertools.count().next log = log.opwriter class OpWriter(object): @@ -181,33 +180,54 @@ def direct_invoke(self, op): assert len(op.args) >= 1 + assert len(self.block.exits) >= 2 #at least one label and one exception label + + link = self.block.exits[0] + assert link.exitcase is None + targetvar = self.db.repr_arg(op.result) returntype = self.db.repr_arg_type(op.result) functionref = self.db.repr_arg(op.args[0]) argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - link = self.block.exits[0] - assert link.exitcase is None - label = self.node.block_to_name[link.target] - - assert len(self.block.exits) > 1 - link = self.block.exits[1] #XXX need an additional block if we catch multiple exc.types! - exc_label = self.node.block_to_name[link.target] - - if len(self.block.exits) > 2: - msg = 'XXX Exception handling incomplete implementation warning: n_exits=%d' % (len(self.block.exits),) - print msg - self.codewriter.comment(msg, indent=True) - #exc_label = 'exception_block.%d' % nextexclabel() + none_label = self.node.block_to_name[link.target] + exc_label = self.node.block_to_name[self.block] + '_exception' + exc_error_label = exc_label + '_error' if returntype != "void": self.codewriter.invoke(targetvar, returntype, functionref, argrefs, - argtypes, label, exc_label) + argtypes, none_label, exc_label) else: - self.codewriter.invoke_void(functionref, argrefs, argtypes, label, exc_label) + self.codewriter.invoke_void(functionref, argrefs, argtypes, none_label, exc_label) - #self.codewriter.label(exc_label) + self.codewriter.label(exc_label) + value_label = [] + value = 0 + for link in self.block.exits[1:]: + assert issubclass(link.exitcase, Exception) + + target = self.node.block_to_name[link.target] + value_label.append( (value,target) ) + value += 1 + + #msg = 'XXX Exception target=%s, exitcase=%s, last_exception.concretetype=%s' % \ + # (str(target), str(link.exitcase), link.last_exception.concretetype) + #self.codewriter.comment(msg) + #self.codewriter.comment('TODO: in %s rename %s to %s' % (target, self.node.block_to_name[self.block], exc_label)) + + tmptype1, tmpvar1 = 'long' , self.db.repr_tmpvar() + self.codewriter.load(tmpvar1, tmptype1, '%last_exception_type') + + #tmptype2, tmpvar2 = '%structtype.object_vtable*', self.db.repr_tmpvar() + #self.codewriter.cast(tmpvar2, tmptype1, tmpvar1, tmptype2) + #self.codewriter.switch(tmptype2, tmpvar2, exc_error_label, value_label) + + self.codewriter.switch(tmptype1, tmpvar1, exc_error_label, value_label) + self.codewriter.label(exc_error_label) + self.codewriter.comment('dead code ahead') + self.codewriter.ret('int', '0') + #self.codewriter.unwind() #this causes llvm to crash?!? def malloc(self, op): targetvar = self.db.repr_arg(op.result) @@ -244,9 +264,8 @@ ("uint", index)) self.codewriter.load(targetvar, targettype, tmpvar) else: - self.codewriter.comment("***Skipping operation getfield()***", - indent=True) - + self.codewriter.comment("***Skipping operation getfield()***") + def getsubstruct(self, op): struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Wed Jul 27 22:00:45 2005 @@ -17,7 +17,7 @@ self.db = db self.struct = struct self.name = "%s.%s" % (self.struct._name , nextnum()) - self.ref = "%%st.%s" % (self.name) + self.ref = "%%structtype.%s" % (self.name) def __str__(self): return "" %(self.ref,) @@ -42,7 +42,7 @@ def __init__(self, db, struct): super(StructVarsizeTypeNode, self).__init__(db, struct) - self.constructor_ref = "%%new.st.var.%s" % (self.name) + self.constructor_ref = "%%newvarsizestruct.%s" % (self.name) self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -89,7 +89,7 @@ self.db = db self.value = value self.structtype = self.value._TYPE - self.ref = "%%stinstance.%s" % (nextnum(),) + self.ref = "%%structinstance.%s" % (nextnum(),) def __str__(self): return "" % (self.ref,) Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Wed Jul 27 22:00:45 2005 @@ -24,15 +24,18 @@ f = compile_function(llvmsnippet.class_simple2, [int]) assert f(2) == 10 - def SEGFAULTtest_method_of_base_class(self): + def test_method_of_base_class(self): + py.test.skip("not working yet (segfault)") f = compile_function(llvmsnippet.method_of_base_class, []) assert f() == 14 - def SEGFAULTtest_attribute_from_base_class(self): + def test_attribute_from_base_class(self): + py.test.skip("not working yet (segfault)") f = compile_function(llvmsnippet.attribute_from_base_class, []) assert f() == 4 - def SEGFAULTtest_direct_call_of_virtual_method(self): + def test_direct_call_of_virtual_method(self): + py.test.skip("not working yet (segfault)") f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) assert f() == 14 Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Wed Jul 27 22:00:45 2005 @@ -11,6 +11,7 @@ self.n = n def test_simple1(): + py.test.skip("not working yet") def raise_(i): if i: raise TestException() @@ -42,6 +43,33 @@ assert f( 0) == fn( 0) assert f(10) == fn(10) +def test_simple3(): + py.test.skip("not working yet") + 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) From arigo at codespeak.net Wed Jul 27 22:10:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 22:10:08 +0200 (CEST) Subject: [pypy-svn] r15212 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727201008.AC63627B60@code1.codespeak.net> Author: arigo Date: Wed Jul 27 22:10:06 2005 New Revision: 15212 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: Don't write pyc files that have the executable bit set :-) Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Wed Jul 27 22:10:06 2005 @@ -96,11 +96,11 @@ e = None if modtype == PYFILE: filename = filepart + ".py" - fd = os.open(filename, os.O_RDONLY, 0777) + fd = os.open(filename, os.O_RDONLY, 0666) else: assert modtype == PYCFILE filename = filepart + ".pyc" - fd = os.open(filename, BIN_READMASK, 0777) + fd = os.open(filename, BIN_READMASK, 0666) space.sys.setmodule(w_mod) space.setattr(w_mod, w('__file__'), space.wrap(filename)) @@ -403,7 +403,7 @@ the header; if not, return NULL. Doesn't set an exception. """ - fd = os.open(cpathname, BIN_READMASK, 0777) # using no defaults + fd = os.open(cpathname, BIN_READMASK, 0666) # using no defaults osfile = OsFileWrapper(fd) magic = _r_long(osfile) try: @@ -445,7 +445,6 @@ if magic != pyc_magic: raise OperationError(space.w_ImportError, w( "Bad magic number in %s" % cpathname)) - return NULL; _r_long(osfile) # skip time stamp code_w = read_compiled_module(space, cpathname, osfile) #if (Py_VerboseFlag) @@ -475,7 +474,7 @@ return else: print "indeed writing", cpathname - fd = os.open(cpathname, BIN_WRITEMASK, 0777) + fd = os.open(cpathname, BIN_WRITEMASK, 0666) osfile = OsFileWrapper(fd) _w_long(osfile, pyc_magic) _w_long(osfile, mtime) From nik at codespeak.net Wed Jul 27 22:21:19 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Wed, 27 Jul 2005 22:21:19 +0200 (CEST) Subject: [pypy-svn] r15213 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050727202119.C02F127B60@code1.codespeak.net> Author: nik Date: Wed Jul 27 22:21:18 2005 New Revision: 15213 Added: pypy/dist/pypy/module/__builtin__/test/test_buffer.py Modified: pypy/dist/pypy/module/__builtin__/app_buffer.py Log: added unicode support to buffer type (in conformance with CPython 2.4.1). still missing: array support for buffer. Modified: pypy/dist/pypy/module/__builtin__/app_buffer.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/app_buffer.py (original) +++ pypy/dist/pypy/module/__builtin__/app_buffer.py Wed Jul 27 22:21:18 2005 @@ -1,4 +1,6 @@ # Might probably be deprecated in Python at some point. +import sys +from struct import pack, unpack class buffer(object): """buffer(object [, offset[, size]]) @@ -12,6 +14,15 @@ def __init__(self, object, offset=0, size=None): if isinstance(object, str): pass + elif isinstance(object, unicode): + str_object = "" + if sys.maxunicode == 65535: + pack_code = "H" + else: + pack_code = "I" + for char in object: + str_object += pack(pack_code, ord(char)) + object = str_object elif isinstance(object, buffer): object = object.buf else: Added: pypy/dist/pypy/module/__builtin__/test/test_buffer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/__builtin__/test/test_buffer.py Wed Jul 27 22:21:18 2005 @@ -0,0 +1,21 @@ +"""Tests some behaviour of the buffer type that is not tested in +lib-python/2.4.1/test/test_types.py where the stdlib buffer tests live.""" +import autopath + +class AppTestBuffer: + + def test_unicode_buffer(self): + import sys + b = buffer(u"ab") + if sys.maxunicode == 65535: # UCS2 build + assert len(b) == 4 + if sys.byteorder == "big": + assert b[0:4] == "\x00a\x00b" + else: + assert b[0:4] == "a\x00b\x00" + else: # UCS4 build + assert len(b) == 8 + if sys.byteorder == "big": + assert b[0:8] == "\x00\x00\x00a\x00\x00\x00b" + else: + assert b[0:8] == "a\x00\x00\x00b\x00\x00\x00" From arigo at codespeak.net Wed Jul 27 22:34:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Jul 2005 22:34:26 +0200 (CEST) Subject: [pypy-svn] r15214 - pypy/dist/pypy/lib Message-ID: <20050727203426.8528027B60@code1.codespeak.net> Author: arigo Date: Wed Jul 27 22:34:24 2005 New Revision: 15214 Modified: pypy/dist/pypy/lib/_marshal.py Log: Performance hacks. Modified: pypy/dist/pypy/lib/_marshal.py ============================================================================== --- pypy/dist/pypy/lib/_marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Wed Jul 27 22:34:24 2005 @@ -229,10 +229,10 @@ self.bufpos = 0 def read(self, n): - ret = self.bufstr[self.bufpos : self.bufpos+n] - self.bufpos += n - if self.bufpos > len(self.bufstr): - raise EOFError, "read past buffer" + start = self.bufpos + end = start + n + ret = self.bufstr[start:end] + self.bufpos = end return ret @@ -311,13 +311,9 @@ return Ellipsis dispatch[TYPE_ELLIPSIS] = load_ellipsis - def load_int(self): - return self.r_long() - dispatch[TYPE_INT] = load_int - - def load_int64(self): - return self.r_long64() - dispatch[TYPE_INT64] = load_int64 + dispatch[TYPE_INT] = r_long + + dispatch[TYPE_INT64] = r_long64 def load_long(self): size = self.r_long() @@ -378,9 +374,7 @@ def load_list(self): n = self.r_long() - list = [] - for i in range(n): - list.append(self.load()) + list = [self.load() for i in range(n)] return list dispatch[TYPE_LIST] = load_list From hpk at codespeak.net Thu Jul 28 00:59:04 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 00:59:04 +0200 (CEST) Subject: [pypy-svn] r15215 - pypy/dist/pypy/documentation Message-ID: <20050727225904.2E48827B5E@code1.codespeak.net> Author: hpk Date: Thu Jul 28 00:59:03 2005 New Revision: 15215 Modified: pypy/dist/pypy/documentation/translation.txt Log: issue100 resolved fixed 'explicitely' to 'explicitly' according to Brett's comment Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Thu Jul 28 00:59:03 2005 @@ -126,7 +126,7 @@ The annotator itself (``pypy.translator.annrpython``) works by propagating the annotations forward in the flow graphs, starting at some -entry point function, possibly with explicitely provided annotations +entry point function, possibly with explicitly provided annotations about the entry point's input arguments. It considers each operation in the flow graph in turn. Each operation takes a few input arguments (Variables and Constants) and produce a single result (a Variable). @@ -623,8 +623,8 @@ a very limited, easily controllable set of types, and define implementations of types like list in this elementary world. The ``malloc()`` function is a kind of placeholder, which must eventually be provided by the code generator for the -target platform; but as we have just seen its Python implementation in ` -rpython/lltype.py`_ works too, which is primarily useful for testing, +target platform; but as we have just seen its Python implementation in +`rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc. The argument to ``malloc()`` is the structure type directly, but it returns a @@ -634,7 +634,7 @@ For the purpose of creating structures with pointers to other structures, we can -declare pointer types explicitely:: +declare pointer types explicitly:: >>> typeOf(p) == Ptr(POINT) True @@ -722,7 +722,7 @@ (non-GC non-varsize) structures. GcArrays can be malloc()ed. The length must be specified when malloc() is -called, and arrays cannot be resized; this length is stored explicitely in a +called, and arrays cannot be resized; this length is stored explicitly in a header. The non-GC version of Array can be used as the last field of a structure, to From rxe at codespeak.net Thu Jul 28 01:41:31 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 01:41:31 +0200 (CEST) Subject: [pypy-svn] r15216 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050727234131.CCACD27B5E@code1.codespeak.net> Author: rxe Date: Thu Jul 28 01:41:30 2005 New Revision: 15216 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: pedronis/rxe Reluctant checkin of serious hacks to make tests work again. Reason: we would need codecs to read codecs.pyc because of the unicode constants in it Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 01:41:30 2005 @@ -30,7 +30,7 @@ import stat -def info_modtype(filepart): +def info_modtype(space ,filepart): """ calculate whether the .py file exists, the .pyc file exists and whether the .pyc file has the correct mtime entry. @@ -49,7 +49,7 @@ pycfile = filepart + ".pyc" if os.path.exists(pycfile): - pyc_state = check_compiled_module(pyfile, pyfile_ts, pycfile) + pyc_state = check_compiled_module(space, pyfile, pyfile_ts, pycfile) pycfile_exists = pyc_state >= 0 pycfile_ts_valid = pyc_state > 0 and pyfile_exist else: @@ -58,10 +58,10 @@ return pyfile_exist, pycfile_exists, pycfile_ts_valid -def find_modtype(filepart): +def find_modtype(space, filepart): """ This is the way pypy does it. A pyc is only used if the py file exists AND the pyc file contains the timestamp of the py. """ - pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(filepart) + pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(space, filepart) if pycfile_ts_valid: return PYCFILE elif pyfile_exist: @@ -69,10 +69,10 @@ else: return NOFILE -def find_modtype_cpython(filepart): +def find_modtype_cpython(space, filepart): """ This is the way cpython does it (where the py file doesnt exist but there is a valid pyc file. """ - pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(filepart) + pyfile_exist, pycfile_exists, pycfile_ts_valid = info_modtype(space, filepart) if pycfile_ts_valid: return PYCFILE elif pyfile_exist: @@ -85,7 +85,7 @@ def try_import_mod(space, w_modulename, filepart, w_parent, w_name, pkgdir=None): # decide what type we want (pyc/py) - modtype = find_modtype(filepart) + modtype = find_modtype(space, filepart) if modtype == NOFILE: return None @@ -394,7 +394,7 @@ d = x & 0xff osfile.write(chr(a) + chr(b) + chr(c) + chr(d)) -def check_compiled_module(pathname, mtime, cpathname): +def check_compiled_module(space, pathname, mtime, cpathname): """ Given a pathname for a Python source file, its time of last modification, and a pathname for a compiled file, check whether the @@ -403,6 +403,15 @@ the header; if not, return NULL. Doesn't set an exception. """ + #XXX Umph, we would need codecs to read codecs.pyc + # because of the unicode constants in it + if cpathname[-10:] == "codecs.pyc": + return -1 + try: + w_marshal = space.getbuiltinmodule('marshal') + except OperationError: + print "skipped checking of", cpathname + return -1 fd = os.open(cpathname, BIN_READMASK, 0666) # using no defaults osfile = OsFileWrapper(fd) magic = _r_long(osfile) @@ -423,7 +432,7 @@ def read_compiled_module(space, cpathname, osfile): """ Read a code object from a file and check it for validity """ - + w_marshal = space.getbuiltinmodule('marshal') fd = osfile.fd size = os.fstat(fd)[stat.ST_SIZE] - os.lseek(fd, 0, 1) From tismer at codespeak.net Thu Jul 28 01:48:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 01:48:26 +0200 (CEST) Subject: [pypy-svn] r15217 - in pypy/dist/pypy: lib module/__builtin__ module/__builtin__/test/impsubdir/compiled translator Message-ID: <20050727234826.1308027B5E@code1.codespeak.net> Author: tismer Date: Thu Jul 28 01:48:22 2005 New Revision: 15217 Modified: pypy/dist/pypy/lib/_marshal.py pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.pyc pypy/dist/pypy/translator/geninterplevel.py Log: optimized the snot out of _marshal.py timing on my machine for "import os" is now: writing all the .pyc files: 75 sec loading all the .pyc files: 105 sec Every other optimization is considered insane I guess. We really should writemore interplevel Modified: pypy/dist/pypy/lib/_marshal.py ============================================================================== --- pypy/dist/pypy/lib/_marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Thu Jul 28 01:48:22 2005 @@ -229,10 +229,10 @@ self.bufpos = 0 def read(self, n): - start = self.bufpos - end = start + n - ret = self.bufstr[start:end] - self.bufpos = end + pos = self.bufpos + newpos = pos + n + ret = self.bufstr[pos : newpos] + self.bufpos = newpos return ret @@ -270,7 +270,9 @@ x = a | (b<<8) | (c<<16) | (d<<24) if d & 0x80 and x > 0: x = -((1L<<32) - x) - return int(x) + return int(x) + else: + return x def r_long64(self): a = ord(self._read(1)) @@ -423,6 +425,226 @@ return frozenset(args) dispatch[TYPE_FROZENSET] = load_frozenset +# ________________________________________________________________ + +def _read(self, n): + pos = self.bufpos + newpos = pos + n + ret = self.bufstr[pos : newpos] + self.bufpos = newpos + return ret + +def _read1(self): + ret = self.bufstr[self.bufpos] + self.bufpos += 1 + return ret + +def _r_short(self): + lo = ord(_read1(self)) + hi = ord(_read1(self)) + x = lo | (hi<<8) + if x & 0x8000: + x = x - 0x10000 + return x + +def _r_long(self): + # inlined this most common case + p = self.bufpos + s = self.bufstr + a = ord(s[p]) + b = ord(s[p+1]) + c = ord(s[p+2]) + d = ord(s[p+3]) + self.bufpos += 4 + x = a | (b<<8) | (c<<16) | (d<<24) + if d & 0x80 and x > 0: + x = -((1L<<32) - x) + return int(x) + else: + return x + +def _r_long64(self): + a = ord(_read1(self)) + b = ord(_read1(self)) + c = ord(_read1(self)) + d = ord(_read1(self)) + e = long(ord(_read1(self))) + f = long(ord(_read1(self))) + g = long(ord(_read1(self))) + h = long(ord(_read1(self))) + x = a | (b<<8) | (c<<16) | (d<<24) + x = x | (e<<32) | (f<<40) | (g<<48) | (h<<56) + if h & 0x80 and x > 0: + x = -((1L<<64) - x) + return x + +_load_dispatch = {} + +class _FastUnmarshaller: + + dispatch = {} + + def __init__(self, buffer): + self.bufstr = buffer + self.bufpos = 0 + self._stringtable = [] + + def load(self): + # make flow space happy + c = '?' + try: + c = self.bufstr[self.bufpos] + self.bufpos += 1 + return _load_dispatch[c](self) + except KeyError: + raise ValueError, "bad marshal code: %c (%d)" % (c, ord(c)) + except IndexError: + raise EOFError + + def load_null(self): + return _NULL + dispatch[TYPE_NULL] = load_null + + def load_none(self): + return None + dispatch[TYPE_NONE] = load_none + + def load_true(self): + return True + dispatch[TYPE_TRUE] = load_true + + def load_false(self): + return False + dispatch[TYPE_FALSE] = load_false + + def load_stopiter(self): + return StopIteration + dispatch[TYPE_STOPITER] = load_stopiter + + def load_ellipsis(self): + return Ellipsis + dispatch[TYPE_ELLIPSIS] = load_ellipsis + + def load_int(self): + return _r_long(self) + dispatch[TYPE_INT] = load_int + + def load_int64(self): + return _r_long64(self) + dispatch[TYPE_INT64] = load_int64 + + def load_long(self): + size = _r_long(self) + sign = 1 + if size < 0: + sign = -1 + size = -size + x = 0L + for i in range(size): + d = _r_short(self) + x = x | (d<<(i*15L)) + return x * sign + dispatch[TYPE_LONG] = load_long + + def load_float(self): + n = ord(_read1(self)) + s = _read(self, n) + return float(s) + dispatch[TYPE_FLOAT] = load_float + + def load_complex(self): + n = ord(_read1(self)) + s = _read(self, n) + real = float(s) + n = ord(_read1(self)) + s = _read(self, n) + imag = float(s) + return complex(real, imag) + dispatch[TYPE_COMPLEX] = load_complex + + def load_string(self): + n = _r_long(self) + return _read(self, n) + dispatch[TYPE_STRING] = load_string + + def load_interned(self): + n = _r_long(self) + ret = intern(_read(self, n)) + self._stringtable.append(ret) + return ret + dispatch[TYPE_INTERNED] = load_interned + + def load_stringref(self): + n = _r_long(self) + return self._stringtable[n] + dispatch[TYPE_STRINGREF] = load_stringref + + def load_unicode(self): + n = _r_long(self) + s = _read(self, n) + ret = s.decode('utf8') + return ret + dispatch[TYPE_UNICODE] = load_unicode + + def load_tuple(self): + return tuple(self.load_list()) + dispatch[TYPE_TUPLE] = load_tuple + + def load_list(self): + n = _r_long(self) + list = [] + for i in range(n): + list.append(self.load()) + return list + dispatch[TYPE_LIST] = load_list + + def load_dict(self): + d = {} + while 1: + key = self.load() + if key is _NULL: + break + value = self.load() + d[key] = value + return d + dispatch[TYPE_DICT] = load_dict + + def load_code(self): + argcount = _r_long(self) + nlocals = _r_long(self) + stacksize = _r_long(self) + flags = _r_long(self) + code = self.load() + consts = self.load() + names = self.load() + varnames = self.load() + freevars = self.load() + cellvars = self.load() + filename = self.load() + name = self.load() + firstlineno = _r_long(self) + lnotab = self.load() + if not new: + raise RuntimeError, "can't unmarshal code objects; no 'new' module" + return new.code(argcount, nlocals, stacksize, flags, code, consts, + names, varnames, filename, name, firstlineno, lnotab, + freevars, cellvars) + dispatch[TYPE_CODE] = load_code + + def load_set(self): + n = _r_long(self) + args = [self.load() for i in range(n)] + return set(args) + dispatch[TYPE_SET] = load_set + + def load_frozenset(self): + n = _r_long(self) + args = [self.load() for i in range(n)] + return frozenset(args) + dispatch[TYPE_FROZENSET] = load_frozenset + +_load_dispatch = _FastUnmarshaller.dispatch + try: set except NameError: @@ -445,6 +667,5 @@ return ''.join(buffer) def loads(s): - buffer = _StringBuffer(s) - um = _Unmarshaller(buffer.read) + um = _FastUnmarshaller(s) return um.load() Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 01:48:22 2005 @@ -455,6 +455,7 @@ raise OperationError(space.w_ImportError, w( "Bad magic number in %s" % cpathname)) _r_long(osfile) # skip time stamp + print "loading pyc file:", cpathname code_w = read_compiled_module(space, cpathname, osfile) #if (Py_VerboseFlag) # PySys_WriteStderr("import %s # precompiled from %s\n", Modified: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.pyc ============================================================================== Binary files. No diff available. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Thu Jul 28 01:48:22 2005 @@ -365,6 +365,9 @@ # shortcutting references to __builtin__ if id(obj) in self.builtin_ids: func = self.builtin_ids[id(obj)] + #name = self.get_nameof_builtin_func(func) + # the above is quicker in principle, but pulls more + # stuff in, so it is slower right now. name = "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__) else: for cls in type(obj).__mro__: @@ -386,6 +389,27 @@ self.rpynames[key] = name return name + def get_nameof_builtin_func(self, func): + # this is a hack! + # in some cases, like exceptions, we don't have space.builtin available, + #so we crate a fall-back... + name = self.uniquename('gbltin_' + func.__name__) + self.initcode.append1('''\ +try: + # see if we have space.builtin in this context + space.builtin +except AttributeError: + print "didn't get", %(bltin)r + def %(name)s(space, __args__): + w_func = space.builtin.get(%(bltin)r) + return space.call_args(w_func, __args__) + %(name)s = space.wrap(gateway.interp2app(%(name)s, unwrap_spec=[gateway.ObjSpace, gateway.Arguments])) +else: + print "got it:", %(bltin)r + %(name)s = space.builtin.get(%(bltin)r)''' + % {'name': name, 'bltin': func.__name__} ) + return name + def uniquename(self, basename): name = self.namespace.uniquename(basename) self.globalobjects.append(name) From rxe at codespeak.net Thu Jul 28 02:04:04 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 02:04:04 +0200 (CEST) Subject: [pypy-svn] r15218 - in pypy/dist/pypy/module/__builtin__: . test Message-ID: <20050728000404.0565927B5E@code1.codespeak.net> Author: rxe Date: Thu Jul 28 02:04:02 2005 New Revision: 15218 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Fix tests and hide spurious prints for now. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 02:04:02 2005 @@ -410,7 +410,8 @@ try: w_marshal = space.getbuiltinmodule('marshal') except OperationError: - print "skipped checking of", cpathname + #XXX debug + #print "skipped checking of", cpathname return -1 fd = os.open(cpathname, BIN_READMASK, 0666) # using no defaults osfile = OsFileWrapper(fd) @@ -480,10 +481,13 @@ try: w_marshal = space.getbuiltinmodule('marshal') except OperationError: - print "skipped writing of", cpathname + # XXX debug + #print "skipped writing of", cpathname return else: - print "indeed writing", cpathname + pass + #XXX debug + #print "indeed writing", cpathname fd = os.open(cpathname, BIN_WRITEMASK, 0666) osfile = OsFileWrapper(fd) _w_long(osfile, pyc_magic) Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Thu Jul 28 02:04:02 2005 @@ -196,20 +196,30 @@ # ___________________ .pyc related stuff _________________ def test_check_compiled_module(self): + space = self.space pathname = "whatever" mtime = 12345 cpathname = _testfile(importing.pyc_magic, mtime) - ret = importing.check_compiled_module(pathname, mtime, cpathname) + ret = importing.check_compiled_module(space, + pathname, + mtime, + cpathname) assert ret == 1 # check for wrong mtime - ret = importing.check_compiled_module(pathname, mtime+1, cpathname) + ret = importing.check_compiled_module(space, + pathname, + mtime+1, + cpathname) assert ret == 0 os.remove(cpathname) # check for wrong version cpathname = _testfile(importing.pyc_magic+1, mtime) - ret = importing.check_compiled_module(pathname, mtime, cpathname) + ret = importing.check_compiled_module(space, + pathname, + mtime, + cpathname) assert ret == -1 os.remove(cpathname) @@ -323,7 +333,10 @@ # check pathname = str(udir.join('cpathname.py')) - ret = importing.check_compiled_module(pathname, mtime, cpathname) + ret = importing.check_compiled_module(space, + pathname, + mtime, + cpathname) assert ret == 1 # read compile module From tismer at codespeak.net Thu Jul 28 10:52:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 10:52:16 +0200 (CEST) Subject: [pypy-svn] r15224 - pypy/dist/pypy/translator Message-ID: <20050728085216.03DD227B68@code1.codespeak.net> Author: tismer Date: Thu Jul 28 10:52:15 2005 New Revision: 15224 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: tried to speed up marshal by globally loading builtin functions. The effect was slightly negative, probably because some more functions get pulled early, even if they arenot needed. kept the code, but disabled it. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Thu Jul 28 10:52:15 2005 @@ -634,7 +634,11 @@ base_class = None base = cls def initinstance(): - content = instance.__dict__.items() + try: + content = instance.__dict__.items() + except AttributeError: + import pdb + pdb.set_trace() ##!! content.sort() for key, value in content: if self.should_translate_attr(instance, key): From ale at codespeak.net Thu Jul 28 10:56:19 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 28 Jul 2005 10:56:19 +0200 (CEST) Subject: [pypy-svn] r15225 - in pypy/dist/pypy: module/math rpython rpython/module Message-ID: <20050728085619.7FF8827B6C@code1.codespeak.net> Author: ale Date: Thu Jul 28 10:56:16 2005 New Revision: 15225 Modified: pypy/dist/pypy/module/math/__init__.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/module/ll_math.py Log: added math.log (needed for lib-python) Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Thu Jul 28 10:56:16 2005 @@ -24,6 +24,7 @@ #'sqrt' : 'interp_math.sqrt', 'frexp' : 'interp_math.frexp', #'degrees' : 'interp_math.degrees', + 'log' : 'interp_math.log', 'log10' : 'interp_math.log10', 'fmod' : 'interp_math.fmod', #'atan' : 'interp_math.atan', Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 28 10:56:16 2005 @@ -84,6 +84,7 @@ declare(time.clock , float , 'll_time/clock') declare(time.sleep , noneannotation, 'll_time/sleep') declare(math.log10 , float , 'll_math/log10') +declare(math.log , float , 'll_math/log') declare(math.ceil , float , 'll_math/ceil') declare(math.frexp , frexpannotation, 'll_math/frexp') declare(math.atan2 , float , 'll_math/atan2') Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jul 28 10:56:16 2005 @@ -408,4 +408,5 @@ # by default we route all logging messages to nothingness # e.g. tests can then switch on logging to get more help # for failing tests -py.log.setconsumer('llinterp', None) +from pypy.tool.ansi_print import ansi_log +py.log.setconsumer('llinterp', ansi_log) Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Thu Jul 28 10:56:16 2005 @@ -2,6 +2,10 @@ import math +def ll_math_log(x): + return math.log(x) +ll_math_log.suggested_primitive = True + def ll_math_log10(x): return math.log10(x) ll_math_log10.suggested_primitive = True From tismer at codespeak.net Thu Jul 28 11:41:43 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 11:41:43 +0200 (CEST) Subject: [pypy-svn] r15227 - in pypy/dist/pypy/module: __builtin__ _codecs Message-ID: <20050728094143.1AEF727B74@code1.codespeak.net> Author: tismer Date: Thu Jul 28 11:41:36 2005 New Revision: 15227 Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/module/_codecs/app_codecs.py Log: made app_codecs suitable for geninterplevel. changed importing so that it does not crash but gives up with an error message, if it fails to marhsal something. will modify marshal to survive app_codecs now... hint about aesthetics: app_codecs could need some cosmetic overhaul. There are mixed tab/spaces, C style comments, missing spaces after commas. Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 11:41:36 2005 @@ -488,12 +488,16 @@ pass #XXX debug #print "indeed writing", cpathname + w_M = space.getattr(w_marshal, space.wrap('dumps')) + try: + w_str = space.call_method(w_marshal, 'dumps', space.wrap(co)) + except OperationError: + print "Problem while marshalling %s, skipping" % cpathname + return fd = os.open(cpathname, BIN_WRITEMASK, 0666) osfile = OsFileWrapper(fd) _w_long(osfile, pyc_magic) _w_long(osfile, mtime) - w_M = space.getattr(w_marshal, space.wrap('dumps')) - w_str = space.call_method(w_marshal, 'dumps', space.wrap(co)) strbuf = space.str_w(w_str) osfile.write(strbuf) os.close(fd) Modified: pypy/dist/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/app_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Thu Jul 28 11:41:36 2005 @@ -1,4 +1,3 @@ -"NOT_RPYTHON" """ _codecs -- Provides access to the codec registry and the builtin @@ -902,17 +901,21 @@ return p -def PyUnicode_EncodeUTF16(s,size,errors,byteorder='little'): +# moved out of local scope, especially because it didn't +# have any nested variables. + +def STORECHAR(CH, byteorder): + hi = chr(((CH) >> 8) & 0xff) + lo = chr((CH) & 0xff) + if byteorder == 'little': + return [lo, hi] + else: + return [hi, lo] + +def PyUnicode_EncodeUTF16(s, size, errors, byteorder='little'): # /* Offsets from p for storing byte pairs in the right order. */ - def STORECHAR(CH,byteorder): - hi = chr(((CH) >> 8) & 0xff) - lo = chr((CH) & 0xff) - if byteorder == 'little': - return [lo,hi] - else: - return [hi,lo] p = [] bom = sys.byteorder From arigo at codespeak.net Thu Jul 28 12:03:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 12:03:39 +0200 (CEST) Subject: [pypy-svn] r15228 - in pypy/dist/pypy: lib module/__builtin__ objspace/std Message-ID: <20050728100339.2778B27B74@code1.codespeak.net> Author: arigo Date: Thu Jul 28 12:03:33 2005 New Revision: 15228 Added: pypy/dist/pypy/lib/marshal.py (contents, props changed) Modified: pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/objspace/std/objspace.py Log: For now, disable pyc file support. This creates more mysterious umph-ish bootstrapping problems that we want to worry about at the moment. Added: pypy/dist/pypy/lib/marshal.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/marshal.py Thu Jul 28 12:03:33 2005 @@ -0,0 +1,3 @@ +# temporary +from _marshal import __doc__ +from _marshal import * Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 12:03:33 2005 @@ -48,7 +48,7 @@ pyfile_exist = False pycfile = filepart + ".pyc" - if os.path.exists(pycfile): + if 0: # os.path.exists(pycfile): # DISABLED PYC FILES FOR NOW pyc_state = check_compiled_module(space, pyfile, pyfile_ts, pycfile) pycfile_exists = pyc_state >= 0 pycfile_ts_valid = pyc_state > 0 and pyfile_exist @@ -365,9 +365,10 @@ w(space.builtin)) pycode.exec_code(space, w_dict, w_dict) - mtime = os.fstat(osfile.fd)[stat.ST_MTIME] - cpathname = pathname + 'c' - write_compiled_module(space, pycode, cpathname, mtime) + if 0: # DISABLED PYC FILES FOR NOW + mtime = os.fstat(osfile.fd)[stat.ST_MTIME] + cpathname = pathname + 'c' + write_compiled_module(space, pycode, cpathname, mtime) return w_mod Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 12:03:33 2005 @@ -81,7 +81,8 @@ self.setup_old_style_classes() # early bootstrap for marshal - self.sys.setmodule(self.setup_marshal()) + if 0: # DISABLED PYC FILES FOR NOW + self.sys.setmodule(self.setup_marshal()) # fix up a problem where multimethods apparently don't # like to define this at interp-level From arigo at codespeak.net Thu Jul 28 12:09:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 12:09:11 +0200 (CEST) Subject: [pypy-svn] r15229 - pypy/dist/pypy/module/__builtin__/test Message-ID: <20050728100911.C2FD427B74@code1.codespeak.net> Author: arigo Date: Thu Jul 28 12:09:08 2005 New Revision: 15229 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py Log: skip tests for pyc file support, for now Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Thu Jul 28 12:09:08 2005 @@ -196,6 +196,7 @@ # ___________________ .pyc related stuff _________________ def test_check_compiled_module(self): + py.test.skip('pyc file support disabled for now') space = self.space pathname = "whatever" mtime = 12345 @@ -224,6 +225,7 @@ os.remove(cpathname) def test_read_compiled_module(self): + py.test.skip('pyc file support disabled for now') space = self.space pathname = "whatever" mtime = 12345 @@ -242,6 +244,7 @@ assert ret == 42 def test_load_compiled_module(self): + py.test.skip('pyc file support disabled for now') space = self.space pathname = "whatever" mtime = 12345 @@ -313,6 +316,7 @@ #XXX Note tested while no writing def test_write_compiled_module(self): + py.test.skip('pyc file support disabled for now') space = self.space pathname = _testfilesource() fd = os.open(pathname, importing.BIN_READMASK, 0777) From arigo at codespeak.net Thu Jul 28 12:25:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 12:25:36 +0200 (CEST) Subject: [pypy-svn] r15230 - in pypy/dist/pypy: interpreter interpreter/pyparser module/symbol Message-ID: <20050728102536.B1EC627B74@code1.codespeak.net> Author: arigo Date: Thu Jul 28 12:25:31 2005 New Revision: 15230 Added: pypy/dist/pypy/module/symbol/ (props changed) pypy/dist/pypy/module/symbol/__init__.py (contents, props changed) Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pyparser/pytoken.py Log: An attempt to bring in sync the interp-level and app-level numbers associated to the tokens and symbols: * The token list is now hand-coded in pytoken.py, in such an order that it produces the same numbers as the lib-python/2.4.1/token.py. * The symbol list cannot be hand-coded, as it is generated by the grammar parser. Instead, there is now a mixed module 'symbol' that exports the values produced by the grammar parser to app-level. This allows grammar experimentations without having to worry about the values getting out of sync. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 12:25:31 2005 @@ -147,6 +147,7 @@ builtinmodule_list.append(('_codecs', None)) if self.options.useparsermodule == "recparser": builtinmodule_list.append(('parser', 'recparser')) + builtinmodule_list.append(('symbol', None)) elif self.options.useparsermodule == "parser": builtinmodule_list.append(('parser', None)) if self.options.nofakedmodules: Modified: pypy/dist/pypy/interpreter/pyparser/pytoken.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pytoken.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pytoken.py Thu Jul 28 12:25:31 2005 @@ -3,9 +3,7 @@ # adds a new map token_values to avoid doing getattr on the module # from PyPy RPython -import token - -N_TOKENS = token.N_TOKENS +N_TOKENS = 0 tok_name = {} tok_values = {} @@ -23,13 +21,62 @@ # This is used to replace None add_token( 'NULLTOKEN', -1 ) -for value, name in token.tok_name.items(): - add_token( name, value ) - -# Make sure '@' is in the token list -if "AT" not in tok_values: - add_token( "AT" ) +# For compatibility, this produces the same constant values as Python 2.4. +add_token( 'ENDMARKER' ) +add_token( 'NAME' ) +add_token( 'NUMBER' ) +add_token( 'STRING' ) +add_token( 'NEWLINE' ) +add_token( 'INDENT' ) +add_token( 'DEDENT' ) +add_token( 'LPAR' ) +add_token( 'RPAR' ) +add_token( 'LSQB' ) +add_token( 'RSQB' ) +add_token( 'COLON' ) +add_token( 'COMMA' ) +add_token( 'SEMI' ) +add_token( 'PLUS' ) +add_token( 'MINUS' ) +add_token( 'STAR' ) +add_token( 'SLASH' ) +add_token( 'VBAR' ) +add_token( 'AMPER' ) +add_token( 'LESS' ) +add_token( 'GREATER' ) +add_token( 'EQUAL' ) +add_token( 'DOT' ) +add_token( 'PERCENT' ) +add_token( 'BACKQUOTE' ) +add_token( 'LBRACE' ) +add_token( 'RBRACE' ) +add_token( 'EQEQUAL' ) +add_token( 'NOTEQUAL' ) +add_token( 'LESSEQUAL' ) +add_token( 'GREATEREQUAL' ) +add_token( 'TILDE' ) +add_token( 'CIRCUMFLEX' ) +add_token( 'LEFTSHIFT' ) +add_token( 'RIGHTSHIFT' ) +add_token( 'DOUBLESTAR' ) +add_token( 'PLUSEQUAL' ) +add_token( 'MINEQUAL' ) +add_token( 'STAREQUAL' ) +add_token( 'SLASHEQUAL' ) +add_token( 'PERCENTEQUAL' ) +add_token( 'AMPEREQUAL' ) +add_token( 'VBAREQUAL' ) +add_token( 'CIRCUMFLEXEQUAL' ) +add_token( 'LEFTSHIFTEQUAL' ) +add_token( 'RIGHTSHIFTEQUAL' ) +add_token( 'DOUBLESTAREQUAL' ) +add_token( 'DOUBLESLASH' ) +add_token( 'DOUBLESLASHEQUAL' ) +add_token( 'AT' ) +add_token( 'OP' ) +add_token( 'ERRORTOKEN' ) +# extra PyPy-specific tokens add_token( "COMMENT" ) add_token( "NL" ) Added: pypy/dist/pypy/module/symbol/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/symbol/__init__.py Thu Jul 28 12:25:31 2005 @@ -0,0 +1,31 @@ +"""Dynamic replacement for the stdlib 'symbol' module. + +This module exports the symbol values computed by the grammar parser +at run-time. +""" + +from pypy.interpreter.mixedmodule import MixedModule + +# Forward imports so they run at startup time +import pypy.interpreter.pyparser.pythonlexer +import pypy.interpreter.pyparser.pythonparse + + +class Module(MixedModule): + """Non-terminal symbols of Python grammar.""" + + appleveldefs = {} + interpleveldefs = {} # see below + + +# Export the values from our custom symbol module. +# Skip negative values (the corresponding symbols are not visible in +# pure Python). +from pypy.interpreter.pyparser import pysymbol + +sym_name = {} +for val, name in pysymbol.sym_name.items(): + if val >= 0: + Module.interpleveldefs[name] = 'space.wrap(%d)' % val + sym_name[val] = name +Module.interpleveldefs['sym_name'] = 'space.wrap(%r)' % (sym_name,) From tismer at codespeak.net Thu Jul 28 12:36:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 12:36:56 +0200 (CEST) Subject: [pypy-svn] r15231 - in pypy/dist/pypy: lib module/__builtin__ translator Message-ID: <20050728103656.6EC1D27B7B@code1.codespeak.net> Author: tismer Date: Thu Jul 28 12:36:54 2005 New Revision: 15231 Modified: pypy/dist/pypy/lib/_marshal.py pypy/dist/pypy/module/__builtin__/importing.py pypy/dist/pypy/translator/geninterplevel.py Log: marshalling of unicode related stuff works now. marshal imports the utf 8 support, directly. I agree that this is all nice but way too slow, so marhalling is disabled for now Modified: pypy/dist/pypy/lib/_marshal.py ============================================================================== --- pypy/dist/pypy/lib/_marshal.py (original) +++ pypy/dist/pypy/lib/_marshal.py Thu Jul 28 12:36:54 2005 @@ -4,6 +4,7 @@ """ import types +from _codecs import utf_8_decode, utf_8_encode try: import new @@ -152,8 +153,9 @@ def dump_unicode(self, x): self._write(TYPE_UNICODE) - s = x.encode('utf8') - self.w_long(len(s)) + #s = x.encode('utf8') + s, len_s = utf_8_encode(x) + self.w_long(len_s) self._write(s) dispatch[types.UnicodeType] = dump_unicode @@ -366,7 +368,8 @@ def load_unicode(self): n = self.r_long() s = self._read(n) - ret = s.decode('utf8') + #ret = s.decode('utf8') + ret, len_ret = utf_8_decode(s) return ret dispatch[TYPE_UNICODE] = load_unicode @@ -645,6 +648,10 @@ _load_dispatch = _FastUnmarshaller.dispatch +# _________________________________________________________________ +# +# compatibility + try: set except NameError: @@ -652,6 +659,10 @@ raise ValueError("cannot unmarshal set objects on Python < 2.4") frozenset = set +# _________________________________________________________________ +# +# user interface + def dump(x, f): m = _Marshaller(f.write) m.dump(x) Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 12:36:54 2005 @@ -404,10 +404,6 @@ the header; if not, return NULL. Doesn't set an exception. """ - #XXX Umph, we would need codecs to read codecs.pyc - # because of the unicode constants in it - if cpathname[-10:] == "codecs.pyc": - return -1 try: w_marshal = space.getbuiltinmodule('marshal') except OperationError: Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Thu Jul 28 12:36:54 2005 @@ -634,11 +634,7 @@ base_class = None base = cls def initinstance(): - try: - content = instance.__dict__.items() - except AttributeError: - import pdb - pdb.set_trace() ##!! + content = instance.__dict__.items() content.sort() for key, value in content: if self.should_translate_attr(instance, key): From hpk at codespeak.net Thu Jul 28 13:17:33 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 13:17:33 +0200 (CEST) Subject: [pypy-svn] r15233 - pypy/extradoc/minute Message-ID: <20050728111733.953F927B7C@code1.codespeak.net> Author: hpk Date: Thu Jul 28 13:17:32 2005 New Revision: 15233 Added: pypy/extradoc/minute/pypy-sync-07-28-2005.txt Log: the shortest pypy-sync meeting so far (<15 minutes) vacation hit and hildesheim2-sprinting is going on ... Added: pypy/extradoc/minute/pypy-sync-07-28-2005.txt ============================================================================== --- (empty file) +++ pypy/extradoc/minute/pypy-sync-07-28-2005.txt Thu Jul 28 13:17:32 2005 @@ -0,0 +1,89 @@ +============================================= +pypy-sync developer meeting 28th July 2005 +============================================= + +Attendees: + Samuele Pedroni, Armin Rigo, Anders Lehmann, + Holger Krekel (minutes), Richard Emslie + Christian Tismer, Eric van Riet Paap (posted + info after the meeting) + +Regular Topics +==================== + +- roll call. holger opens the meeting. + +- activity reports (3 prepared lines of info). + All Attendees submitted activity reports (see `IRC-Log`_ + at the end and 'LAST/NEXT/BLOCKERS' entries in particular) + +- resolve conflicts/blockers + No conflicts were discovered. + +Topics of the week +=================== + +codespeak migration planned early august +---------------------------------------------------------------------------- + +There is a migration of codespeak.net to new hardware and +a new hosting environment planned beginning of August. +Make sure that you are subscribe to `codespeak announce`_ list. + +.. _`codespeak announce`: http://codespeak.net/mailman/listinfo/codespeak-ann + +re-assigning tasks (related to NEXT activities) +----------------------------------------------------- + +none. + +Closing +------------------ + +closed at 1:10 (because we were mostly sprint-people on +the pypy-sync channel anyway) + +.. _`IRC-log`: + +Here is the full IRC log:: + hpk well, ok, i guess we start (and make it quick) + hpk here is the agenda: (...) + hpk roll call + hpk activity reports + hpk resolve conflicts/blockers + hpk codespeak migration + hpk re/assigning work tasks + hpk let's start with activity reports in this order hpk,aleale,arigo,pedronis,rxe,stakkars + hpk LAST: hildesheim2-sprint orga + participation + hpk NEXT: hildesheim2-sprint, codespeak migration + hpk BLOCKERS: too many issues and unanwsered mail + aleale last week: worked on math (superseeded by the sprint), compliance tests + aleale next: compliance tests + aleale blockers: Mac os x unfamiliarity + arigo DONE: fixed remaining TyperErrors, helped in removing faking + arigo NEXT: try translating PyPy + arigo BLOCKERS: - + pedronis Last: work on rtyping PyPy, sprint + pedronis Next: sprint, after depends on sprint results + pedronis Issues: umphishness + rxe LAST: sprint: start getting rid of fake files / various importing problems + rxe NEXT: more sprint stuff + rxe BLOCKERS: none + -->| __alex (~alex at 141.22.64.4) has joined #pypy-sync + stakkars DONE: fixing many bugs, pyc file stuff, which turns out to be slow + stakkars NEXT: continue on translation (and maybe write interplevel marshal in spare time) + stakkars BLOCKERS: we have waytoo much applevel code, which strikes back, now. + hpk ok, then it appears we have no conflicts + hpk so only topic is: codspeak migration + hpk most of you know alreada that beginning of august there is a codespeak hardware/hosting migration planned + hpk (make sure you are subscribed to codespeak-ann (announce list) + hpk then: that ends the ritual this time! + hpk see you next week + aleale bye + + ericvrp2 hi richard, did I miss the action? + rxe yes - short and sweet. :-) do you have 3 lines to paste? + ericvrp2 Last/current: holiday/llvm exception handling + ericvrp2 Next: impl. some llvm external functions + ericvrp2 Blockers: none + From arigo at codespeak.net Thu Jul 28 13:55:06 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 13:55:06 +0200 (CEST) Subject: [pypy-svn] r15235 - pypy/extradoc/sprintinfo Message-ID: <20050728115506.1687827B6C@code1.codespeak.net> Author: arigo Date: Thu Jul 28 13:55:05 2005 New Revision: 15235 Added: pypy/extradoc/sprintinfo/hildesheim2-done.txt - copied, changed from r15233, pypy/extradoc/sprintinfo/hildesheim2-planning.txt Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: This day's internal progress report and planning. Copied: pypy/extradoc/sprintinfo/hildesheim2-done.txt (from r15233, pypy/extradoc/sprintinfo/hildesheim2-planning.txt) ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-done.txt Thu Jul 28 13:55:05 2005 @@ -1,42 +1,6 @@ -PyPy Hildesheim2 sprint planning (25th-31st July) -------------------------------------------------------- - -overall time planning:: - 25th full sprint day - 26th full sprint day - 27th afternoon break - 28th morning break - 29th full sprint day # (compliance test decision) - 30th full sprint day - 31th more or less full sprint day - - each day: - 9-10 AM breakfast - 10:30 planning session - evening: dinner - - Carl Friedrich Bolz - Richard Emslie - Armin Rigo - Holger Krekel whole-time - Christian Tismer whole-time - Samuele Pedroni whole-time - -Misc --------- - -* -> TRACKER write a tool that discovers which revision of the pypy tree - broke the high level annotator (in that it produced SomeObjects). - Consider distributing the actual annotation to multiple hosts. (holger) - -* -> TRACKER: (mostly done) add missing docstrings on app-level built-in types and - functions, etc. (Laura): there now is a program that generates the - docstrings into the appropriate places but it needs prettification. - (christian) - -Current Main task: RTYPER issues ------------------------------------ +PyPy Hildesheim2 sprint -- DONE +------------------------------- - do we want to continue to work with the snapshsot? does it make sense during the sprint? @@ -140,8 +104,3 @@ - Richard, Chris track down remaining .pyc file issues. - -Concerning the sync meeting of tomorrow, and given that -we stop working this afternoon, we agreed now for -tomorrow, that Anders should be asked to work on the -complicancy test failures. Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Thu Jul 28 13:55:05 2005 @@ -38,79 +38,34 @@ Current Main task: RTYPER issues ----------------------------------- -- do we want to continue to work with the snapshsot? does it make sense - during the sprint? - decision: during the sprint use directly the trunk, mail pypy-dev - about this (holger, samuele) - - -- we want to work on pypy/translator/goal/ISSUES.txt - -pairs:: - - Samuele, Carl Friedrich (progressing on External functions) - DONE: refactored math and os function out of annotation/builtin and - rpython/rbuiltin into the extfunctable, implemented some - math.*, os.* functions. fixed os.stat - - Open issues: - - DONE (for C) RPython string -> C null-terminated string - conversion. The null termination char is not there! - - - DONE (__builtin__/* don't raise, the rest does) - The flow space kills exception handling for built-ins, - this is not what we want e.g. for os.* functions; - decide new criteria. Maybe only for thing in __builtin__ - or list only the built-ins we want exception handling - suppressed. - - - DONE finish os.path.exists and os.path.isdir support - - (Armin, Carl Friedrich) - - - Armin, Christian (random RTyper problems) - DONE: down to override:cpy_stablecompiler, - up to wrap/unwrap issues related to faking. - The hope is that we can get rid of faking. - - DONE Completing marshal, made it into a mixed-module - that can be geninterped. - (chris wishes to redo it in interplevel) - - DONE modulo some problems. - Inconsistency about problems on different machines. - PYC still untested. More tests needed. - Plan: enable pyc loading to bootstrap compiler - at app-level (Christian, Richard) - Todo: - Choose a PYC file version for PyPy (2.4.1) - Using this version is ok, because our compiler - exactly produces these. The extra functionality in - our marshal is not related to magic numbers. - - Richard, Holger (getting rid of faked files) - DONE: importing uses only os.* functions at - interp-level. With --file option sys.std* - use our own app-level implementation of files. - --file is on by default now when translating - - Remaining problem list: - - - DONE Samuele, Holger - make py.py --file --nofakedmodules work - (crashes somehow) - - - DONE (chris) - allways enforce geninterping of marshal, maybe - similar to what we did with exceptions - - - DONE Samuele, Holger - primitive math is done. Implement applevel math, - have many tests (we are using compliance tests only). +Remaining problem about pyc files:: - - Samuele, Holger, transitional - unify the way stdobjspace is configured. + The inconsistency problems are more or less solved now, + but PYC file support is disabled at the moment because + it is just too slow in general. + + Bootstrapping is right but messy. Christian will rewrite + marshal at interp-level at some point. + + We won't use PYC file support for translate_pypy anyway. + We will construct and initialize the object space just like now, + and then import at app-level the 'compiler' package, and finally + patch the executioncontext.compiler to use this 'compiler' + package. The resulting object space is what translate_pypy is + seeing. + + Ultimately the compiler and marshal should both be at + interp-level anyway. + +Getting rid of faking:: + + DONE. no faking left if you use --file --nofakedmodules. + (of course in this case you can't import most modules like + _sre at all.) + +Left:: + + - unify the way stdobjspace is configured. the basic objspace configuration interface becomes a set of keyword arguments. The current command line arguments will be mapped onto this @@ -118,30 +73,18 @@ This also includes configuration of which modules should be loaded. - - Samuele, eleumaS - extend the testing framework to allow to specify + - extend the testing framework to allow to specify a space with options for a test. Related to the latter. - - Holger, Armin - bug to be fixed: applevel test stdout is no longer + - bug to be fixed: applevel test stdout is no longer captured. - - Armin, and everybody else, please - run translation and try to avoid any faking at all. - An example where it still happens is EllipsisType - which gets wrapped by geninterplevel. - - - DONE - Richard, Chris - Choose a PYC file version for PyPy (2.4.1) - Using this version is ok, because our compiler - exactly produces these. The extra functionality in - our marshal is not related to magic numbers. - - - Richard, Chris - track down remaining .pyc file issues. - -Concerning the sync meeting of tomorrow, and given that -we stop working this afternoon, we agreed now for -tomorrow, that Anders should be asked to work on the -complicancy test failures. + - running translate_pypy! + +Pairing +------- + +configuration of the stdobjspace (holger, richard) + +compiler + translate_pypy (christian, samuele, armin, carl friedrich) +(trying to sub-pair internally) From hpk at codespeak.net Thu Jul 28 14:41:17 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 14:41:17 +0200 (CEST) Subject: [pypy-svn] r15237 - pypy/branch/pypy-newobjspace Message-ID: <20050728124117.6534127B83@code1.codespeak.net> Author: hpk Date: Thu Jul 28 14:41:16 2005 New Revision: 15237 Added: pypy/branch/pypy-newobjspace/ - copied from r15236, pypy/dist/pypy/ Log: temporary branch for sorting the new objspace configuration out From cfbolz at codespeak.net Thu Jul 28 14:49:49 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 14:49:49 +0200 (CEST) Subject: [pypy-svn] r15238 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050728124949.079E027B83@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 14:49:47 2005 New Revision: 15238 Modified: pypy/dist/pypy/module/__builtin__/app_help.py Log: typo Modified: pypy/dist/pypy/module/__builtin__/app_help.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/app_help.py (original) +++ pypy/dist/pypy/module/__builtin__/app_help.py Thu Jul 28 14:49:47 2005 @@ -12,7 +12,7 @@ exit = "Use Ctrl-D (i.e. EOF) to exit." def copyright(): - print 'Copyright 2003-2004 Pypy development team.\nAll rights reserved.\nFor further information see http://www.codespaek.net/pypy.\nSome materials may have a different copyright.\nIn these cases, this is explicitly noted in the source code file.' + print 'Copyright 2003-2004 Pypy development team.\nAll rights reserved.\nFor further information see http://www.codespeak.net/pypy.\nSome materials may have a different copyright.\nIn these cases, this is explicitly noted in the source code file.' def license(): print \ From arigo at codespeak.net Thu Jul 28 14:53:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 14:53:25 +0200 (CEST) Subject: [pypy-svn] r15239 - in pypy/dist/pypy: interpreter interpreter/pyparser objspace/std tool Message-ID: <20050728125325.6ADF527B83@code1.codespeak.net> Author: arigo Date: Thu Jul 28 14:53:18 2005 New Revision: 15239 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/error.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/tool/ansi_print.py Log: A new option --compiler=pyparseapp (IN-PROGRESS, not working yet): This option construct and initialize the object space just like now, and then import at app-level the 'compiler' package, and finally patch the executioncontext.compiler to use this 'compiler' package. The resulting object space is what translate_pypy will see. Ultimately the compiler and marshal should both be at interp-level anyway. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 14:53:18 2005 @@ -214,12 +214,10 @@ def createcompiler(self): "Factory function creating a compiler object." # XXX simple selection logic for now - if self.options.compiler == 'pyparse': + if self.options.compiler in ('pyparse', 'pyparseapp'): return PythonCompiler(self) elif self.options.compiler == 'cpython': return CPythonCompiler(self) - #elif self.options.compiler == 'pyparseapp': - # return PythonCompilerApp(self) else: raise ValueError('unknown --compiler option value: %r' % ( self.options.compiler,)) Modified: pypy/dist/pypy/interpreter/error.py ============================================================================== --- pypy/dist/pypy/interpreter/error.py (original) +++ pypy/dist/pypy/interpreter/error.py Thu Jul 28 14:53:18 2005 @@ -197,8 +197,9 @@ # Utilities from pypy.tool.ansi_print import ansi_print -def debug_print(text, file=None): - ansi_print(text, esc="31", file=file) # ANSI color code "red" +def debug_print(text, file=None, newline=True): + # 31: ANSI color code "red" + ansi_print(text, esc="31", file=file, newline=newline) ### installing the excepthook for OperationErrors ##def operr_excepthook(exctype, value, traceback): Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Thu Jul 28 14:53:18 2005 @@ -233,37 +233,55 @@ compile_parse_result._annspecialcase_ = 'override:cpy_stablecompiler' -##class PythonCompilerApp(PythonCompiler): -## """Temporary. Calls the stablecompiler package at app-level.""" +class PythonCompilerApp(PythonCompiler): + """Temporary. Calls the stablecompiler package at app-level.""" -## def __init__(self, space): -## PythonCompiler.__init__(self, space) -## space.appexec(r'''(): -## # NOT_RPYTHON -## from pypy.interpreter import stablecompiler -## from pypy.interpreter.stablecompiler.pycodegen import ModuleCodeGenerator -## from pypy.interpreter.stablecompiler.pycodegen import InteractiveCodeGenerator -## from pypy.interpreter.stablecompiler.pycodegen import ExpressionCodeGenerator -## from pypy.interpreter.stablecompiler.transformer import Transformer -## transformer = Transformer() -## tree = transformer.compile_node(tuples) -## stablecompiler.misc.set_filename(filename, tree) -## if mode == 'exec': -## codegenerator = ModuleCodeGenerator(tree) -## elif mode == 'single': -## codegenerator = InteractiveCodeGenerator(tree) -## else: # mode == 'eval': -## codegenerator = ExpressionCodeGenerator(tree) -## c = codegenerator.getCode() -## ''') - -## def compile_parse_result(self, parse_result, filename, mode): - - - - - - + def __init__(self, space): + from pypy.interpreter.error import debug_print + PythonCompiler.__init__(self, space) + debug_print("importing the 'compiler' package at app-level...", + newline=False) + self.w_applevelcompile = space.appexec([], r'''(): + from compiler.misc import set_filename + from compiler.pycodegen import ModuleCodeGenerator + from compiler.pycodegen import InteractiveCodeGenerator + from compiler.pycodegen import ExpressionCodeGenerator + from compiler.transformer import Transformer + + def applevelcompile(tuples, filename, mode): + transformer = Transformer() + tree = transformer.compile_node(tuples) + set_filename(filename, tree) + if mode == 'exec': + codegenerator = ModuleCodeGenerator(tree) + elif mode == 'single': + codegenerator = InteractiveCodeGenerator(tree) + else: # mode == 'eval': + codegenerator = ExpressionCodeGenerator(tree) + return codegenerator.getCode() + + return applevelcompile + ''') + debug_print(" done") + + def compile_parse_result(self, parse_result, filename, mode): + space = self.space + source_encoding, stack_element = parse_result + w_nested_tuples = stack_element.as_w_tuple(space, lineno=True) + if source_encoding is not None: + w_nested_tuples = space.newtuple([ + space.wrap(pysymbol.encoding_decl), + w_nested_tuples, + space.wrap(source_encoding)]) + + from pypy.interpreter.error import debug_print + debug_print("app-level compiling...", newline=False) + w_code = space.call_function(self.w_applevelcompile, + w_nested_tuples, + space.wrap(filename), + space.wrap(mode)) + debug_print(" done") + return w_code class PyPyCompiler(CPythonCompiler): Modified: pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py (original) +++ pypy/dist/pypy/interpreter/pyparser/tuplebuilder.py Thu Jul 28 14:53:18 2005 @@ -16,6 +16,14 @@ else: return self.nodes[0][:-1] + def as_w_tuple(self, space, lineno=False): + num, value, lineno = self.nodes[0] + content = [space.wrap(num), space.wrap(value)] + if lineno: + content.append(space.wrap(lineno)) + return space.newtuple(content) + + class NonTerminal(StackElement): def __init__(self, num, nodes): """rulename should always be None with regular Python grammar""" @@ -25,8 +33,13 @@ def as_tuple(self, lineno=False): l = [self.num] + [node.as_tuple(lineno) for node in self.nodes] return tuple(l) - - + + def as_w_tuple(self, space, lineno=False): + l = [space.wrap(self.num)] + l += [node.as_w_tuple(space, lineno) for node in self.nodes] + return space.newtuple(l) + + def expand_nodes(stack_elements): """generate a nested tuples from a list of stack elements""" expanded = [] Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 14:53:18 2005 @@ -99,6 +99,11 @@ if self.options.uselibfile: self.setuselibfile() + # XXX hack!: patch the compiler after initialization is complete + if self.options.compiler == 'pyparseapp': + from pypy.interpreter.pycompiler import PythonCompilerApp + self.getexecutioncontext().compiler = PythonCompilerApp(self) + def enable_old_style_classes_as_default_metaclass(self): self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj) Modified: pypy/dist/pypy/tool/ansi_print.py ============================================================================== --- pypy/dist/pypy/tool/ansi_print.py (original) +++ pypy/dist/pypy/tool/ansi_print.py Thu Jul 28 14:53:18 2005 @@ -4,14 +4,16 @@ import sys -def ansi_print(text, esc, file=None): +def ansi_print(text, esc, file=None, newline=True): if file is None: file = sys.stderr text = text.rstrip() if esc and sys.platform != "win32" and file.isatty(): text = ('\x1b[%sm' % esc + text + '\x1b[0m') # ANSI color code "reset" - file.write(text + '\n') + if newline: + text += '\n' + file.write(text) def ansi_log(msg): keywords = list(msg.keywords) From cfbolz at codespeak.net Thu Jul 28 15:34:29 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 15:34:29 +0200 (CEST) Subject: [pypy-svn] r15240 - pypy/dist/pypy/module/__builtin__ Message-ID: <20050728133429.348F627B83@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 15:34:28 2005 New Revision: 15240 Modified: pypy/dist/pypy/module/__builtin__/importing.py Log: commented out printing at interplevel to remove SomeObjects Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu Jul 28 15:34:28 2005 @@ -453,7 +453,7 @@ raise OperationError(space.w_ImportError, w( "Bad magic number in %s" % cpathname)) _r_long(osfile) # skip time stamp - print "loading pyc file:", cpathname + #print "loading pyc file:", cpathname code_w = read_compiled_module(space, cpathname, osfile) #if (Py_VerboseFlag) # PySys_WriteStderr("import %s # precompiled from %s\n", @@ -489,7 +489,7 @@ try: w_str = space.call_method(w_marshal, 'dumps', space.wrap(co)) except OperationError: - print "Problem while marshalling %s, skipping" % cpathname + #print "Problem while marshalling %s, skipping" % cpathname return fd = os.open(cpathname, BIN_WRITEMASK, 0666) osfile = OsFileWrapper(fd) From cfbolz at codespeak.net Thu Jul 28 15:35:19 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 15:35:19 +0200 (CEST) Subject: [pypy-svn] r15241 - pypy/dist/pypy/module/math Message-ID: <20050728133519.7339627B83@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 15:35:18 2005 New Revision: 15241 Modified: pypy/dist/pypy/module/math/interp_math.py Log: made our math module's log function accept a base parameter Modified: pypy/dist/pypy/module/math/interp_math.py ============================================================================== --- pypy/dist/pypy/module/math/interp_math.py (original) +++ pypy/dist/pypy/module/math/interp_math.py Thu Jul 28 15:35:18 2005 @@ -1,6 +1,6 @@ import math -from pypy.interpreter.gateway import ObjSpace +from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped class State: def __init__(self, space): @@ -55,12 +55,15 @@ return space.wrap(math.asin(x)) asin.unwrap_spec = [ObjSpace, float] -def log(space, x, base=math.e): +def log(space, x, w_base=NoneNotWrapped): """log(x[, base]) -> the logarithm of x to the given base. If the base not specified, returns the natural logarithm (base e) of x. """ - return space.wrap(math.log(x, base)) -log.unwrap_spec = [ObjSpace, float, float] + if w_base is None: + return space.wrap(math.log(x)) + else: + return space.wrap(math.log(x) / math.log(space.float_w(w_base))) +log.unwrap_spec = [ObjSpace, float, W_Root] def fabs(space, x): """fabs(x) From cfbolz at codespeak.net Thu Jul 28 15:36:15 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 15:36:15 +0200 (CEST) Subject: [pypy-svn] r15242 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050728133615.1932627B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 15:36:12 2005 New Revision: 15242 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added external function call to the c backend Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Jul 28 15:36:12 2005 @@ -17,7 +17,6 @@ ll_os .ll_os_stat: 'LL_os_stat', ll_os .ll_os_fstat: 'LL_os_fstat', ll_time.ll_time_clock: 'LL_time_clock', - ll_math.ll_math_log10: 'LL_math_log10', ll_math.ll_math_ceil: 'LL_math_ceil', ll_math.ll_math_frexp: 'LL_math_frexp', ll_math.ll_math_atan2: 'LL_math_atan2', @@ -25,6 +24,8 @@ ll_math.ll_math_floor: 'LL_math_floor', ll_math.ll_math_exp: 'LL_math_exp', ll_math.ll_math_ldexp: 'LL_math_ldexp', + ll_math.ll_math_log10: 'LL_math_log10', + ll_math.ll_math_log: 'LL_math_log', ll_math.ll_math_modf: 'LL_math_modf', } Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Thu Jul 28 15:36:12 2005 @@ -11,9 +11,7 @@ /* XXX completely ignoring exceptions/error checking for now */ -double LL_math_log10(double x) { - return log10(x); -} + double LL_math_ceil(double x) { return ceil(x); } @@ -27,6 +25,7 @@ double LL_math_atan2(double x, double y) { return atan2(x, y); } + double LL_math_fmod(double x, double y) { return fmod(x, y); } @@ -40,6 +39,15 @@ return ldexp(x, (int) y); } +double LL_math_log(double x) { + return log(x); +} + +double LL_math_log10(double x) { + return log10(x); +} + + RPyMODF_RESULT* LL_math_modf(double x) { double intpart; double fracpart = modf(x, &intpart); Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Thu Jul 28 15:36:12 2005 @@ -108,6 +108,13 @@ f = compile(fn, [float]) assert f(10.123) == modf(10.123) +def test_math_log(): + from math import log10, log + def fn(x): + return log10(x) + log(x) + f = compile(fn, [float]) + assert f(32675312.32123) == fn(32675312.32123) + def test_os_path_exists(): tmpfile = str(udir.join('test_os_path_exists.TMP')) def fn(): From hpk at codespeak.net Thu Jul 28 15:51:01 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 15:51:01 +0200 (CEST) Subject: [pypy-svn] r15243 - in pypy/branch/pypy-newobjspace: bin interpreter module/sys objspace/std tool Message-ID: <20050728135101.6031527B83@code1.codespeak.net> Author: hpk Date: Thu Jul 28 15:50:58 2005 New Revision: 15243 Modified: pypy/branch/pypy-newobjspace/bin/py.py pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py pypy/branch/pypy-newobjspace/module/sys/state.py pypy/branch/pypy-newobjspace/objspace/std/objspace.py pypy/branch/pypy-newobjspace/tool/option.py Log: py.py begins to work we need some tests for the different configs Modified: pypy/branch/pypy-newobjspace/bin/py.py ============================================================================== --- pypy/branch/pypy-newobjspace/bin/py.py (original) +++ pypy/branch/pypy-newobjspace/bin/py.py Thu Jul 28 15:50:58 2005 @@ -53,6 +53,24 @@ return options +def make_objspace(cmdlineopt): + from pypy.objspace import std + if cmdlineopt.objspace not in ('std', 'thunk'): + raise ValueError("cannot instantiate %r space" %(cmdlineopt.objspace,)) + + # so far we always need a StdObjSpace + space = std.Space(usemodules = cmdlineopt.usemodules, + nofaking = cmdlineopt.nofaking, + uselibfile = cmdlineopt.uselibfile, + oldstyle = cmdlineopt.oldstyle, + parser = cmdlineopt.parser, + compiler = cmdlineopt.compiler, + ) + if cmdlineopt.objspace == 'thunk': + from pypy.objspace import thunk + space = thunk.Space(space) + return space + def main_(argv=None): starttime = time.time() args = option.process_options(get_main_options(), Options, argv[1:]) @@ -60,7 +78,9 @@ error.RECORD_INTERPLEVEL_TRACEBACK = True # create the object space - space = option.objspace() + + space = make_objspace(Options) + space._starttime = starttime assert 'pypy.tool.udir' not in sys.modules, ( "running py.py should not import pypy.tool.udir, which is\n" Modified: pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py (original) +++ pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py Thu Jul 28 15:50:58 2005 @@ -6,7 +6,6 @@ from pypy.interpreter.miscutils import ThreadLocals from pypy.tool.cache import Cache from pypy.rpython.rarithmetic import r_uint -import pypy.tool.option __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'BaseWrappable', 'W_Root'] @@ -94,6 +93,9 @@ finally: self.space.leave_cache_building_mode(val) +class ObjSpaceOptions: + def _freeze_(self): + return True class ObjSpace(object): """Base class for the interpreter-level implementations of object spaces. @@ -101,17 +103,24 @@ full_exceptions = True # full support for exceptions (normalization & more) - def __init__(self, options=None): + def __init__(self, usemodules=(), + nofaking=False, + uselibfile=False, + parser="recparser", + compiler="pyparse"): + "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() # set recursion limit # sets all the internal descriptors - # XXX: Options in option.py is replaced by a function so - # it's not really clean to do a from option import Options - # since changing import order can change the Options object - self.options = options or pypy.tool.option.Options() + self.options = ObjSpaceOptions() + self.options.parser = parser + self.options.nofaking = nofaking + self.options.uselibfile = uselibfile + self.options.compiler = compiler + self.options.usemodules = usemodules self.initialize() def __repr__(self): @@ -140,21 +149,24 @@ try: return self._builtinmodule_list except AttributeError: - builtinmodule_list = [('sys', None), ('__builtin__', None), - ('exceptions', None), ('marshal', None)] - builtinmodule_list.append(('unicodedata', None)) - # Uncomment the following line to enable the builtin _codecs module - builtinmodule_list.append(('_codecs', None)) - if self.options.useparsermodule == "recparser": - builtinmodule_list.append(('parser', 'recparser')) - builtinmodule_list.append(('symbol', None)) - elif self.options.useparsermodule == "parser": - builtinmodule_list.append(('parser', None)) - if self.options.nofakedmodules: - builtinmodule_list.append(('posix', None)) - builtinmodule_list.append(('math', None)) - self._builtinmodule_list = builtinmodule_list - return self._builtinmodule_list + pass + l = 'sys __builtin__ exceptions unicodedata _codecs'.split() + if self.options.nofaking: + l.append('posix') + l.append('math') + for name in self.options.usemodules: + if name in l: + continue + # XXX error throwing (catch wrong names) + l.append(name) + builtinmodule_list = [(x, None) for x in l] + if self.options.parser == "recparser": + builtinmodule_list.append(('parser', 'recparser')) + builtinmodule_list.append(('symbol', None)) + elif self.options.parser == "parser": + builtinmodule_list.append(('parser', None)) + self._builtinmodule_list = builtinmodule_list + return self._builtinmodule_list def make_builtins(self): "NOT_RPYTHON: only for initializing the space." Modified: pypy/branch/pypy-newobjspace/module/sys/state.py ============================================================================== --- pypy/branch/pypy-newobjspace/module/sys/state.py (original) +++ pypy/branch/pypy-newobjspace/module/sys/state.py Thu Jul 28 15:50:58 2005 @@ -50,7 +50,7 @@ builtinmodule_list = self.space.get_builtinmodule_list() builtinmodule_names = [name for name, mixedname in builtinmodule_list] - if not space.options.nofakedmodules: + if not space.options.nofaking: for modname in ALL_BUILTIN_MODULES: if modname not in builtinmodule_names: if not (os.path.exists( Modified: pypy/branch/pypy-newobjspace/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/objspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/objspace.py Thu Jul 28 15:50:58 2005 @@ -29,6 +29,12 @@ PACKAGE_PATH = 'objspace.std' + def __init__(self, oldstyle=False, **kw): + super(StdObjSpace, self).__init__(**kw) + self.options.oldstyle = oldstyle + if oldstyle: + self.enable_old_style_classes_as_default_metaclass() + def initialize(self): "NOT_RPYTHON: only for initializing the space." self._typecache = Cache() Modified: pypy/branch/pypy-newobjspace/tool/option.py ============================================================================== --- pypy/branch/pypy-newobjspace/tool/option.py (original) +++ pypy/branch/pypy-newobjspace/tool/option.py Thu Jul 28 15:50:58 2005 @@ -7,15 +7,16 @@ class Options: showwarning = 0 - spaces = [] + objspace = "std" oldstyle = 0 uselibfile = 0 - nofakedmodules = 0 - useparsermodule = "recparser" # "cpython" / "recparser" / "parser" + nofaking = 0 + parser = "recparser" # "cpython" / "recparser" / "parser" compiler = "pyparse" # "cpython" # "pyparse" pypy parser, cpython's compiler package # "pyparseapp" same, running the compiler at app-level # "pycomp" pypy parser and compiler (TBD) + usemodules = [] version = "2.4" # "native" / "2.3" / "2.4" def run_tb_server(option, opt, value, parser): @@ -25,23 +26,25 @@ def get_standard_options(): options = [] - def objspace_callback(option, opt, value, parser): - parser.values.spaces.append(value) - + def usemodules_callback(option, opt, value, parser): + parser.values.usemodules.append(value) + options.append(make_option( - '-o', '--objspace', action="callback", metavar='NAME', - callback=objspace_callback, type="string", + '-o', '--objspace', action="store", type="string", dest="objspace", help="object space to run PyPy on.")) - options.append(make_option( - '--oldstyle', action="store_true",dest="oldstyle", + '--usemodules', action="callback", metavar='NAME', + callback=usemodules_callback, type="string", + help="(mixed) modules to use.")) + options.append(make_option( + '--oldstyle', action="store_true", dest="oldstyle", help="enable oldstyle classes as default metaclass (std objspace only)")) options.append(make_option( - '--file', action="store_true",dest="uselibfile", + '--uselibfile', action="store_true", dest="uselibfile", help="enable our custom file implementation")) options.append(make_option( - '--nofakedmodules', action="store_true",dest="nofakedmodules", - help="don't fake any module")) + '--nofaking', action="store_true", dest="nofaking", + help="avoid faking of modules or objects")) options.append(make_option( '-w', action="store_true", dest="showwarning", help="enable warnings (disabled by default)")) @@ -51,12 +54,12 @@ help="use web browser for traceback info")) options.append(make_option( '--compiler', action="store", type="string", dest="compiler", - help="select the parser/compiler to use internally", - metavar="[cpython|pyparse|pyparseapp]")) + help="select the compiler approach to use internally", + metavar="[pyparser|cpython|pyparseapp]")) options.append(make_option( - '--parsermodule', action="store",type="string", dest="useparsermodule", + '--parser', action="store",type="string", dest="parser", help="select the parser module to use", - metavar="[cpython|recparser|parser]")) + metavar="[recparser|cpython|parser]")) ## for this to work the option module need to be loaded before the grammar! ## options.append(make_option( ## '--version', action="store",type="string", dest="version", @@ -72,25 +75,3 @@ op.add_options(optionlist) options, args = op.parse_args(argv, input_options) return args - -def objspace(name='', _spacecache={}): - """ return singleton ObjSpace instance. - - this is configured via the environment variable OBJSPACE - """ - - if not name: - if Options.spaces: - name = Options.spaces[-1] - else: - name = os.environ.get('OBJSPACE', 'std') - - try: - return _spacecache[name] - except KeyError: - module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) - Space = module.Space - space = Space( Options() ) - if name == 'std' and Options.oldstyle: - space.enable_old_style_classes_as_default_metaclass() - return _spacecache.setdefault(name, space) From hpk at codespeak.net Thu Jul 28 15:57:23 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 15:57:23 +0200 (CEST) Subject: [pypy-svn] r15244 - pypy/branch/pypy-newobjspace/interpreter Message-ID: <20050728135723.B0B9027B83@code1.codespeak.net> Author: hpk Date: Thu Jul 28 15:57:23 2005 New Revision: 15244 Modified: pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py Log: nofaking enables uselibfile as well Modified: pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py (original) +++ pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py Thu Jul 28 15:57:23 2005 @@ -108,17 +108,15 @@ uselibfile=False, parser="recparser", compiler="pyparse"): - "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() # set recursion limit # sets all the internal descriptors - self.options = ObjSpaceOptions() self.options.parser = parser self.options.nofaking = nofaking - self.options.uselibfile = uselibfile + self.options.uselibfile = uselibfile or nofaking self.options.compiler = compiler self.options.usemodules = usemodules self.initialize() From hpk at codespeak.net Thu Jul 28 16:09:10 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 16:09:10 +0200 (CEST) Subject: [pypy-svn] r15250 - in pypy/branch/pypy-newobjspace: objspace/std translator/goal Message-ID: <20050728140910.3CA6727B8C@code1.codespeak.net> Author: hpk Date: Thu Jul 28 16:09:08 2005 New Revision: 15250 Modified: pypy/branch/pypy-newobjspace/objspace/std/objspace.py pypy/branch/pypy-newobjspace/translator/goal/targetpypymain.py Log: - adapt object space initialization from translation - small renaming Modified: pypy/branch/pypy-newobjspace/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/objspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/objspace.py Thu Jul 28 16:09:08 2005 @@ -103,7 +103,7 @@ """) if self.options.uselibfile: - self.setuselibfile() + self.inituselibfile() def enable_old_style_classes_as_default_metaclass(self): self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj) @@ -151,7 +151,7 @@ w_mod = self.wrap(mod) return w_mod, w_dic - def setuselibfile(self): + def inituselibfile(self): """ NOT_RPYTHON use our application level file implementation including re-wrapping sys.stdout/err/in """ @@ -159,7 +159,7 @@ space = self # nice print helper if the below does not work # (we dont have prints working at applevel before - # setuselibfile is complete) + # inituselibfile is complete) #from pypy.interpreter import gateway #def printit(space, w_msg): # s = space.str_w(w_msg) Modified: pypy/branch/pypy-newobjspace/translator/goal/targetpypymain.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/goal/targetpypymain.py (original) +++ pypy/branch/pypy-newobjspace/translator/goal/targetpypymain.py Thu Jul 28 16:09:08 2005 @@ -38,11 +38,7 @@ # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False - from pypy.tool.option import Options - options = Options() - options.uselibfile = True - options.nofakedmodules = True - space = StdObjSpace(options) + space = StdObjSpace(nofaking=True) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From rxe at codespeak.net Thu Jul 28 16:24:47 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 16:24:47 +0200 (CEST) Subject: [pypy-svn] r15251 - pypy/branch/pypy-newobjspace/bin Message-ID: <20050728142447.E8E1427B8C@code1.codespeak.net> Author: rxe Date: Thu Jul 28 16:24:46 2005 New Revision: 15251 Modified: pypy/branch/pypy-newobjspace/bin/py.py Log: Remove references to optik and remove our version from svn. Modified: pypy/branch/pypy-newobjspace/bin/py.py ============================================================================== --- pypy/branch/pypy-newobjspace/bin/py.py (original) +++ pypy/branch/pypy-newobjspace/bin/py.py Thu Jul 28 16:24:46 2005 @@ -12,7 +12,7 @@ pass from pypy.tool import option -from pypy.tool.optik import make_option +from optparse import make_option from pypy.interpreter import main, interactive, error import os, sys import time From cfbolz at codespeak.net Thu Jul 28 16:28:12 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 16:28:12 +0200 (CEST) Subject: [pypy-svn] r15252 - pypy/dist/pypy/rpython/module/test Message-ID: <20050728142812.80D4027B8C@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 16:28:11 2005 New Revision: 15252 Modified: pypy/dist/pypy/rpython/module/test/test_ll_math.py Log: added test for log Modified: pypy/dist/pypy/rpython/module/test/test_ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_math.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_math.py Thu Jul 28 16:28:11 2005 @@ -16,4 +16,6 @@ assert result.item0 == math.frexp(10.1)[0] assert result.item1 == math.frexp(10.1)[1] - +def test_ll_log(): + assert ll_math_log(8943.790148912) == math.log(8943.790148912) + assert ll_math_log10(8943.790148912) == math.log10(8943.790148912) From rxe at codespeak.net Thu Jul 28 16:29:12 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 16:29:12 +0200 (CEST) Subject: [pypy-svn] r15253 - pypy/branch/pypy-newobjspace/tool Message-ID: <20050728142912.515A527B85@code1.codespeak.net> Author: rxe Date: Thu Jul 28 16:29:10 2005 New Revision: 15253 Removed: pypy/branch/pypy-newobjspace/tool/optik.py Modified: pypy/branch/pypy-newobjspace/tool/option.py Log: Remove references to optik and remove our version from s {sorry missed files in r15251) Deleted: /pypy/branch/pypy-newobjspace/tool/optik.py ============================================================================== --- /pypy/branch/pypy-newobjspace/tool/optik.py Thu Jul 28 16:29:10 2005 +++ (empty file) @@ -1,1667 +0,0 @@ -"""optik - -A powerful, extensible, and easy-to-use command-line parser for Python. - -By Greg Ward - -See http://optik.sourceforge.net/ -""" - -"""optik.errors - -Exception classes used by Optik. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17 GPW (from optik.py) - -import sys -import types, os -import string, re - -class OptikError (Exception): - def __init__ (self, msg): - self.msg = msg - - def __str__ (self): - return self.msg - - -class OptionError (OptikError): - """ - Raised if an Option instance is created with invalid or - inconsistent arguments. - """ - - def __init__ (self, msg, option): - self.msg = msg - self.option_id = str(option) - - def __str__ (self): - if self.option_id: - return "option %s: %s" % (self.option_id, self.msg) - else: - return self.msg - -class OptionConflictError (OptionError): - """ - Raised if conflicting options are added to an OptionParser. - """ - -class OptionValueError (OptikError): - """ - Raised if an invalid option value is encountered on the command - line. - """ - -class BadOptionError (OptikError): - """ - Raised if an invalid or ambiguous option is seen on the command-line. - """ - - -class HelpFormatter: - - """ - Abstract base class for formatting option help. OptionParser - instances should use one of the HelpFormatter subclasses for - formatting help; by default IndentedHelpFormatter is used. - - Instance attributes: - indent_increment : int - the number of columns to indent per nesting level - max_help_position : int - the maximum starting column for option help text - help_position : int - the calculated starting column for option help text; - initially the same as the maximum - width : int - total number of columns for output - level : int - current indentation level - current_indent : int - current indentation level (in columns) - help_width : int - number of columns available for option help text (calculated) - """ - - def __init__ (self, - indent_increment, - max_help_position, - width, - short_first): - self.indent_increment = indent_increment - self.help_position = self.max_help_position = max_help_position - self.width = width - self.current_indent = 0 - self.level = 0 - self.help_width = width - max_help_position - self.short_first = short_first - - def indent (self): - self.current_indent += self.indent_increment - self.level += 1 - - def dedent (self): - self.current_indent -= self.indent_increment - assert self.current_indent >= 0, "Indent decreased below 0." - self.level -= 1 - - def format_usage (self, usage): - raise NotImplementedError, "subclasses must implement" - - def format_heading (self, heading): - raise NotImplementedError, "subclasses must implement" - - def format_description (self, description): - desc_width = self.width - self.current_indent - indent = " "*self.current_indent - return fill(description, desc_width, - initial_indent=indent, - subsequent_indent=indent) - - def format_option (self, option): - # The help for each option consists of two parts: - # * the opt strings and metavars - # eg. ("-x", or "-fFILENAME, --file=FILENAME") - # * the user-supplied help string - # eg. ("turn on expert mode", "read data from FILENAME") - # - # If possible, we write both of these on the same line: - # -x turn on expert mode - # - # But if the opt string list is too long, we put the help - # string on a second line, indented to the same column it would - # start in if it fit on the first line. - # -fFILENAME, --file=FILENAME - # read data from FILENAME - result = [] - opts = option.option_strings - opt_width = self.help_position - self.current_indent - 2 - if len(opts) > opt_width: - opts = "%*s%s\n" % (self.current_indent, "", opts) - indent_first = self.help_position - else: # start help on same line as opts - opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) - indent_first = 0 - result.append(opts) - if option.help: - help_lines = wrap(option.help, self.help_width) - result.append("%*s%s\n" % (indent_first, "", help_lines[0])) - result.extend(["%*s%s\n" % (self.help_position, "", line) - for line in help_lines[1:]]) - elif opts[-1] != "\n": - result.append("\n") - return "".join(result) - - def store_option_strings (self, parser): - self.indent() - max_len = 0 - for opt in parser.option_list: - strings = self.format_option_strings(opt) - opt.option_strings = strings - max_len = max(max_len, len(strings) + self.current_indent) - self.indent() - for group in parser.option_groups: - for opt in group.option_list: - strings = self.format_option_strings(opt) - opt.option_strings = strings - max_len = max(max_len, len(strings) + self.current_indent) - self.dedent() - self.dedent() - self.help_position = min(max_len + 2, self.max_help_position) - - def format_option_strings (self, option): - """Return a comma-separated list of option strings & metavariables.""" - if option.takes_value(): - metavar = option.metavar or option.dest.upper() - short_opts = [sopt + metavar for sopt in option._short_opts] - long_opts = [lopt + "=" + metavar for lopt in option._long_opts] - else: - short_opts = option._short_opts - long_opts = option._long_opts - - if self.short_first: - opts = short_opts + long_opts - else: - opts = long_opts + short_opts - - return ", ".join(opts) - -class IndentedHelpFormatter (HelpFormatter): - """Format help with indented section bodies. - """ - - def __init__ (self, - indent_increment=2, - max_help_position=24, - width=80, - short_first=1): - HelpFormatter.__init__( - self, indent_increment, max_help_position, width, short_first) - - def format_usage (self, usage): - return "usage: %s\n" % usage - - def format_heading (self, heading): - return "%*s%s:\n" % (self.current_indent, "", heading) - - -class TitledHelpFormatter (HelpFormatter): - """Format help with underlined section headers. - """ - - def __init__ (self, - indent_increment=0, - max_help_position=24, - width=80, - short_first=0): - HelpFormatter.__init__ ( - self, indent_increment, max_help_position, width, short_first) - - def format_usage (self, usage): - return "%s %s\n" % (self.format_heading("Usage"), usage) - - def format_heading (self, heading): - return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading)) -"""optik.option - -Defines the Option class and some standard value-checking functions. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17, GPW (from optik.py) - - -# Do the right thing with boolean values for all known Python versions. -try: - True, False -except NameError: - (True, False) = (1, 0) - -_builtin_cvt = { "int" : (int, "integer"), - "long" : (long, "long integer"), - "float" : (float, "floating-point"), - "complex" : (complex, "complex") } - -def check_builtin (option, opt, value): - (cvt, what) = _builtin_cvt[option.type] - try: - return cvt(value) - except ValueError: - raise OptionValueError( - #"%s: invalid %s argument %r" % (opt, what, value)) - "option %s: invalid %s value: %r" % (opt, what, value)) - -def check_choice(option, opt, value): - if value in option.choices: - return value - else: - choices = ", ".join(map(repr, option.choices)) - raise OptionValueError( - "option %s: invalid choice: %r (choose from %s)" - % (opt, value, choices)) - -# Not supplying a default is different from a default of None, -# so we need an explicit "not supplied" value. -NO_DEFAULT = "NO"+"DEFAULT" - - -class Option: - """ - Instance attributes: - _short_opts : [string] - _long_opts : [string] - - action : string - type : string - dest : string - default : any - nargs : int - const : any - choices : [string] - callback : function - callback_args : (any*) - callback_kwargs : { string : any } - help : string - metavar : string - """ - - # The list of instance attributes that may be set through - # keyword args to the constructor. - ATTRS = ['action', - 'type', - 'dest', - 'default', - 'nargs', - 'const', - 'choices', - 'callback', - 'callback_args', - 'callback_kwargs', - 'help', - 'metavar'] - - # The set of actions allowed by option parsers. Explicitly listed - # here so the constructor can validate its arguments. - ACTIONS = ("store", - "store_const", - "store_true", - "store_false", - "append", - "count", - "callback", - "help", - "version") - - # The set of actions that involve storing a value somewhere; - # also listed just for constructor argument validation. (If - # the action is one of these, there must be a destination.) - STORE_ACTIONS = ("store", - "store_const", - "store_true", - "store_false", - "append", - "count") - - # The set of actions for which it makes sense to supply a value - # type, ie. where we expect an argument to this option. - TYPED_ACTIONS = ("store", - "append", - "callback") - - # The set of known types for option parsers. Again, listed here for - # constructor argument validation. - TYPES = ("string", "int", "long", "float", "complex", "choice") - - # Dictionary of argument checking functions, which convert and - # validate option arguments according to the option type. - # - # Signature of checking functions is: - # check(option : Option, opt : string, value : string) -> any - # where - # option is the Option instance calling the checker - # opt is the actual option seen on the command-line - # (eg. "-a", "--file") - # value is the option argument seen on the command-line - # - # The return value should be in the appropriate Python type - # for option.type -- eg. an integer if option.type == "int". - # - # If no checker is defined for a type, arguments will be - # unchecked and remain strings. - TYPE_CHECKER = { "int" : check_builtin, - "long" : check_builtin, - "float" : check_builtin, - "complex" : check_builtin, - "choice" : check_choice, - } - - - # CHECK_METHODS is a list of unbound method objects; they are called - # by the constructor, in order, after all attributes are - # initialized. The list is created and filled in later, after all - # the methods are actually defined. (I just put it here because I - # like to define and document all class attributes in the same - # place.) Subclasses that add another _check_*() method should - # define their own CHECK_METHODS list that adds their check method - # to those from this class. - CHECK_METHODS = None - - - # -- Constructor/initialization methods ---------------------------- - - def __init__ (self, *opts, **attrs): - # Set _short_opts, _long_opts attrs from 'opts' tuple. - # Have to be set now, in case no option strings are supplied. - self._short_opts = [] - self._long_opts = [] - opts = self._check_opt_strings(opts) - self._set_opt_strings(opts) - - # Set all other attrs (action, type, etc.) from 'attrs' dict - self._set_attrs(attrs) - - # Check all the attributes we just set. There are lots of - # complicated interdependencies, but luckily they can be farmed - # out to the _check_*() methods listed in CHECK_METHODS -- which - # could be handy for subclasses! The one thing these all share - # is that they raise OptionError if they discover a problem. - for checker in self.CHECK_METHODS: - checker(self) - - def _check_opt_strings (self, opts): - # Filter out None because early versions of Optik had exactly - # one short option and one long option, either of which - # could be None. - opts = filter(None, opts) - if not opts: - raise TypeError("at least one option string must be supplied") - return opts - - def _set_opt_strings (self, opts): - for opt in opts: - if len(opt) < 2: - raise OptionError( - "invalid option string %r: " - "must be at least two characters long" % opt, self) - elif len(opt) == 2: - if not (opt[0] == "-" and opt[1] != "-"): - raise OptionError( - "invalid short option string %r: " - "must be of the form -x, (x any non-dash char)" % opt, - self) - self._short_opts.append(opt) - else: - if not (opt[0:2] == "--" and opt[2] != "-"): - raise OptionError( - "invalid long option string %r: " - "must start with --, followed by non-dash" % opt, - self) - self._long_opts.append(opt) - - def _set_attrs (self, attrs): - for attr in self.ATTRS: - if attrs.has_key(attr): - setattr(self, attr, attrs[attr]) - del attrs[attr] - else: - if attr == 'default': - setattr(self, attr, NO_DEFAULT) - else: - setattr(self, attr, None) - if attrs: - raise OptionError( - "invalid keyword arguments: %s" % ", ".join(attrs.keys()), - self) - - - # -- Constructor validation methods -------------------------------- - - def _check_action (self): - if self.action is None: - self.action = "store" - elif self.action not in self.ACTIONS: - raise OptionError("invalid action: %r" % self.action, self) - - def _check_type (self): - if self.type is None: - # XXX should factor out another class attr here: list of - # actions that *require* a type - if self.action in ("store", "append"): - if self.choices is not None: - # The "choices" attribute implies "choice" type. - self.type = "choice" - else: - # No type given? "string" is the most sensible default. - self.type = "string" - else: - if self.type not in self.TYPES: - raise OptionError("invalid option type: %r" % self.type, self) - if self.action not in self.TYPED_ACTIONS: - raise OptionError( - "must not supply a type for action %r" % self.action, self) - - def _check_choice(self): - if self.type == "choice": - if self.choices is None: - raise OptionError( - "must supply a list of choices for type 'choice'", self) - elif type(self.choices) not in (types.TupleType, types.ListType): - raise OptionError( - "choices must be a list of strings ('%s' supplied)" - % str(type(self.choices)).split("'")[1], self) - elif self.choices is not None: - raise OptionError( - "must not supply choices for type %r" % self.type, self) - - def _check_dest (self): - if self.action in self.STORE_ACTIONS and self.dest is None: - # No destination given, and we need one for this action. - # Glean a destination from the first long option string, - # or from the first short option string if no long options. - if self._long_opts: - # eg. "--foo-bar" -> "foo_bar" - self.dest = self._long_opts[0][2:].replace('-', '_') - else: - self.dest = self._short_opts[0][1] - - def _check_const (self): - if self.action != "store_const" and self.const is not None: - raise OptionError( - "'const' must not be supplied for action %r" % self.action, - self) - - def _check_nargs (self): - if self.action in self.TYPED_ACTIONS: - if self.nargs is None: - self.nargs = 1 - elif self.nargs is not None: - raise OptionError( - "'nargs' must not be supplied for action %r" % self.action, - self) - - def _check_callback (self): - if self.action == "callback": - if not callable(self.callback): - raise OptionError( - "callback not callable: %r" % self.callback, self) - if (self.callback_args is not None and - type(self.callback_args) is not types.TupleType): - raise OptionError( - "callback_args, if supplied, must be a tuple: not %r" - % self.callback_args, self) - if (self.callback_kwargs is not None and - type(self.callback_kwargs) is not types.DictType): - raise OptionError( - "callback_kwargs, if supplied, must be a dict: not %r" - % self.callback_kwargs, self) - else: - if self.callback is not None: - raise OptionError( - "callback supplied (%r) for non-callback option" - % self.callback, self) - if self.callback_args is not None: - raise OptionError( - "callback_args supplied for non-callback option", self) - if self.callback_kwargs is not None: - raise OptionError( - "callback_kwargs supplied for non-callback option", self) - - - CHECK_METHODS = [_check_action, - _check_type, - _check_choice, - _check_dest, - _check_const, - _check_nargs, - _check_callback] - - - # -- Miscellaneous methods ----------------------------------------- - - def __str__ (self): - return "/".join(self._short_opts + self._long_opts) - - def takes_value (self): - return self.type is not None - - - # -- Processing methods -------------------------------------------- - - def check_value (self, opt, value): - checker = self.TYPE_CHECKER.get(self.type) - if checker is None: - return value - else: - return checker(self, opt, value) - - def process (self, opt, value, values, parser): - - # First, convert the value(s) to the right type. Howl if any - # value(s) are bogus. - if value is not None: - if self.nargs == 1: - value = self.check_value(opt, value) - else: - value = tuple([self.check_value(opt, v) for v in value]) - - # And then take whatever action is expected of us. - # This is a separate method to make life easier for - # subclasses to add new actions. - return self.take_action( - self.action, self.dest, opt, value, values, parser) - - def take_action (self, action, dest, opt, value, values, parser): - if action == "store": - setattr(values, dest, value) - elif action == "store_const": - setattr(values, dest, self.const) - elif action == "store_true": - setattr(values, dest, True) - elif action == "store_false": - setattr(values, dest, False) - elif action == "append": - values.ensure_value(dest, []).append(value) - elif action == "count": - setattr(values, dest, values.ensure_value(dest, 0) + 1) - elif action == "callback": - args = self.callback_args or () - kwargs = self.callback_kwargs or {} - self.callback(self, opt, value, parser, *args, **kwargs) - elif action == "help": - parser.print_help() - sys.exit(0) - elif action == "version": - parser.print_version() - sys.exit(0) - else: - raise RuntimeError, "unknown action %r" % self.action - - return 1 - -# class Option -"""optik.option_parser - -Provides the OptionParser and Values classes. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17, GPW (from optik.py) - - - -def get_prog_name (): - return os.path.basename(sys.argv[0]) - - -SUPPRESS_HELP = "SUPPRESS"+"HELP" -SUPPRESS_USAGE = "SUPPRESS"+"USAGE" - -STD_HELP_OPTION = Option("-h", "--help", - action="help", - help="show this help message and exit") -STD_VERSION_OPTION = Option("--version", - action="version", - help="show program's version number and exit") - - -class Values: - - def __init__ (self, defaults=None): - if defaults: - for (attr, val) in defaults.items(): - setattr(self, attr, val) - - def __repr__ (self): - return ("<%s at 0x%x: %r>" - % (self.__class__.__name__, id(self), self.__dict__)) - - def _update_careful (self, dict): - """ - Update the option values from an arbitrary dictionary, but only - use keys from dict that already have a corresponding attribute - in self. Any keys in dict without a corresponding attribute - are silently ignored. - """ - for attr in dir(self): - if dict.has_key(attr): - dval = dict[attr] - if dval is not None: - setattr(self, attr, dval) - - def _update_loose (self, dict): - """ - Update the option values from an arbitrary dictionary, - using all keys from the dictionary regardless of whether - they have a corresponding attribute in self or not. - """ - self.__dict__.update(dict) - - def _update (self, dict, mode): - if mode == "careful": - self._update_careful(dict) - elif mode == "loose": - self._update_loose(dict) - else: - raise ValueError, "invalid update mode: %r" % mode - - def read_module (self, modname, mode="careful"): - __import__(modname) - mod = sys.modules[modname] - self._update(vars(mod), mode) - - def read_file (self, filename, mode="careful"): - vars = {} - execfile(filename, vars) - self._update(vars, mode) - - def ensure_value (self, attr, value): - if not hasattr(self, attr) or getattr(self, attr) is None: - setattr(self, attr, value) - return getattr(self, attr) - - -class OptionContainer: - - """ - Abstract base class. - - Class attributes: - standard_option_list : [Option] - list of standard options that will be accepted by all instances - of this parser class (intended to be overridden by subclasses). - - Instance attributes: - option_list : [Option] - the list of Option objects contained by this OptionContainer - _short_opt : { string : Option } - dictionary mapping short option strings, eg. "-f" or "-X", - to the Option instances that implement them. If an Option - has multiple short option strings, it will appears in this - dictionary multiple times. [1] - _long_opt : { string : Option } - dictionary mapping long option strings, eg. "--file" or - "--exclude", to the Option instances that implement them. - Again, a given Option can occur multiple times in this - dictionary. [1] - defaults : { string : any } - dictionary mapping option destination names to default - values for each destination [1] - - [1] These mappings are common to (shared by) all components of the - controlling OptionParser, where they are initially created. - - """ - - def __init__ (self, option_class, conflict_handler, description): - # Initialize the option list and related data structures. - # This method must be provided by subclasses, and it must - # initialize at least the following instance attributes: - # option_list, _short_opt, _long_opt, defaults. - self._create_option_list() - - self.option_class = option_class - self.set_conflict_handler(conflict_handler) - self.set_description(description) - - def _create_option_mappings (self): - # For use by OptionParser constructor -- create the master - # option mappings used by this OptionParser and all - # OptionGroups that it owns. - self._short_opt = {} # single letter -> Option instance - self._long_opt = {} # long option -> Option instance - self.defaults = {} # maps option dest -> default value - - - def _share_option_mappings (self, parser): - # For use by OptionGroup constructor -- use shared option - # mappings from the OptionParser that owns this OptionGroup. - self._short_opt = parser._short_opt - self._long_opt = parser._long_opt - self.defaults = parser.defaults - - def set_conflict_handler (self, handler): - if handler not in ("ignore", "error", "resolve"): - raise ValueError, "invalid conflict_resolution value %r" % handler - self.conflict_handler = handler - - def set_description (self, description): - self.description = description - - - # -- Option-adding methods ----------------------------------------- - - def _check_conflict (self, option): - conflict_opts = [] - for opt in option._short_opts: - if self._short_opt.has_key(opt): - conflict_opts.append((opt, self._short_opt[opt])) - for opt in option._long_opts: - if self._long_opt.has_key(opt): - conflict_opts.append((opt, self._long_opt[opt])) - - if conflict_opts: - handler = self.conflict_handler - if handler == "ignore": # behaviour for Optik 1.0, 1.1 - pass - elif handler == "error": # new in 1.2 - raise OptionConflictError( - "conflicting option string(s): %s" - % ", ".join([co[0] for co in conflict_opts]), - option) - elif handler == "resolve": # new in 1.2 - for (opt, c_option) in conflict_opts: - if opt.startswith("--"): - c_option._long_opts.remove(opt) - del self._long_opt[opt] - else: - c_option._short_opts.remove(opt) - del self._short_opt[opt] - if not (c_option._short_opts or c_option._long_opts): - c_option.container.option_list.remove(c_option) - - def add_option (self, *args, **kwargs): - """add_option(Option) - add_option(opt_str, ..., kwarg=val, ...) - """ - if type(args[0]) is types.StringType: - option = self.option_class(*args, **kwargs) - elif len(args) == 1 and not kwargs: - option = args[0] - if not isinstance(option, Option): - raise TypeError, "not an Option instance: %r" % option - else: - raise TypeError, "invalid arguments" - - self._check_conflict(option) - - self.option_list.append(option) - option.container = self - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - if option.dest is not None: # option has a dest, we need a default - if option.default is not NO_DEFAULT: - self.defaults[option.dest] = option.default - elif not self.defaults.has_key(option.dest): - self.defaults[option.dest] = None - - return option - - def add_options (self, option_list): - for option in option_list: - self.add_option(option) - - # -- Option query/removal methods ---------------------------------- - - def get_option (self, opt_str): - return (self._short_opt.get(opt_str) or - self._long_opt.get(opt_str)) - - def has_option (self, opt_str): - return (self._short_opt.has_key(opt_str) or - self._long_opt.has_key(opt_str)) - - def remove_option (self, opt_str): - option = self._short_opt.get(opt_str) - if option is None: - option = self._long_opt.get(opt_str) - if option is None: - raise ValueError("no such option %r" % opt_str) - - for opt in option._short_opts: - del self._short_opt[opt] - for opt in option._long_opts: - del self._long_opt[opt] - option.container.option_list.remove(option) - - - # -- Help-formatting methods --------------------------------------- - - def format_option_help (self, formatter): - if not self.option_list: - return "" - result = [] - for option in self.option_list: - if not option.help is SUPPRESS_HELP: - result.append(formatter.format_option(option)) - return "".join(result) - - def format_description (self, formatter): - if self.description: - return formatter.format_description(self.description) - else: - return "" - - def format_help (self, formatter): - if self.description: - desc = self.format_description(formatter) + "\n" - else: - desc = "" - return desc + self.format_option_help(formatter) - - -class OptionGroup (OptionContainer): - - def __init__ (self, parser, title, description=None): - self.parser = parser - OptionContainer.__init__( - self, parser.option_class, parser.conflict_handler, description) - self.title = title - - def _create_option_list (self): - self.option_list = [] - self._share_option_mappings(self.parser) - - def set_title (self, title): - self.title = title - - # -- Help-formatting methods --------------------------------------- - - def format_help (self, formatter): - result = formatter.format_heading(self.title) - formatter.indent() - result += OptionContainer.format_help(self, formatter) - formatter.dedent() - return result - - -class OptionParser (OptionContainer): - - """ - Class attributes: - standard_option_list : [Option] - list of standard options that will be accepted by all instances - of this parser class (intended to be overridden by subclasses). - - Instance attributes: - usage : string - a usage string for your program. Before it is displayed - to the user, "%prog" will be expanded to the name of - your program (self.prog or os.path.basename(sys.argv[0])). - prog : string - the name of the current program (to override - os.path.basename(sys.argv[0])). - - allow_interspersed_args : boolean = true - if true, positional arguments may be interspersed with options. - Assuming -a and -b each take a single argument, the command-line - -ablah foo bar -bboo baz - will be interpreted the same as - -ablah -bboo -- foo bar baz - If this flag were false, that command line would be interpreted as - -ablah -- foo bar -bboo baz - -- ie. we stop processing options as soon as we see the first - non-option argument. (This is the tradition followed by - Python's getopt module, Perl's Getopt::Std, and other argument- - parsing libraries, but it is generally annoying to users.) - - rargs : [string] - the argument list currently being parsed. Only set when - parse_args() is active, and continually trimmed down as - we consume arguments. Mainly there for the benefit of - callback options. - largs : [string] - the list of leftover arguments that we have skipped while - parsing options. If allow_interspersed_args is false, this - list is always empty. - values : Values - the set of option values currently being accumulated. Only - set when parse_args() is active. Also mainly for callbacks. - - Because of the 'rargs', 'largs', and 'values' attributes, - OptionParser is not thread-safe. If, for some perverse reason, you - need to parse command-line arguments simultaneously in different - threads, use different OptionParser instances. - - """ - - standard_option_list = [] - - def __init__ (self, - usage=None, - option_list=None, - option_class=Option, - version=None, - conflict_handler="error", - description=None, - formatter=None, - add_help_option=1, - prog=None): - OptionContainer.__init__( - self, option_class, conflict_handler, description) - self.set_usage(usage) - self.prog = prog - self.version = version - self.allow_interspersed_args = 1 - if formatter is None: - formatter = IndentedHelpFormatter() - self.formatter = formatter - - # Populate the option list; initial sources are the - # standard_option_list class attribute, the 'option_list' - # argument, and the STD_VERSION_OPTION (if 'version' supplied) - # and STD_HELP_OPTION globals. - self._populate_option_list(option_list, - add_help=add_help_option) - - self._init_parsing_state() - - # -- Private methods ----------------------------------------------- - # (used by our or OptionContainer's constructor) - - def _create_option_list (self): - self.option_list = [] - self.option_groups = [] - self._create_option_mappings() - - def _populate_option_list (self, option_list, add_help=1): - if self.standard_option_list: - self.add_options(self.standard_option_list) - if option_list: - self.add_options(option_list) - if self.version: - self.add_option(STD_VERSION_OPTION) - if add_help: - self.add_option(STD_HELP_OPTION) - - def _init_parsing_state (self): - # These are set in parse_args() for the convenience of callbacks. - self.rargs = None - self.largs = None - self.values = None - - - # -- Simple modifier methods --------------------------------------- - - def set_usage (self, usage): - if usage is None: - self.usage = "%prog [options]" - elif usage is SUPPRESS_USAGE: - self.usage = None - elif usage.startswith("usage: "): - # for backwards compatibility with Optik 1.3 and earlier - self.usage = usage[7:] - else: - self.usage = usage - - def enable_interspersed_args (self): - self.allow_interspersed_args = 1 - - def disable_interspersed_args (self): - self.allow_interspersed_args = 0 - - def set_default (self, dest, value): - self.defaults[dest] = value - - def set_defaults (self, **kwargs): - self.defaults.update(kwargs) - - def get_default_values (self): - return Values(self.defaults) - - - # -- OptionGroup methods ------------------------------------------- - - def add_option_group (self, *args, **kwargs): - # XXX lots of overlap with OptionContainer.add_option() - if type(args[0]) is types.StringType: - group = OptionGroup(self, *args, **kwargs) - elif len(args) == 1 and not kwargs: - group = args[0] - if not isinstance(group, OptionGroup): - raise TypeError, "not an OptionGroup instance: %r" % group - if group.parser is not self: - raise ValueError, "invalid OptionGroup (wrong parser)" - else: - raise TypeError, "invalid arguments" - - self.option_groups.append(group) - return group - - def get_option_group (self, opt_str): - option = (self._short_opt.get(opt_str) or - self._long_opt.get(opt_str)) - if option and option.container is not self: - return option.container - return None - - - # -- Option-parsing methods ---------------------------------------- - - def _get_args (self, args): - if args is None: - return sys.argv[1:] - else: - return args[:] # don't modify caller's list - - def parse_args (self, args=None, values=None): - """ - parse_args(args : [string] = sys.argv[1:], - values : Values = None) - -> (values : Values, args : [string]) - - Parse the command-line options found in 'args' (default: - sys.argv[1:]). Any errors result in a call to 'error()', which - by default prints the usage message to stderr and calls - sys.exit() with an error message. On success returns a pair - (values, args) where 'values' is an Values instance (with all - your option values) and 'args' is the list of arguments left - over after parsing options. - """ - rargs = self._get_args(args) - if values is None: - values = self.get_default_values() - - # Store the halves of the argument list as attributes for the - # convenience of callbacks: - # rargs - # the rest of the command-line (the "r" stands for - # "remaining" or "right-hand") - # largs - # the leftover arguments -- ie. what's left after removing - # options and their arguments (the "l" stands for "leftover" - # or "left-hand") - self.rargs = rargs - self.largs = largs = [] - self.values = values - - try: - stop = self._process_args(largs, rargs, values) - except (BadOptionError, OptionValueError), err: - self.error(err.msg) - - args = largs + rargs - return self.check_values(values, args) - - def check_values (self, values, args): - """ - check_values(values : Values, args : [string]) - -> (values : Values, args : [string]) - - Check that the supplied option values and leftover arguments are - valid. Returns the option values and leftover arguments - (possibly adjusted, possibly completely new -- whatever you - like). Default implementation just returns the passed-in - values; subclasses may override as desired. - """ - return (values, args) - - def _process_args (self, largs, rargs, values): - """_process_args(largs : [string], - rargs : [string], - values : Values) - - Process command-line arguments and populate 'values', consuming - options and arguments from 'rargs'. If 'allow_interspersed_args' is - false, stop at the first non-option argument. If true, accumulate any - interspersed non-option arguments in 'largs'. - """ - while rargs: - arg = rargs[0] - # We handle bare "--" explicitly, and bare "-" is handled by the - # standard arg handler since the short arg case ensures that the - # len of the opt string is greater than 1. - if arg == "--": - del rargs[0] - return - elif arg[0:2] == "--": - # process a single long option (possibly with value(s)) - self._process_long_opt(rargs, values) - elif arg[:1] == "-" and len(arg) > 1: - # process a cluster of short options (possibly with - # value(s) for the last one only) - self._process_short_opts(rargs, values) - elif self.allow_interspersed_args: - largs.append(arg) - del rargs[0] - else: - return # stop now, leave this arg in rargs - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt (self, opt): - """_match_long_opt(opt : string) -> string - - Determine which long option string 'opt' matches, ie. which one - it is an unambiguous abbrevation for. Raises BadOptionError if - 'opt' doesn't unambiguously match any long option string. - """ - return _match_abbrev(opt, self._long_opt) - - def _process_long_opt (self, rargs, values): - arg = rargs.pop(0) - - # Value explicitly attached to arg? Pretend it's the next - # argument. - if "=" in arg: - (opt, next_arg) = arg.split("=", 1) - rargs.insert(0, next_arg) - had_explicit_value = 1 - else: - opt = arg - had_explicit_value = 0 - - opt = self._match_long_opt(opt) - option = self._long_opt[opt] - if option.takes_value(): - nargs = option.nargs - if len(rargs) < nargs: - if nargs == 1: - self.error("%s option requires a value" % opt) - else: - self.error("%s option requires %d values" - % (opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - elif had_explicit_value: - self.error("%s option does not take a value" % opt) - - else: - value = None - - option.process(opt, value, values, self) - - def _process_short_opts (self, rargs, values): - arg = rargs.pop(0) - stop = 0 - i = 1 - for ch in arg[1:]: - opt = "-" + ch - option = self._short_opt.get(opt) - i += 1 # we have consumed a character - - if not option: - self.error("no such option: %s" % opt) - if option.takes_value(): - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - rargs.insert(0, arg[i:]) - stop = 1 - - nargs = option.nargs - if len(rargs) < nargs: - if nargs == 1: - self.error("%s option requires a value" % opt) - else: - self.error("%s option requires %s values" - % (opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - else: # option doesn't take a value - value = None - - option.process(opt, value, values, self) - - if stop: - break - - - # -- Feedback methods ---------------------------------------------- - - def error (self, msg): - """error(msg : string) - - Print a usage message incorporating 'msg' to stderr and exit. - If you override this in a subclass, it should not return -- it - should either exit or raise an exception. - """ - self.print_usage(sys.stderr) - sys.exit("%s: error: %s" % (get_prog_name(), msg)) - - def get_usage (self): - if self.usage: - return self.formatter.format_usage( - self.usage.replace("%prog", get_prog_name())) - else: - return "" - - def print_usage (self, file=None): - """print_usage(file : file = stdout) - - Print the usage message for the current program (self.usage) to - 'file' (default stdout). Any occurence of the string "%prog" in - self.usage is replaced with the name of the current program - (basename of sys.argv[0]). Does nothing if self.usage is empty - or not defined. - """ - if self.usage: - print >>file, self.get_usage() - - def get_version (self): - if self.version: - return self.version.replace("%prog", get_prog_name()) - else: - return "" - - def print_version (self, file=None): - """print_version(file : file = stdout) - - Print the version message for this program (self.version) to - 'file' (default stdout). As with print_usage(), any occurence - of "%prog" in self.version is replaced by the current program's - name. Does nothing if self.version is empty or undefined. - """ - if self.version: - print >>file, self.get_version() - - def format_option_help (self, formatter=None): - if formatter is None: - formatter = self.formatter - formatter.store_option_strings(self) - result = [] - result.append(formatter.format_heading("options")) - formatter.indent() - if self.option_list: - result.append(OptionContainer.format_option_help(self, formatter)) - result.append("\n") - for group in self.option_groups: - result.append(group.format_help(formatter)) - result.append("\n") - formatter.dedent() - # Drop the last "\n", or the header if no options or option groups: - return "".join(result[:-1]) - - def format_help (self, formatter=None): - if formatter is None: - formatter = self.formatter - result = [] - if self.usage: - result.append(self.get_usage() + "\n") - if self.description: - result.append(self.format_description(formatter) + "\n") - result.append(self.format_option_help(formatter)) - return "".join(result) - - def print_help (self, file=None): - """print_help(file : file = stdout) - - Print an extended help message, listing all options and any - help text provided with them, to 'file' (default stdout). - """ - if file is None: - file = sys.stdout - file.write(self.format_help()) - -# class OptionParser - - -def _match_abbrev (s, wordmap): - """_match_abbrev(s : string, wordmap : {string : Option}) -> string - - Return the string key in 'wordmap' for which 's' is an unambiguous - abbreviation. If 's' is found to be ambiguous or doesn't match any of - 'words', raise BadOptionError. - """ - # Is there an exact match? - if wordmap.has_key(s): - return s - else: - # Isolate all words with s as a prefix. - possibilities = [word for word in wordmap.keys() - if word.startswith(s)] - # No exact match, so there had better be just one possibility. - if len(possibilities) == 1: - return possibilities[0] - elif not possibilities: - raise BadOptionError("no such option: %s" % s) - else: - # More than one possible completion: ambiguous prefix. - raise BadOptionError("ambiguous option: %s (%s?)" - % (s, ", ".join(possibilities))) -"""Text wrapping and filling. -""" - -# Copyright (C) 1999-2001 Gregory P. Ward. -# Copyright (C) 2002, 2003 Python Software Foundation. -# Written by Greg Ward - - -# Do the right thing with boolean values for all known Python versions. -try: - True, False -except NameError: - (True, False) = (1, 0) - -class TextWrapper: - """ - Object for wrapping/filling text. The public interface consists of - the wrap() and fill() methods; the other methods are just there for - subclasses to override in order to tweak the default behaviour. - If you want to completely replace the main wrapping algorithm, - you'll probably have to override _wrap_chunks(). - - Several instance attributes control various aspects of wrapping: - width (default: 70) - the maximum width of wrapped lines (unless break_long_words - is false) - initial_indent (default: "") - string that will be prepended to the first line of wrapped - output. Counts towards the line's width. - subsequent_indent (default: "") - string that will be prepended to all lines save the first - of wrapped output; also counts towards each line's width. - expand_tabs (default: true) - Expand tabs in input text to spaces before further processing. - Each tab will become 1 .. 8 spaces, depending on its position in - its line. If false, each tab is treated as a single character. - replace_whitespace (default: true) - Replace all whitespace characters in the input text by spaces - after tab expansion. Note that if expand_tabs is false and - replace_whitespace is true, every tab will be converted to a - single space! - fix_sentence_endings (default: false) - Ensure that sentence-ending punctuation is always followed - by two spaces. Off by default becaus the algorithm is - (unavoidably) imperfect. - break_long_words (default: true) - Break words longer than 'width'. If false, those words will not - be broken, and some lines might be longer than 'width'. - """ - - whitespace_trans = string.maketrans(string.whitespace, - ' ' * len(string.whitespace)) - - # This funky little regex is just the trick for splitting - # text up into word-wrappable chunks. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! - # (after stripping out empty strings). - wordsep_re = re.compile(r'(\s+|' # any whitespace - r'-*\w{2,}-(?=\w{2,})|' # hyphenated words - r'(?<=\S)-{2,}(?=\w))') # em-dash - - # XXX will there be a locale-or-charset-aware version of - # string.lowercase in 2.3? - sentence_end_re = re.compile(r'[%s]' # lowercase letter - r'[\.\!\?]' # sentence-ending punct. - r'[\"\']?' # optional end-of-quote - % string.lowercase) - - - def __init__ (self, - width=70, - initial_indent="", - subsequent_indent="", - expand_tabs=True, - replace_whitespace=True, - fix_sentence_endings=False, - break_long_words=True): - self.width = width - self.initial_indent = initial_indent - self.subsequent_indent = subsequent_indent - self.expand_tabs = expand_tabs - self.replace_whitespace = replace_whitespace - self.fix_sentence_endings = fix_sentence_endings - self.break_long_words = break_long_words - - - # -- Private methods ----------------------------------------------- - # (possibly useful for subclasses to override) - - def _munge_whitespace(self, text): - """_munge_whitespace(text : string) -> string - - Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" - becomes " foo bar baz". - """ - if self.expand_tabs: - text = text.expandtabs() - if self.replace_whitespace: - text = text.translate(self.whitespace_trans) - return text - - - def _split(self, text): - """_split(text : string) -> [string] - - Split the text to wrap into indivisible chunks. Chunks are - not quite the same as words; see wrap_chunks() for full - details. As an example, the text - Look, goof-ball -- use the -b option! - breaks into the following chunks: - 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', 'option!' - """ - chunks = self.wordsep_re.split(text) - chunks = filter(None, chunks) - return chunks - - def _fix_sentence_endings(self, chunks): - """_fix_sentence_endings(chunks : [string]) - - Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() - and split() will convert that to [..., "foo.", " ", "Bar", ...] - which has one too few spaces; this method simply changes the one - space to two. - """ - i = 0 - pat = self.sentence_end_re - while i < len(chunks)-1: - if chunks[i+1] == " " and pat.search(chunks[i]): - chunks[i+1] = " " - i += 2 - else: - i += 1 - - def _handle_long_word(self, chunks, cur_line, cur_len, width): - """_handle_long_word(chunks : [string], - cur_line : [string], - cur_len : int, width : int) - - Handle a chunk of text (most likely a word, not whitespace) that - is too long to fit in any line. - """ - space_left = width - cur_len - - # If we're allowed to break long words, then do so: put as much - # of the next chunk onto the current line as will fit. - if self.break_long_words: - cur_line.append(chunks[0][0:space_left]) - chunks[0] = chunks[0][space_left:] - - # Otherwise, we have to preserve the long word intact. Only add - # it to the current line if there's nothing already there -- - # that minimizes how much we violate the width constraint. - elif not cur_line: - cur_line.append(chunks.pop(0)) - - # If we're not allowed to break long words, and there's already - # text on the current line, do nothing. Next time through the - # main loop of _wrap_chunks(), we'll wind up here again, but - # cur_len will be zero, so the next line will be entirely - # devoted to the long word that we can't handle right now. - - def _wrap_chunks(self, chunks): - """_wrap_chunks(chunks : [string]) -> [string] - - Wrap a sequence of text chunks and return a list of lines of - length 'self.width' or less. (If 'break_long_words' is false, - some lines may be longer than this.) Chunks correspond roughly - to words and the whitespace between them: each chunk is - indivisible (modulo 'break_long_words'), but a line break can - come between any two chunks. Chunks should not have internal - whitespace; ie. a chunk is either all whitespace or a "word". - Whitespace chunks will be removed from the beginning and end of - lines, but apart from that whitespace is preserved. - """ - lines = [] - - while chunks: - - # Start the list of chunks that will make up the current line. - # cur_len is just the length of all the chunks in cur_line. - cur_line = [] - cur_len = 0 - - # Figure out which static string will prefix this line. - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - # Maximum width for this line. - width = self.width - len(indent) - - # First chunk on line is whitespace -- drop it. - if chunks[0].strip() == '': - del chunks[0] - - while chunks: - l = len(chunks[0]) - - # Can at least squeeze this chunk onto the current line. - if cur_len + l <= width: - cur_line.append(chunks.pop(0)) - cur_len += l - - # Nope, this line is full. - else: - break - - # The current line is full, and the next chunk is too big to - # fit on *any* line (not just this one). - if chunks and len(chunks[0]) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - - # If the last chunk on this line is all whitespace, drop it. - if cur_line and cur_line[-1].strip() == '': - del cur_line[-1] - - # Convert current line back to a string and store it in list - # of all lines (return value). - if cur_line: - lines.append(indent + ''.join(cur_line)) - - return lines - - - # -- Public interface ---------------------------------------------- - - def wrap(self, text): - """wrap(text : string) -> [string] - - Reformat the single paragraph in 'text' so it fits in lines of - no more than 'self.width' columns, and return a list of wrapped - lines. Tabs in 'text' are expanded with string.expandtabs(), - and all other whitespace characters (including newline) are - converted to space. - """ - text = self._munge_whitespace(text) - indent = self.initial_indent - if len(text) + len(indent) <= self.width: - return [indent + text] - chunks = self._split(text) - if self.fix_sentence_endings: - self._fix_sentence_endings(chunks) - return self._wrap_chunks(chunks) - - def fill(self, text): - """fill(text : string) -> string - - Reformat the single paragraph in 'text' to fit in lines of no - more than 'self.width' columns, and return a new string - containing the entire wrapped paragraph. - """ - return "\n".join(self.wrap(text)) - - -# -- Convenience interface --------------------------------------------- - -def wrap(text, width=70, **kwargs): - """Wrap a single paragraph of text, returning a list of wrapped lines. - - Reformat the single paragraph in 'text' so it fits in lines of no - more than 'width' columns, and return a list of wrapped lines. By - default, tabs in 'text' are expanded with string.expandtabs(), and - all other whitespace characters (including newline) are converted to - space. See TextWrapper class for available keyword args to customize - wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.wrap(text) - -def fill(text, width=70, **kwargs): - """Fill a single paragraph of text, returning a new string. - - Reformat the single paragraph in 'text' to fit in lines of no more - than 'width' columns, and return a new string containing the entire - wrapped paragraph. As with wrap(), tabs are expanded and other - whitespace characters converted to space. See TextWrapper class for - available keyword args to customize wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.fill(text) - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -__version__ = "1.4.1" - - - - -# Some day, there might be many Option classes. As of Optik 1.3, the -# preferred way to instantiate Options is indirectly, via make_option(), -# which will become a factory function when there are many Option -# classes. -make_option = Option Modified: pypy/branch/pypy-newobjspace/tool/option.py ============================================================================== --- pypy/branch/pypy-newobjspace/tool/option.py (original) +++ pypy/branch/pypy-newobjspace/tool/option.py Thu Jul 28 16:29:10 2005 @@ -2,8 +2,8 @@ # XXX needs clean-up and reorganization. import os -from pypy.tool import optik -make_option = optik.make_option +import optparse +make_option = optparse.make_option class Options: showwarning = 0 @@ -71,7 +71,7 @@ def process_options(optionlist, input_options, argv=None): global Options Options = input_options - op = optik.OptionParser() + op = optparse.OptionParser() op.add_options(optionlist) options, args = op.parse_args(argv, input_options) return args From cfbolz at codespeak.net Thu Jul 28 16:33:34 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 16:33:34 +0200 (CEST) Subject: [pypy-svn] r15255 - in pypy/dist/pypy: annotation module/sys Message-ID: <20050728143334.DFEFA27B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 16:33:32 2005 New Revision: 15255 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/vm.py Log: removed getrefcount from our sys module since we couldn't find an obvious way to implement it (even with strange things in the backend). Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu Jul 28 16:33:32 2005 @@ -275,7 +275,6 @@ # this one is needed otherwise when annotating assert in a test we may try to annotate # py.test AssertionError.__init__ . BUILTIN_ANALYZERS[AssertionError.__init__.im_func] = exception_init -BUILTIN_ANALYZERS[sys.getrefcount] = count BUILTIN_ANALYZERS[sys.getdefaultencoding] = conf import unicodedata BUILTIN_ANALYZERS[unicodedata.decimal] = unicodedata_decimal # xxx Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Thu Jul 28 16:33:32 2005 @@ -35,7 +35,6 @@ 'builtin_module_names' : 'state.get(space).w_builtin_module_names', 'pypy_getudir' : 'state.pypy_getudir', - 'getrefcount' : 'vm.getrefcount', '_getframe' : 'vm._getframe', 'setrecursionlimit' : 'vm.setrecursionlimit', 'getrecursionlimit' : 'vm.getrecursionlimit', Modified: pypy/dist/pypy/module/sys/vm.py ============================================================================== --- pypy/dist/pypy/module/sys/vm.py (original) +++ pypy/dist/pypy/module/sys/vm.py Thu Jul 28 16:33:32 2005 @@ -83,15 +83,15 @@ from pypy.tool.udir import udir return space.wrap(str(udir)) -def getrefcount(space, w_obj): - """getrefcount(object) -> integer - Return the reference count of object. The count returned is generally - one higher than you might expect, because it includes the (temporary) - reference as an argument to getrefcount(). - """ - # From the results i get when using this i need to apply a fudge - # value of 6 to get results comparable to cpythons. /Arre - return space.wrap(sys.getrefcount(w_obj) - 6) +## def getrefcount(space, w_obj): +## """getrefcount(object) -> integer +## Return the reference count of object. The count returned is generally +## one higher than you might expect, because it includes the (temporary) +## reference as an argument to getrefcount(). +## """ +## # From the results i get when using this i need to apply a fudge +## # value of 6 to get results comparable to cpythons. /Arre +## return space.wrap(sys.getrefcount(w_obj) - 6) def settrace(space, w_func): """settrace(function) From cfbolz at codespeak.net Thu Jul 28 16:45:28 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 16:45:28 +0200 (CEST) Subject: [pypy-svn] r15256 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050728144528.AA57C27B83@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 16:45:26 2005 New Revision: 15256 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py Log: (arigo, cfbolz): changed grammar to not use negative slice starts. Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Thu Jul 28 16:45:26 2005 @@ -157,7 +157,9 @@ def sequence(self, rule, source, elts_number): """ """ items = [] - for node in self.stack[-elts_number:]: + slice_start = len(self.stack) - elts_number + assert slice_start >= 0 + for node in self.stack[slice_start:]: items += node.expand() is_root = rule.is_root() # replace N elements with 1 element regrouping them @@ -166,7 +168,7 @@ elem = SyntaxNode(rule.codename, items, source.current_lineno()) else: elem = TempSyntaxNode(rule.codename, items, source.current_lineno()) - del self.stack[-elts_number:] + del self.stack[slice_start:] self.stack.append(elem) elif elts_number == 0: if is_root: From arigo at codespeak.net Thu Jul 28 16:55:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 16:55:14 +0200 (CEST) Subject: [pypy-svn] r15257 - pypy/dist/pypy/rpython Message-ID: <20050728145514.308AA27B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 16:55:11 2005 New Revision: 15257 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Comment out this warning. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jul 28 16:55:11 2005 @@ -77,7 +77,7 @@ def add_pendingsetup(self, repr): assert isinstance(repr, Repr) if repr in self._seen_reprs_must_call_setup: - warning("ignoring already seen repr for setup: %r" %(repr,)) + #warning("ignoring already seen repr for setup: %r" %(repr,)) return self._reprs_must_call_setup.append(repr) self._seen_reprs_must_call_setup[repr] = True From hpk at codespeak.net Thu Jul 28 17:12:17 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 17:12:17 +0200 (CEST) Subject: [pypy-svn] r15259 - pypy/branch/pypy-newobjspace/objspace/std/test Message-ID: <20050728151217.6865027B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 17:12:16 2005 New Revision: 15259 Removed: pypy/branch/pypy-newobjspace/objspace/std/test/test_fake.py Log: remove nonsensical test Deleted: /pypy/branch/pypy-newobjspace/objspace/std/test/test_fake.py ============================================================================== --- /pypy/branch/pypy-newobjspace/objspace/std/test/test_fake.py Thu Jul 28 17:12:16 2005 +++ (empty file) @@ -1,14 +0,0 @@ -# test the integration of unicode and strings (even though we don't -# really implement unicode yet). - -import autopath, sys - - -objspacename = 'std' - -class AppTestFakedTypes: - def test_inheriting(self): - class MyUnicode(unicode): - pass - my_u = MyUnicode('123') - assert type(my_u) is MyUnicode From cfbolz at codespeak.net Thu Jul 28 17:20:52 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 17:20:52 +0200 (CEST) Subject: [pypy-svn] r15260 - pypy/dist/pypy/rpython Message-ID: <20050728152052.BD03B27B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 17:20:51 2005 New Revision: 15260 Modified: pypy/dist/pypy/rpython/rstr.py Log: try to give a more helpful error message Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jul 28 17:20:51 2005 @@ -317,7 +317,7 @@ vchunk = hop.gendirectcall(rint.ll_int2oct, vitem, inputconst(Bool, False)) else: - assert 0 + raise TyperError, "%%%s is not RPython" % (code, ) else: vchunk = inputconst(string_repr, thing) i = inputconst(Signed, i) From hpk at codespeak.net Thu Jul 28 17:32:49 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 17:32:49 +0200 (CEST) Subject: [pypy-svn] r15262 - in pypy/branch/pypy-newobjspace: . objspace/flow/test objspace/std/test objspace/test rpython/test translator/c/test translator/java/test translator/pyrex/test translator/test Message-ID: <20050728153249.114EC27B88@code1.codespeak.net> Author: hpk Date: Thu Jul 28 17:32:38 2005 New Revision: 15262 Modified: pypy/branch/pypy-newobjspace/conftest.py pypy/branch/pypy-newobjspace/objspace/flow/test/test_framestate.py pypy/branch/pypy-newobjspace/objspace/flow/test/test_model.py pypy/branch/pypy-newobjspace/objspace/flow/test/test_objspace.py pypy/branch/pypy-newobjspace/objspace/std/test/test_boolobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_dictobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_dictproxy.py pypy/branch/pypy-newobjspace/objspace/std/test/test_floatobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_instmethobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_intobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_iterobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_listobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_longobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_noneobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_sliceobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_stdobjspace.py pypy/branch/pypy-newobjspace/objspace/std/test/test_stringformat.py pypy/branch/pypy-newobjspace/objspace/std/test/test_stringobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_strutil.py pypy/branch/pypy-newobjspace/objspace/std/test/test_tupleobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_typeobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_unicodeobject.py pypy/branch/pypy-newobjspace/objspace/std/test/test_userobject.py pypy/branch/pypy-newobjspace/objspace/test/test_descriptor.py pypy/branch/pypy-newobjspace/objspace/test/test_thunkobjspace.py pypy/branch/pypy-newobjspace/rpython/test/test_llann.py pypy/branch/pypy-newobjspace/rpython/test/test_rarithmetic.py pypy/branch/pypy-newobjspace/translator/c/test/test_lltyped.py pypy/branch/pypy-newobjspace/translator/c/test/test_notype.py pypy/branch/pypy-newobjspace/translator/c/test/test_operation.py pypy/branch/pypy-newobjspace/translator/java/test/for_now_dont_test_javatrans.py pypy/branch/pypy-newobjspace/translator/pyrex/test/test_pyrextrans.py pypy/branch/pypy-newobjspace/translator/test/test_annrpython.py pypy/branch/pypy-newobjspace/translator/test/test_cltrans.py Log: simplify test objspace creation and access - there is no 'objspacename' magic anymore, neither at global nor at class/instance level - you can now basically only specify 'std' or 'thunk' via py.test - anythin more special you need to setup yourself in appropriate setup_* methods. Modified: pypy/branch/pypy-newobjspace/conftest.py ============================================================================== --- pypy/branch/pypy-newobjspace/conftest.py (original) +++ pypy/branch/pypy-newobjspace/conftest.py Thu Jul 28 17:32:38 2005 @@ -18,12 +18,16 @@ option = py.test.Config.addoptions("pypy options", Option('-O', '--objspace', action="store", default=None, - type="string", dest="objspacename", + type="string", dest="objspace", help="object space to run tests on."), Option('--oldstyle', action="store_true",dest="oldstyle", default=False, - help="enable oldstyle classes as default metaclass (std objspace only)"), - Option('--file', action="store_true",dest="uselibfile", default=False, - help="enable our custom file implementation"), + help="enable oldstyle classes as default metaclass"), + Option('--uselibfile', action="store_true", + dest="uselibfile", default=False, + help="enable our applevel file implementation"), + Option('--nofaking', action="store_true", + dest="nofaking", default=False, + help="avoid faking of modules and objects completely."), Option('--allpypy', action="store_true",dest="allpypy", default=False, help="run everything possible on top of PyPy."), ) @@ -31,24 +35,17 @@ def getobjspace(name=None, _spacecache={}): """ helper for instantiating and caching space's for testing. """ - if name is None: - name = option.objspacename - if name is None: - name = py.std.os.environ.get('OBJSPACE', 'std') - else: - optionname = option.objspacename - if optionname is not None and optionname != name: - return None + name = name or option.objspace or 'std' try: return _spacecache[name] except KeyError: - import pypy.tool.option - spaceoptions = pypy.tool.option.Options() - spaceoptions.uselibfile = option.uselibfile - #py.magic.invoke(compile=True) - module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) + assert name in ('std', 'thunk'), name + from pypy.objspace.std import Space try: - space = module.Space(spaceoptions) + space = Space(uselibfile=option.uselibfile, + nofaking=option.nofaking, + oldstyle=option.oldstyle, + ) except KeyboardInterrupt: raise except OperationError, e: @@ -64,17 +61,14 @@ traceback.print_exc() py.test.fail("fatal: cannot initialize objspace: %r" %(module.Space,)) _spacecache[name] = space - if name == 'std' and option.oldstyle: - space.enable_old_style_classes_as_default_metaclass() - if name != 'flow': # not sensible for flow objspace case - space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), - appsupport.build_pytest_assertion(space)) - space.setitem(space.builtin.w_dict, space.wrap('raises'), - space.wrap(appsupport.app_raises)) - space.setitem(space.builtin.w_dict, space.wrap('skip'), - space.wrap(appsupport.app_skip)) - space.raises_w = appsupport.raises_w.__get__(space) - space.eq_w = appsupport.eq_w.__get__(space) + space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), + appsupport.build_pytest_assertion(space)) + space.setitem(space.builtin.w_dict, space.wrap('raises'), + space.wrap(appsupport.app_raises)) + space.setitem(space.builtin.w_dict, space.wrap('skip'), + space.wrap(appsupport.app_skip)) + space.raises_w = appsupport.raises_w.__get__(space) + space.eq_w = appsupport.eq_w.__get__(space) return space # @@ -142,8 +136,7 @@ def execute(self, target, *args): co = target.func_code if 'space' in co.co_varnames[:co.co_argcount]: - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) + space = gettestobjspace() target(space, *args) else: target(*args) @@ -157,8 +150,7 @@ class AppTestFunction(PyPyTestFunction): def execute(self, target, *args): assert not args - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) + space = gettestobjspace() func = app2interp_temp(target) print "executing", func self.execute_appex(space, func, space) @@ -175,11 +167,7 @@ def setup(self): cls = self.obj - name = getattr(cls, 'objspacename', None) - if name is None: - m = __import__(cls.__module__, {}, {}, ["objspacename"]) - name = getattr(m, 'objspacename', None) - cls.space = gettestobjspace(name) + cls.space = gettestobjspace() super(IntClassCollector, self).setup() class AppClassInstance(py.test.collect.Instance): Modified: pypy/branch/pypy-newobjspace/objspace/flow/test/test_framestate.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/flow/test/test_framestate.py (original) +++ pypy/branch/pypy-newobjspace/objspace/flow/test/test_framestate.py Thu Jul 28 17:32:38 2005 @@ -5,10 +5,12 @@ from pypy.objspace.flow.model import * from pypy.objspace.flow.framestate import * from pypy.interpreter.pycode import PyCode - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace class TestFrameState: + def setup_class(cls): + cls.space = FlowObjSpace() + def getframe(self, func): space = self.space try: Modified: pypy/branch/pypy-newobjspace/objspace/flow/test/test_model.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/flow/test/test_model.py (original) +++ pypy/branch/pypy-newobjspace/objspace/flow/test/test_model.py Thu Jul 28 17:32:38 2005 @@ -1,10 +1,12 @@ import autopath from pypy.objspace.flow.model import * - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace class TestModel: + def setup_class(cls): + cls.space = FlowObjSpace() + def getflow(self, func): import inspect try: Modified: pypy/branch/pypy-newobjspace/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/flow/test/test_objspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/flow/test/test_objspace.py Thu Jul 28 17:32:38 2005 @@ -3,14 +3,16 @@ from pypy.objspace.flow.model import flatten from pypy.interpreter.argument import Arguments from pypy.translator.simplify import simplify_graph - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace import os import operator is_operator = getattr(operator, 'is_', operator.eq) # it's not there 2.2 class TestFlowObjSpace: + def setup_class(cls): + cls.space = FlowObjSpace() + def codetest(self, func): import inspect try: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_boolobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_boolobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_boolobject.py Thu Jul 28 17:32:38 2005 @@ -1,7 +1,6 @@ import autopath -objspacename = 'std' class TestW_BoolObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_dictobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_dictobject.py Thu Jul 28 17:32:38 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std.dictobject import W_DictObject -objspacename = 'std' class TestW_DictObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_dictproxy.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_dictproxy.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_dictproxy.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestUserObject: def test_dictproxy(self): Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_floatobject.py Thu Jul 28 17:32:38 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std import floatobject as fobj from pypy.objspace.std.objspace import FailedToImplement -objspacename = 'std' class TestW_FloatObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_instmethobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_instmethobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_instmethobject.py Thu Jul 28 17:32:38 2005 @@ -3,7 +3,6 @@ # NB. instmethobject.py has been removed, # but the following tests still make sense -objspacename = 'std' class AppTestInstMethObjectApp: def test_callBound(self): Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_intobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_intobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_intobject.py Thu Jul 28 17:32:38 2005 @@ -4,7 +4,6 @@ from pypy.objspace.std.objspace import FailedToImplement from pypy.rpython.rarithmetic import r_uint -objspacename = 'std' class TestW_IntObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_iterobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_iterobject.py Thu Jul 28 17:32:38 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std.iterobject import W_SeqIterObject from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_IterObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_listobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_listobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_listobject.py Thu Jul 28 17:32:38 2005 @@ -4,7 +4,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_ListObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_longobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_longobject.py Thu Jul 28 17:32:38 2005 @@ -6,7 +6,6 @@ from pypy.interpreter.error import OperationError from pypy.rpython.rarithmetic import r_uint # will go away -objspacename = 'std' def gen_signs(l): for s in l: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_noneobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_noneobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_noneobject.py Thu Jul 28 17:32:38 2005 @@ -1,7 +1,6 @@ import autopath -objspacename = 'std' class TestW_NoneObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_sliceobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_sliceobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_sliceobject.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class TestW_SliceObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_stdobjspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_stdobjspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_stdobjspace.py Thu Jul 28 17:32:38 2005 @@ -2,7 +2,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_StdObjSpace: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_stringformat.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_stringformat.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestStringObjectWithDict: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_stringobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_stringobject.py Thu Jul 28 17:32:38 2005 @@ -3,7 +3,6 @@ from pypy.objspace.std.stringobject import W_StringObject -objspacename = 'std' class TestW_StringObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_strutil.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_strutil.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_strutil.py Thu Jul 28 17:32:38 2005 @@ -4,7 +4,6 @@ import py -objspacename = 'std' class TestStrUtil: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_tupleobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_tupleobject.py Thu Jul 28 17:32:38 2005 @@ -4,7 +4,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_TupleObject: Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_typeobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_typeobject.py Thu Jul 28 17:32:38 2005 @@ -52,7 +52,6 @@ ## w({'x1': 5.5, 'x2': 7})), ## w(-1.5)) -objspacename = 'std' class AppTestTypeObject: def test_bases(self): Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_unicodeobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_unicodeobject.py Thu Jul 28 17:32:38 2005 @@ -4,7 +4,6 @@ import autopath, sys -objspacename = 'std' class AppTestUnicodeStringStdOnly: def test_compares(self): Modified: pypy/branch/pypy-newobjspace/objspace/std/test/test_userobject.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/test/test_userobject.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/test/test_userobject.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestUserObject: def test_emptyclass(self): Modified: pypy/branch/pypy-newobjspace/objspace/test/test_descriptor.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/test/test_descriptor.py (original) +++ pypy/branch/pypy-newobjspace/objspace/test/test_descriptor.py Thu Jul 28 17:32:38 2005 @@ -52,7 +52,6 @@ assert A.seen == [1,2,3,4] class TestDesciprtorOnStd: - objspacename = 'std' def test_hash(self): class A: pass Modified: pypy/branch/pypy-newobjspace/objspace/test/test_thunkobjspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/test/test_thunkobjspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/test/test_thunkobjspace.py Thu Jul 28 17:32:38 2005 @@ -1,7 +1,9 @@ +from pypy.objspace import thunk class AppTest_Thunk: - objspacename = 'thunk' + def setup_class(cls): + cls.space = thunk.Space(cls.space) def test_simple(self): computed = [] Modified: pypy/branch/pypy-newobjspace/rpython/test/test_llann.py ============================================================================== --- pypy/branch/pypy-newobjspace/rpython/test/test_llann.py (original) +++ pypy/branch/pypy-newobjspace/rpython/test/test_llann.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,7 @@ from pypy.rpython.lltype import * from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import annotate_lowlevel_helper +from pypy.objspace.flow import FlowObjSpace # helpers @@ -17,7 +18,8 @@ return None class TestLowLevelAnnotateTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() from pypy.translator.annrpython import RPythonAnnotator Modified: pypy/branch/pypy-newobjspace/rpython/test/test_rarithmetic.py ============================================================================== --- pypy/branch/pypy-newobjspace/rpython/test/test_rarithmetic.py (original) +++ pypy/branch/pypy-newobjspace/rpython/test/test_rarithmetic.py Thu Jul 28 17:32:38 2005 @@ -13,7 +13,6 @@ #print machbits -objspacename = 'std' class Test_r_int: Modified: pypy/branch/pypy-newobjspace/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/c/test/test_lltyped.py (original) +++ pypy/branch/pypy-newobjspace/translator/c/test/test_lltyped.py Thu Jul 28 17:32:38 2005 @@ -1,10 +1,12 @@ from pypy.rpython.lltype import * from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace class TestLowLevelType: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def getcompiled(self, func, argstypelist=[]): t = Translator(func, simplifying=True) Modified: pypy/branch/pypy-newobjspace/translator/c/test/test_notype.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/c/test/test_notype.py (original) +++ pypy/branch/pypy-newobjspace/translator/c/test/test_notype.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,7 @@ import autopath from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace from pypy.translator.test import snippet @@ -9,7 +10,8 @@ buildpyxmodule.enable_fast_compilation() class TestNoTypeCGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, func, *morefuncs): try: func = func.im_func Modified: pypy/branch/pypy-newobjspace/translator/c/test/test_operation.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/c/test/test_operation.py (original) +++ pypy/branch/pypy-newobjspace/translator/c/test/test_operation.py Thu Jul 28 17:32:38 2005 @@ -1,6 +1,7 @@ import autopath from pypy.objspace.flow.model import * from pypy.objspace.flow.operation import FunctionByName +from pypy.objspace.flow import FlowObjSpace from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator @@ -95,7 +96,8 @@ class TestOperations: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, graph): t = Translator() Modified: pypy/branch/pypy-newobjspace/translator/java/test/for_now_dont_test_javatrans.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/java/test/for_now_dont_test_javatrans.py (original) +++ pypy/branch/pypy-newobjspace/translator/java/test/for_now_dont_test_javatrans.py Thu Jul 28 17:32:38 2005 @@ -5,6 +5,7 @@ from pypy.translator.java.genjava import GenJava from pypy.translator.test import snippet from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace def setup_module(mod): @@ -16,7 +17,8 @@ class TestNoTypeCGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_jfunc(self, func): try: func = func.im_func Modified: pypy/branch/pypy-newobjspace/translator/pyrex/test/test_pyrextrans.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/pyrex/test/test_pyrextrans.py (original) +++ pypy/branch/pypy-newobjspace/translator/pyrex/test/test_pyrextrans.py Thu Jul 28 17:32:38 2005 @@ -6,6 +6,7 @@ from pypy.translator.tool.buildpyxmodule import build_cfunc from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace from pypy import conftest #from pypy.conftest import option @@ -18,7 +19,8 @@ class TestNoTypePyrexGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, func): try: func = func.im_func Modified: pypy/branch/pypy-newobjspace/translator/test/test_annrpython.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/test/test_annrpython.py (original) +++ pypy/branch/pypy-newobjspace/translator/test/test_annrpython.py Thu Jul 28 17:32:38 2005 @@ -11,6 +11,7 @@ from pypy.annotation.dictdef import DictDef from pypy.objspace.flow.model import * from pypy.rpython.rarithmetic import r_uint +from pypy.objspace.flow import FlowObjSpace from pypy.translator.test import snippet @@ -34,7 +35,8 @@ class TestAnnotateTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() from pypy.translator.annrpython import RPythonAnnotator Modified: pypy/branch/pypy-newobjspace/translator/test/test_cltrans.py ============================================================================== --- pypy/branch/pypy-newobjspace/translator/test/test_cltrans.py (original) +++ pypy/branch/pypy-newobjspace/translator/test/test_cltrans.py Thu Jul 28 17:32:38 2005 @@ -2,6 +2,7 @@ from pypy.tool.udir import udir import py import os +from pypy.objspace.flow import FlowObjSpace def setup_module(mod): mod.global_cl = os.getenv("PYPY_CL") @@ -36,7 +37,8 @@ from pypy.translator.tool.buildcl import Literal class TestGenCLTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def setup_method(self,method): if not global_cl: From hpk at codespeak.net Thu Jul 28 17:47:17 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 17:47:17 +0200 (CEST) Subject: [pypy-svn] r15265 - pypy/branch/pypy-newobjspace/objspace/std Message-ID: <20050728154717.257D027B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 17:47:16 2005 New Revision: 15265 Modified: pypy/branch/pypy-newobjspace/objspace/std/objspace.py Log: raise RuntimeError if we are non-faking and are hitting undetermined cpython-objects Modified: pypy/branch/pypy-newobjspace/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/std/objspace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/std/objspace.py Thu Jul 28 17:47:16 2005 @@ -274,7 +274,12 @@ return self.call_function(c, self.wrap(x.real), self.wrap(x.imag)) - # anything below this line is implicitly XXX'ed + + if self.options.nofaking: + # annotation should actually not get here + raise OperationError(self.w_RuntimeError, + self.wrap("nofaking enabled: refusing " + "to wrap cpython value %r" %(x,))) if isinstance(x, type(Exception)) and issubclass(x, Exception): w_result = self.wrap_exception_cls(x) if w_result is not None: From hpk at codespeak.net Thu Jul 28 17:49:12 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 17:49:12 +0200 (CEST) Subject: [pypy-svn] r15266 - pypy/branch/pypy-newobjspace/objspace Message-ID: <20050728154912.773DA27B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 17:49:11 2005 New Revision: 15266 Modified: pypy/branch/pypy-newobjspace/objspace/trace.py Log: remove some impossible code Modified: pypy/branch/pypy-newobjspace/objspace/trace.py ============================================================================== --- pypy/branch/pypy-newobjspace/objspace/trace.py (original) +++ pypy/branch/pypy-newobjspace/objspace/trace.py Thu Jul 28 17:49:11 2005 @@ -169,7 +169,7 @@ del operations[name] return operations -def create_trace_space(space = None, operations = None): +def create_trace_space(space, operations = None): """ Will create a trace object space if no space supplied. Otherwise will turn the supplied into a tracable space by extending its class.""" @@ -177,12 +177,6 @@ if hasattr(space, "__pypytrace__"): return space - if space is None: - # make up a TrivialObjSpace by default - # ultimately, remove this hack and fix the -P option of tests - from pypy.objspace import trivial - space = trivial.TrivialObjSpace() - if operations is None: operations = get_operations() From rxe at codespeak.net Thu Jul 28 18:03:49 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 18:03:49 +0200 (CEST) Subject: [pypy-svn] r15267 - in pypy/branch/pypy-newobjspace: interpreter module/sys Message-ID: <20050728160349.ADF8927B85@code1.codespeak.net> Author: rxe Date: Thu Jul 28 18:03:47 2005 New Revision: 15267 Modified: pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py pypy/branch/pypy-newobjspace/module/sys/state.py Log: Rationalise get_builtinmodule_list() a tiny bit. Modified: pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py (original) +++ pypy/branch/pypy-newobjspace/interpreter/baseobjspace.py Thu Jul 28 18:03:47 2005 @@ -148,15 +148,17 @@ return self._builtinmodule_list except AttributeError: pass - l = 'sys __builtin__ exceptions unicodedata _codecs'.split() + + l = ['unicodedata', '_codecs'] + if self.options.nofaking: l.append('posix') l.append('math') + for name in self.options.usemodules: - if name in l: - continue - # XXX error throwing (catch wrong names) - l.append(name) + if name not in l: + l.append(name) + builtinmodule_list = [(x, None) for x in l] if self.options.parser == "recparser": builtinmodule_list.append(('parser', 'recparser')) Modified: pypy/branch/pypy-newobjspace/module/sys/state.py ============================================================================== --- pypy/branch/pypy-newobjspace/module/sys/state.py (original) +++ pypy/branch/pypy-newobjspace/module/sys/state.py Thu Jul 28 18:03:47 2005 @@ -2,7 +2,6 @@ Implementation of interpreter-level 'sys' routines. """ import pypy -#from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError import sys, os From ale at codespeak.net Thu Jul 28 18:14:19 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 28 Jul 2005 18:14:19 +0200 (CEST) Subject: [pypy-svn] r15268 - in pypy/dist/pypy: module/math rpython rpython/module rpython/module/test Message-ID: <20050728161419.490E827B85@code1.codespeak.net> Author: ale Date: Thu Jul 28 18:14:17 2005 New Revision: 15268 Modified: pypy/dist/pypy/module/math/__init__.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_math.py pypy/dist/pypy/rpython/module/test/test_ll_math.py Log: added math.sqrt, sin, cos, sinh, hypot (needed for lib-python) Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Thu Jul 28 18:14:17 2005 @@ -10,33 +10,36 @@ # is that we need to add support to # extfunctable/translation interpleveldefs = { - 'e' : 'interp_math.get(space).w_e', - 'pi' : 'interp_math.get(space).w_pi', - #'pow' : 'interp_math.pow', - #'cosh' : 'interp_math.cosh', - 'ldexp' : 'interp_math.ldexp', - #'hypot' : 'interp_math.hypot', - #'tan' : 'interp_math.tan', - #'asin' : 'interp_math.asin', - #'log' : 'interp_math.log', - #'fabs' : 'interp_math.fabs', - 'floor' : 'interp_math.floor', - #'sqrt' : 'interp_math.sqrt', - 'frexp' : 'interp_math.frexp', - #'degrees' : 'interp_math.degrees', - 'log' : 'interp_math.log', - 'log10' : 'interp_math.log10', - 'fmod' : 'interp_math.fmod', - #'atan' : 'interp_math.atan', - 'ceil' : 'interp_math.ceil', - #'sinh' : 'interp_math.sinh', - #'cos' : 'interp_math.cos', - #'tanh' : 'interp_math.tanh', - #'radians' : 'interp_math.radians', - #'sin' : 'interp_math.sin', - 'atan2' : 'interp_math.atan2', - 'modf' : 'interp_math.modf', - 'exp' : 'interp_math.exp', - #'acos' : 'interp_math.acos', + 'e' : 'interp_math.get(space).w_e', + 'pi' : 'interp_math.get(space).w_pi', + #'pow' : 'interp_math.pow', + #'cosh' : 'interp_math.cosh', + 'ldexp' : 'interp_math.ldexp', + 'hypot' : 'interp_math.hypot', + #'tan' : 'interp_math.tan', + #'asin' : 'interp_math.asin', + #'log' : 'interp_math.log', + #'fabs' : 'interp_math.fabs', + 'floor' : 'interp_math.floor', + #'sqrt' : 'interp_math.sqrt', + 'frexp' : 'interp_math.frexp', + #'degrees' : 'interp_math.degrees', + 'log' : 'interp_math.log', + 'log10' : 'interp_math.log10', + 'fmod' : 'interp_math.fmod', + #'atan' : 'interp_math.atan', + 'ceil' : 'interp_math.ceil', + 'sinh' : 'interp_math.sinh', + 'acos' : 'interp_math.acos', + 'sin' : 'interp_math.sin', + 'sqrt' : 'interp_math.sqrt', + 'cos' : 'interp_math.cos', + #'tanh' : 'interp_math.tanh', + #'radians' : 'interp_math.radians', + #'sin' : 'interp_math.sin', + 'atan2' : 'interp_math.atan2', + 'modf' : 'interp_math.modf', + 'exp' : 'interp_math.exp', + 'acos' : 'interp_math.acos', } Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 28 18:14:17 2005 @@ -85,6 +85,12 @@ declare(time.sleep , noneannotation, 'll_time/sleep') declare(math.log10 , float , 'll_math/log10') declare(math.log , float , 'll_math/log') +declare(math.cos , float , 'll_math/cos') +declare(math.sin , float , 'll_math/sin') +declare(math.sinh , float , 'll_math/sinh') +declare(math.acos , float , 'll_math/acos') +declare(math.sqrt , float , 'll_math/sqrt') +declare(math.hypot , float , 'll_math/hypot') declare(math.ceil , float , 'll_math/ceil') declare(math.frexp , frexpannotation, 'll_math/frexp') declare(math.atan2 , float , 'll_math/atan2') Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Thu Jul 28 18:14:17 2005 @@ -2,6 +2,30 @@ import math +def ll_math_cos(x): + return math.cos(x) +ll_math_cos.suggested_primitive = True + +def ll_math_sin(x): + return math.sin(x) +ll_math_sin.suggested_primitive = True + +def ll_math_sinh(x): + return math.sinh(x) +ll_math_sinh.suggested_primitive = True + +def ll_math_hypot(x, y): + return math.hypot(x, y) +ll_math_hypot.suggested_primitive = True + +def ll_math_acos(x): + return math.acos(x) +ll_math_acos.suggested_primitive = True + +def ll_math_sqrt(x): + return math.sqrt(x) +ll_math_sqrt.suggested_primitive = True + def ll_math_log(x): return math.log(x) ll_math_log.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_math.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_math.py Thu Jul 28 18:14:17 2005 @@ -19,3 +19,17 @@ def test_ll_log(): assert ll_math_log(8943.790148912) == math.log(8943.790148912) assert ll_math_log10(8943.790148912) == math.log10(8943.790148912) + +def test_ll_cos_sin(): + assert ll_math_cos(math.pi/3) == math.cos(math.pi/3) + assert ll_math_sin(math.pi/3) == math.sin(math.pi/3) + assert ll_math_acos(1./3) == math.acos(1./3) + assert ll_math_sinh(math.pi/3) == math.sinh(math.pi/3) + assert ll_math_cosh(math.pi/3) == math.cosh(math.pi/3) + +def test_ll_math_sqrt(): + assert ll_math_sqrt(10) == math.sqrt(10) + +def test_ll_math_hypot(): + assert ll_math_hypot(math.pi/3,3) == math.hypot(math.pi/3,3) + From ale at codespeak.net Thu Jul 28 18:20:53 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 28 Jul 2005 18:20:53 +0200 (CEST) Subject: [pypy-svn] r15269 - in pypy/dist/pypy: module/math rpython rpython/module Message-ID: <20050728162053.0668227B85@code1.codespeak.net> Author: ale Date: Thu Jul 28 18:20:51 2005 New Revision: 15269 Modified: pypy/dist/pypy/module/math/__init__.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_math.py Log: added math.cosh (needed for lib-python) Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Thu Jul 28 18:20:51 2005 @@ -13,7 +13,7 @@ 'e' : 'interp_math.get(space).w_e', 'pi' : 'interp_math.get(space).w_pi', #'pow' : 'interp_math.pow', - #'cosh' : 'interp_math.cosh', + 'cosh' : 'interp_math.cosh', 'ldexp' : 'interp_math.ldexp', 'hypot' : 'interp_math.hypot', #'tan' : 'interp_math.tan', Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 28 18:20:51 2005 @@ -88,6 +88,7 @@ declare(math.cos , float , 'll_math/cos') declare(math.sin , float , 'll_math/sin') declare(math.sinh , float , 'll_math/sinh') +declare(math.cosh , float , 'll_math/cosh') declare(math.acos , float , 'll_math/acos') declare(math.sqrt , float , 'll_math/sqrt') declare(math.hypot , float , 'll_math/hypot') Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Thu Jul 28 18:20:51 2005 @@ -10,18 +10,22 @@ return math.sin(x) ll_math_sin.suggested_primitive = True +def ll_math_acos(x): + return math.acos(x) +ll_math_acos.suggested_primitive = True + def ll_math_sinh(x): return math.sinh(x) ll_math_sinh.suggested_primitive = True +def ll_math_cosh(x): + return math.cosh(x) +ll_math_cosh.suggested_primitive = True + def ll_math_hypot(x, y): return math.hypot(x, y) ll_math_hypot.suggested_primitive = True -def ll_math_acos(x): - return math.acos(x) -ll_math_acos.suggested_primitive = True - def ll_math_sqrt(x): return math.sqrt(x) ll_math_sqrt.suggested_primitive = True From hpk at codespeak.net Thu Jul 28 18:29:13 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 18:29:13 +0200 (CEST) Subject: [pypy-svn] r15270 - in pypy/dist/pypy: . bin interpreter module/sys objspace objspace/flow/test objspace/std objspace/std/test objspace/test rpython/test tool translator/c/test translator/goal translator/java/test translator/pyrex/test translator/test Message-ID: <20050728162913.9CD1127B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 18:29:05 2005 New Revision: 15270 Removed: pypy/dist/pypy/objspace/std/test/test_fake.py pypy/dist/pypy/tool/optik.py Modified: pypy/dist/pypy/bin/py.py pypy/dist/pypy/conftest.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/sys/state.py pypy/dist/pypy/objspace/flow/test/test_framestate.py pypy/dist/pypy/objspace/flow/test/test_model.py pypy/dist/pypy/objspace/flow/test/test_objspace.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_boolobject.py pypy/dist/pypy/objspace/std/test/test_dictobject.py pypy/dist/pypy/objspace/std/test/test_dictproxy.py pypy/dist/pypy/objspace/std/test/test_floatobject.py pypy/dist/pypy/objspace/std/test/test_instmethobject.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_noneobject.py pypy/dist/pypy/objspace/std/test/test_sliceobject.py pypy/dist/pypy/objspace/std/test/test_stdobjspace.py pypy/dist/pypy/objspace/std/test/test_stringformat.py pypy/dist/pypy/objspace/std/test/test_stringobject.py pypy/dist/pypy/objspace/std/test/test_strutil.py pypy/dist/pypy/objspace/std/test/test_tupleobject.py pypy/dist/pypy/objspace/std/test/test_typeobject.py pypy/dist/pypy/objspace/std/test/test_unicodeobject.py pypy/dist/pypy/objspace/std/test/test_userobject.py pypy/dist/pypy/objspace/test/test_descriptor.py pypy/dist/pypy/objspace/test/test_thunkobjspace.py pypy/dist/pypy/objspace/trace.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/test/test_rarithmetic.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/c/test/test_lltyped.py pypy/dist/pypy/translator/c/test/test_notype.py pypy/dist/pypy/translator/c/test/test_operation.py pypy/dist/pypy/translator/goal/targetpypymain.py pypy/dist/pypy/translator/java/test/for_now_dont_test_javatrans.py pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py pypy/dist/pypy/translator/test/test_annrpython.py pypy/dist/pypy/translator/test/test_cltrans.py Log: (rxe,hpk) - refactored Object Space initialization to be keyword/argument based instead of requiring pseudo-cmdlineoptions - implemented more generic mechanisms for specifying which of our builtin modules should be used. you can now do e.g. "pypy --usemodules=posix" to play around with the posix module and StdObjSpace(usemodules=['posix']) should work to instantiate an object space that has the posix module builtin. - adapted test framework to the new style in particular you can't specify 'objspacename=SOMENAME' anymore but instead you should instantiate your own Object Space if you want to have a custom or special one (like the flow space). - removed test_fake.py which became nonsensical over time Modified: pypy/dist/pypy/bin/py.py ============================================================================== --- pypy/dist/pypy/bin/py.py (original) +++ pypy/dist/pypy/bin/py.py Thu Jul 28 18:29:05 2005 @@ -12,7 +12,7 @@ pass from pypy.tool import option -from pypy.tool.optik import make_option +from optparse import make_option from pypy.interpreter import main, interactive, error import os, sys import time @@ -53,6 +53,24 @@ return options +def make_objspace(cmdlineopt): + from pypy.objspace import std + if cmdlineopt.objspace not in ('std', 'thunk'): + raise ValueError("cannot instantiate %r space" %(cmdlineopt.objspace,)) + + # so far we always need a StdObjSpace + space = std.Space(usemodules = cmdlineopt.usemodules, + nofaking = cmdlineopt.nofaking, + uselibfile = cmdlineopt.uselibfile, + oldstyle = cmdlineopt.oldstyle, + parser = cmdlineopt.parser, + compiler = cmdlineopt.compiler, + ) + if cmdlineopt.objspace == 'thunk': + from pypy.objspace import thunk + space = thunk.Space(space) + return space + def main_(argv=None): starttime = time.time() args = option.process_options(get_main_options(), Options, argv[1:]) @@ -60,7 +78,9 @@ error.RECORD_INTERPLEVEL_TRACEBACK = True # create the object space - space = option.objspace() + + space = make_objspace(Options) + space._starttime = starttime assert 'pypy.tool.udir' not in sys.modules, ( "running py.py should not import pypy.tool.udir, which is\n" Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Thu Jul 28 18:29:05 2005 @@ -18,12 +18,16 @@ option = py.test.Config.addoptions("pypy options", Option('-O', '--objspace', action="store", default=None, - type="string", dest="objspacename", + type="string", dest="objspace", help="object space to run tests on."), Option('--oldstyle', action="store_true",dest="oldstyle", default=False, - help="enable oldstyle classes as default metaclass (std objspace only)"), - Option('--file', action="store_true",dest="uselibfile", default=False, - help="enable our custom file implementation"), + help="enable oldstyle classes as default metaclass"), + Option('--uselibfile', action="store_true", + dest="uselibfile", default=False, + help="enable our applevel file implementation"), + Option('--nofaking', action="store_true", + dest="nofaking", default=False, + help="avoid faking of modules and objects completely."), Option('--allpypy', action="store_true",dest="allpypy", default=False, help="run everything possible on top of PyPy."), ) @@ -31,24 +35,17 @@ def getobjspace(name=None, _spacecache={}): """ helper for instantiating and caching space's for testing. """ - if name is None: - name = option.objspacename - if name is None: - name = py.std.os.environ.get('OBJSPACE', 'std') - else: - optionname = option.objspacename - if optionname is not None and optionname != name: - return None + name = name or option.objspace or 'std' try: return _spacecache[name] except KeyError: - import pypy.tool.option - spaceoptions = pypy.tool.option.Options() - spaceoptions.uselibfile = option.uselibfile - #py.magic.invoke(compile=True) - module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) + assert name in ('std', 'thunk'), name + from pypy.objspace.std import Space try: - space = module.Space(spaceoptions) + space = Space(uselibfile=option.uselibfile, + nofaking=option.nofaking, + oldstyle=option.oldstyle, + ) except KeyboardInterrupt: raise except OperationError, e: @@ -64,17 +61,14 @@ traceback.print_exc() py.test.fail("fatal: cannot initialize objspace: %r" %(module.Space,)) _spacecache[name] = space - if name == 'std' and option.oldstyle: - space.enable_old_style_classes_as_default_metaclass() - if name != 'flow': # not sensible for flow objspace case - space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), - appsupport.build_pytest_assertion(space)) - space.setitem(space.builtin.w_dict, space.wrap('raises'), - space.wrap(appsupport.app_raises)) - space.setitem(space.builtin.w_dict, space.wrap('skip'), - space.wrap(appsupport.app_skip)) - space.raises_w = appsupport.raises_w.__get__(space) - space.eq_w = appsupport.eq_w.__get__(space) + space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), + appsupport.build_pytest_assertion(space)) + space.setitem(space.builtin.w_dict, space.wrap('raises'), + space.wrap(appsupport.app_raises)) + space.setitem(space.builtin.w_dict, space.wrap('skip'), + space.wrap(appsupport.app_skip)) + space.raises_w = appsupport.raises_w.__get__(space) + space.eq_w = appsupport.eq_w.__get__(space) return space # @@ -142,8 +136,7 @@ def execute(self, target, *args): co = target.func_code if 'space' in co.co_varnames[:co.co_argcount]: - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) + space = gettestobjspace() target(space, *args) else: target(*args) @@ -157,8 +150,7 @@ class AppTestFunction(PyPyTestFunction): def execute(self, target, *args): assert not args - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) + space = gettestobjspace() func = app2interp_temp(target) print "executing", func self.execute_appex(space, func, space) @@ -175,11 +167,7 @@ def setup(self): cls = self.obj - name = getattr(cls, 'objspacename', None) - if name is None: - m = __import__(cls.__module__, {}, {}, ["objspacename"]) - name = getattr(m, 'objspacename', None) - cls.space = gettestobjspace(name) + cls.space = gettestobjspace() super(IntClassCollector, self).setup() class AppClassInstance(py.test.collect.Instance): Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 18:29:05 2005 @@ -6,7 +6,6 @@ from pypy.interpreter.miscutils import ThreadLocals from pypy.tool.cache import Cache from pypy.rpython.rarithmetic import r_uint -import pypy.tool.option __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'BaseWrappable', 'W_Root'] @@ -94,6 +93,9 @@ finally: self.space.leave_cache_building_mode(val) +class ObjSpaceOptions: + def _freeze_(self): + return True class ObjSpace(object): """Base class for the interpreter-level implementations of object spaces. @@ -101,17 +103,22 @@ full_exceptions = True # full support for exceptions (normalization & more) - def __init__(self, options=None): + def __init__(self, usemodules=(), + nofaking=False, + uselibfile=False, + parser="recparser", + compiler="pyparse"): "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() # set recursion limit # sets all the internal descriptors - - # XXX: Options in option.py is replaced by a function so - # it's not really clean to do a from option import Options - # since changing import order can change the Options object - self.options = options or pypy.tool.option.Options() + self.options = ObjSpaceOptions() + self.options.parser = parser + self.options.nofaking = nofaking + self.options.uselibfile = uselibfile or nofaking + self.options.compiler = compiler + self.options.usemodules = usemodules self.initialize() def __repr__(self): @@ -140,21 +147,26 @@ try: return self._builtinmodule_list except AttributeError: - builtinmodule_list = [('sys', None), ('__builtin__', None), - ('exceptions', None), ('marshal', None)] - builtinmodule_list.append(('unicodedata', None)) - # Uncomment the following line to enable the builtin _codecs module - builtinmodule_list.append(('_codecs', None)) - if self.options.useparsermodule == "recparser": - builtinmodule_list.append(('parser', 'recparser')) - builtinmodule_list.append(('symbol', None)) - elif self.options.useparsermodule == "parser": - builtinmodule_list.append(('parser', None)) - if self.options.nofakedmodules: - builtinmodule_list.append(('posix', None)) - builtinmodule_list.append(('math', None)) - self._builtinmodule_list = builtinmodule_list - return self._builtinmodule_list + pass + + l = ['sys', '__builtin__', 'exceptions', 'unicodedata', '_codecs'] + + if self.options.nofaking: + l.append('posix') + l.append('math') + + for name in self.options.usemodules: + if name not in l: + l.append(name) + + builtinmodule_list = [(x, None) for x in l] + if self.options.parser == "recparser": + builtinmodule_list.append(('parser', 'recparser')) + builtinmodule_list.append(('symbol', None)) + elif self.options.parser == "parser": + builtinmodule_list.append(('parser', None)) + self._builtinmodule_list = builtinmodule_list + return self._builtinmodule_list def make_builtins(self): "NOT_RPYTHON: only for initializing the space." Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Thu Jul 28 18:29:05 2005 @@ -2,7 +2,6 @@ Implementation of interpreter-level 'sys' routines. """ import pypy -#from pypy.interpreter.module import Module from pypy.interpreter.error import OperationError import sys, os @@ -50,7 +49,7 @@ builtinmodule_list = self.space.get_builtinmodule_list() builtinmodule_names = [name for name, mixedname in builtinmodule_list] - if not space.options.nofakedmodules: + if not space.options.nofaking: for modname in ALL_BUILTIN_MODULES: if modname not in builtinmodule_names: if not (os.path.exists( Modified: pypy/dist/pypy/objspace/flow/test/test_framestate.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_framestate.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_framestate.py Thu Jul 28 18:29:05 2005 @@ -5,10 +5,12 @@ from pypy.objspace.flow.model import * from pypy.objspace.flow.framestate import * from pypy.interpreter.pycode import PyCode - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace class TestFrameState: + def setup_class(cls): + cls.space = FlowObjSpace() + def getframe(self, func): space = self.space try: Modified: pypy/dist/pypy/objspace/flow/test/test_model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_model.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_model.py Thu Jul 28 18:29:05 2005 @@ -1,10 +1,12 @@ import autopath from pypy.objspace.flow.model import * - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace class TestModel: + def setup_class(cls): + cls.space = FlowObjSpace() + def getflow(self, func): import inspect try: Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Thu Jul 28 18:29:05 2005 @@ -3,14 +3,16 @@ from pypy.objspace.flow.model import flatten from pypy.interpreter.argument import Arguments from pypy.translator.simplify import simplify_graph - -objspacename = 'flow' +from pypy.objspace.flow import FlowObjSpace import os import operator is_operator = getattr(operator, 'is_', operator.eq) # it's not there 2.2 class TestFlowObjSpace: + def setup_class(cls): + cls.space = FlowObjSpace() + def codetest(self, func): import inspect try: Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 18:29:05 2005 @@ -29,6 +29,12 @@ PACKAGE_PATH = 'objspace.std' + def __init__(self, oldstyle=False, **kw): + super(StdObjSpace, self).__init__(**kw) + self.options.oldstyle = oldstyle + if oldstyle: + self.enable_old_style_classes_as_default_metaclass() + def initialize(self): "NOT_RPYTHON: only for initializing the space." self._typecache = Cache() @@ -97,7 +103,7 @@ """) if self.options.uselibfile: - self.setuselibfile() + self.inituselibfile() # XXX hack!: patch the compiler after initialization is complete if self.options.compiler == 'pyparseapp': @@ -150,7 +156,7 @@ w_mod = self.wrap(mod) return w_mod, w_dic - def setuselibfile(self): + def inituselibfile(self): """ NOT_RPYTHON use our application level file implementation including re-wrapping sys.stdout/err/in """ @@ -158,7 +164,7 @@ space = self # nice print helper if the below does not work # (we dont have prints working at applevel before - # setuselibfile is complete) + # inituselibfile is complete) #from pypy.interpreter import gateway #def printit(space, w_msg): # s = space.str_w(w_msg) @@ -273,7 +279,12 @@ return self.call_function(c, self.wrap(x.real), self.wrap(x.imag)) - # anything below this line is implicitly XXX'ed + + if self.options.nofaking: + # annotation should actually not get here + raise OperationError(self.w_RuntimeError, + self.wrap("nofaking enabled: refusing " + "to wrap cpython value %r" %(x,))) if isinstance(x, type(Exception)) and issubclass(x, Exception): w_result = self.wrap_exception_cls(x) if w_result is not None: Modified: pypy/dist/pypy/objspace/std/test/test_boolobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_boolobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_boolobject.py Thu Jul 28 18:29:05 2005 @@ -1,7 +1,6 @@ import autopath -objspacename = 'std' class TestW_BoolObject: Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Thu Jul 28 18:29:05 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std.dictobject import W_DictObject -objspacename = 'std' class TestW_DictObject: Modified: pypy/dist/pypy/objspace/std/test/test_dictproxy.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictproxy.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictproxy.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestUserObject: def test_dictproxy(self): Deleted: /pypy/dist/pypy/objspace/std/test/test_fake.py ============================================================================== --- /pypy/dist/pypy/objspace/std/test/test_fake.py Thu Jul 28 18:29:05 2005 +++ (empty file) @@ -1,14 +0,0 @@ -# test the integration of unicode and strings (even though we don't -# really implement unicode yet). - -import autopath, sys - - -objspacename = 'std' - -class AppTestFakedTypes: - def test_inheriting(self): - class MyUnicode(unicode): - pass - my_u = MyUnicode('123') - assert type(my_u) is MyUnicode 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 Thu Jul 28 18:29:05 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std import floatobject as fobj from pypy.objspace.std.objspace import FailedToImplement -objspacename = 'std' class TestW_FloatObject: Modified: pypy/dist/pypy/objspace/std/test/test_instmethobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_instmethobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_instmethobject.py Thu Jul 28 18:29:05 2005 @@ -3,7 +3,6 @@ # NB. instmethobject.py has been removed, # but the following tests still make sense -objspacename = 'std' class AppTestInstMethObjectApp: def test_callBound(self): 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 Thu Jul 28 18:29:05 2005 @@ -4,7 +4,6 @@ from pypy.objspace.std.objspace import FailedToImplement from pypy.rpython.rarithmetic import r_uint -objspacename = 'std' class TestW_IntObject: 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 Thu Jul 28 18:29:05 2005 @@ -2,7 +2,6 @@ from pypy.objspace.std.iterobject import W_SeqIterObject from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_IterObject: 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 Thu Jul 28 18:29:05 2005 @@ -4,7 +4,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_ListObject: 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 Thu Jul 28 18:29:05 2005 @@ -6,7 +6,6 @@ from pypy.interpreter.error import OperationError from pypy.rpython.rarithmetic import r_uint # will go away -objspacename = 'std' def gen_signs(l): for s in l: Modified: pypy/dist/pypy/objspace/std/test/test_noneobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_noneobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_noneobject.py Thu Jul 28 18:29:05 2005 @@ -1,7 +1,6 @@ import autopath -objspacename = 'std' class TestW_NoneObject: 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 Thu Jul 28 18:29:05 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class TestW_SliceObject: Modified: pypy/dist/pypy/objspace/std/test/test_stdobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_stdobjspace.py (original) +++ pypy/dist/pypy/objspace/std/test/test_stdobjspace.py Thu Jul 28 18:29:05 2005 @@ -2,7 +2,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_StdObjSpace: Modified: pypy/dist/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/dist/pypy/objspace/std/test/test_stringformat.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestStringObjectWithDict: 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 Jul 28 18:29:05 2005 @@ -3,7 +3,6 @@ from pypy.objspace.std.stringobject import W_StringObject -objspacename = 'std' class TestW_StringObject: Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Thu Jul 28 18:29:05 2005 @@ -4,7 +4,6 @@ import py -objspacename = 'std' class TestStrUtil: 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 Thu Jul 28 18:29:05 2005 @@ -4,7 +4,6 @@ from pypy.interpreter.error import OperationError -objspacename = 'std' class TestW_TupleObject: 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 Thu Jul 28 18:29:05 2005 @@ -52,7 +52,6 @@ ## w({'x1': 5.5, 'x2': 7})), ## w(-1.5)) -objspacename = 'std' class AppTestTypeObject: def test_bases(self): 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 Jul 28 18:29:05 2005 @@ -4,7 +4,6 @@ import autopath, sys -objspacename = 'std' class AppTestUnicodeStringStdOnly: def test_compares(self): Modified: pypy/dist/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_userobject.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,5 @@ import autopath -objspacename = 'std' class AppTestUserObject: def test_emptyclass(self): Modified: pypy/dist/pypy/objspace/test/test_descriptor.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_descriptor.py (original) +++ pypy/dist/pypy/objspace/test/test_descriptor.py Thu Jul 28 18:29:05 2005 @@ -52,7 +52,6 @@ assert A.seen == [1,2,3,4] class TestDesciprtorOnStd: - objspacename = 'std' def test_hash(self): class A: pass Modified: pypy/dist/pypy/objspace/test/test_thunkobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_thunkobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_thunkobjspace.py Thu Jul 28 18:29:05 2005 @@ -1,7 +1,9 @@ +from pypy.objspace import thunk class AppTest_Thunk: - objspacename = 'thunk' + def setup_class(cls): + cls.space = thunk.Space(cls.space) def test_simple(self): computed = [] Modified: pypy/dist/pypy/objspace/trace.py ============================================================================== --- pypy/dist/pypy/objspace/trace.py (original) +++ pypy/dist/pypy/objspace/trace.py Thu Jul 28 18:29:05 2005 @@ -169,7 +169,7 @@ del operations[name] return operations -def create_trace_space(space = None, operations = None): +def create_trace_space(space, operations = None): """ Will create a trace object space if no space supplied. Otherwise will turn the supplied into a tracable space by extending its class.""" @@ -177,12 +177,6 @@ if hasattr(space, "__pypytrace__"): return space - if space is None: - # make up a TrivialObjSpace by default - # ultimately, remove this hack and fix the -P option of tests - from pypy.objspace import trivial - space = trivial.TrivialObjSpace() - if operations is None: operations = get_operations() Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,7 @@ from pypy.rpython.lltype import * from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import annotate_lowlevel_helper +from pypy.objspace.flow import FlowObjSpace # helpers @@ -17,7 +18,8 @@ return None class TestLowLevelAnnotateTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() from pypy.translator.annrpython import RPythonAnnotator 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 Thu Jul 28 18:29:05 2005 @@ -13,7 +13,6 @@ #print machbits -objspacename = 'std' class Test_r_int: Deleted: /pypy/dist/pypy/tool/optik.py ============================================================================== --- /pypy/dist/pypy/tool/optik.py Thu Jul 28 18:29:05 2005 +++ (empty file) @@ -1,1667 +0,0 @@ -"""optik - -A powerful, extensible, and easy-to-use command-line parser for Python. - -By Greg Ward - -See http://optik.sourceforge.net/ -""" - -"""optik.errors - -Exception classes used by Optik. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17 GPW (from optik.py) - -import sys -import types, os -import string, re - -class OptikError (Exception): - def __init__ (self, msg): - self.msg = msg - - def __str__ (self): - return self.msg - - -class OptionError (OptikError): - """ - Raised if an Option instance is created with invalid or - inconsistent arguments. - """ - - def __init__ (self, msg, option): - self.msg = msg - self.option_id = str(option) - - def __str__ (self): - if self.option_id: - return "option %s: %s" % (self.option_id, self.msg) - else: - return self.msg - -class OptionConflictError (OptionError): - """ - Raised if conflicting options are added to an OptionParser. - """ - -class OptionValueError (OptikError): - """ - Raised if an invalid option value is encountered on the command - line. - """ - -class BadOptionError (OptikError): - """ - Raised if an invalid or ambiguous option is seen on the command-line. - """ - - -class HelpFormatter: - - """ - Abstract base class for formatting option help. OptionParser - instances should use one of the HelpFormatter subclasses for - formatting help; by default IndentedHelpFormatter is used. - - Instance attributes: - indent_increment : int - the number of columns to indent per nesting level - max_help_position : int - the maximum starting column for option help text - help_position : int - the calculated starting column for option help text; - initially the same as the maximum - width : int - total number of columns for output - level : int - current indentation level - current_indent : int - current indentation level (in columns) - help_width : int - number of columns available for option help text (calculated) - """ - - def __init__ (self, - indent_increment, - max_help_position, - width, - short_first): - self.indent_increment = indent_increment - self.help_position = self.max_help_position = max_help_position - self.width = width - self.current_indent = 0 - self.level = 0 - self.help_width = width - max_help_position - self.short_first = short_first - - def indent (self): - self.current_indent += self.indent_increment - self.level += 1 - - def dedent (self): - self.current_indent -= self.indent_increment - assert self.current_indent >= 0, "Indent decreased below 0." - self.level -= 1 - - def format_usage (self, usage): - raise NotImplementedError, "subclasses must implement" - - def format_heading (self, heading): - raise NotImplementedError, "subclasses must implement" - - def format_description (self, description): - desc_width = self.width - self.current_indent - indent = " "*self.current_indent - return fill(description, desc_width, - initial_indent=indent, - subsequent_indent=indent) - - def format_option (self, option): - # The help for each option consists of two parts: - # * the opt strings and metavars - # eg. ("-x", or "-fFILENAME, --file=FILENAME") - # * the user-supplied help string - # eg. ("turn on expert mode", "read data from FILENAME") - # - # If possible, we write both of these on the same line: - # -x turn on expert mode - # - # But if the opt string list is too long, we put the help - # string on a second line, indented to the same column it would - # start in if it fit on the first line. - # -fFILENAME, --file=FILENAME - # read data from FILENAME - result = [] - opts = option.option_strings - opt_width = self.help_position - self.current_indent - 2 - if len(opts) > opt_width: - opts = "%*s%s\n" % (self.current_indent, "", opts) - indent_first = self.help_position - else: # start help on same line as opts - opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) - indent_first = 0 - result.append(opts) - if option.help: - help_lines = wrap(option.help, self.help_width) - result.append("%*s%s\n" % (indent_first, "", help_lines[0])) - result.extend(["%*s%s\n" % (self.help_position, "", line) - for line in help_lines[1:]]) - elif opts[-1] != "\n": - result.append("\n") - return "".join(result) - - def store_option_strings (self, parser): - self.indent() - max_len = 0 - for opt in parser.option_list: - strings = self.format_option_strings(opt) - opt.option_strings = strings - max_len = max(max_len, len(strings) + self.current_indent) - self.indent() - for group in parser.option_groups: - for opt in group.option_list: - strings = self.format_option_strings(opt) - opt.option_strings = strings - max_len = max(max_len, len(strings) + self.current_indent) - self.dedent() - self.dedent() - self.help_position = min(max_len + 2, self.max_help_position) - - def format_option_strings (self, option): - """Return a comma-separated list of option strings & metavariables.""" - if option.takes_value(): - metavar = option.metavar or option.dest.upper() - short_opts = [sopt + metavar for sopt in option._short_opts] - long_opts = [lopt + "=" + metavar for lopt in option._long_opts] - else: - short_opts = option._short_opts - long_opts = option._long_opts - - if self.short_first: - opts = short_opts + long_opts - else: - opts = long_opts + short_opts - - return ", ".join(opts) - -class IndentedHelpFormatter (HelpFormatter): - """Format help with indented section bodies. - """ - - def __init__ (self, - indent_increment=2, - max_help_position=24, - width=80, - short_first=1): - HelpFormatter.__init__( - self, indent_increment, max_help_position, width, short_first) - - def format_usage (self, usage): - return "usage: %s\n" % usage - - def format_heading (self, heading): - return "%*s%s:\n" % (self.current_indent, "", heading) - - -class TitledHelpFormatter (HelpFormatter): - """Format help with underlined section headers. - """ - - def __init__ (self, - indent_increment=0, - max_help_position=24, - width=80, - short_first=0): - HelpFormatter.__init__ ( - self, indent_increment, max_help_position, width, short_first) - - def format_usage (self, usage): - return "%s %s\n" % (self.format_heading("Usage"), usage) - - def format_heading (self, heading): - return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading)) -"""optik.option - -Defines the Option class and some standard value-checking functions. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17, GPW (from optik.py) - - -# Do the right thing with boolean values for all known Python versions. -try: - True, False -except NameError: - (True, False) = (1, 0) - -_builtin_cvt = { "int" : (int, "integer"), - "long" : (long, "long integer"), - "float" : (float, "floating-point"), - "complex" : (complex, "complex") } - -def check_builtin (option, opt, value): - (cvt, what) = _builtin_cvt[option.type] - try: - return cvt(value) - except ValueError: - raise OptionValueError( - #"%s: invalid %s argument %r" % (opt, what, value)) - "option %s: invalid %s value: %r" % (opt, what, value)) - -def check_choice(option, opt, value): - if value in option.choices: - return value - else: - choices = ", ".join(map(repr, option.choices)) - raise OptionValueError( - "option %s: invalid choice: %r (choose from %s)" - % (opt, value, choices)) - -# Not supplying a default is different from a default of None, -# so we need an explicit "not supplied" value. -NO_DEFAULT = "NO"+"DEFAULT" - - -class Option: - """ - Instance attributes: - _short_opts : [string] - _long_opts : [string] - - action : string - type : string - dest : string - default : any - nargs : int - const : any - choices : [string] - callback : function - callback_args : (any*) - callback_kwargs : { string : any } - help : string - metavar : string - """ - - # The list of instance attributes that may be set through - # keyword args to the constructor. - ATTRS = ['action', - 'type', - 'dest', - 'default', - 'nargs', - 'const', - 'choices', - 'callback', - 'callback_args', - 'callback_kwargs', - 'help', - 'metavar'] - - # The set of actions allowed by option parsers. Explicitly listed - # here so the constructor can validate its arguments. - ACTIONS = ("store", - "store_const", - "store_true", - "store_false", - "append", - "count", - "callback", - "help", - "version") - - # The set of actions that involve storing a value somewhere; - # also listed just for constructor argument validation. (If - # the action is one of these, there must be a destination.) - STORE_ACTIONS = ("store", - "store_const", - "store_true", - "store_false", - "append", - "count") - - # The set of actions for which it makes sense to supply a value - # type, ie. where we expect an argument to this option. - TYPED_ACTIONS = ("store", - "append", - "callback") - - # The set of known types for option parsers. Again, listed here for - # constructor argument validation. - TYPES = ("string", "int", "long", "float", "complex", "choice") - - # Dictionary of argument checking functions, which convert and - # validate option arguments according to the option type. - # - # Signature of checking functions is: - # check(option : Option, opt : string, value : string) -> any - # where - # option is the Option instance calling the checker - # opt is the actual option seen on the command-line - # (eg. "-a", "--file") - # value is the option argument seen on the command-line - # - # The return value should be in the appropriate Python type - # for option.type -- eg. an integer if option.type == "int". - # - # If no checker is defined for a type, arguments will be - # unchecked and remain strings. - TYPE_CHECKER = { "int" : check_builtin, - "long" : check_builtin, - "float" : check_builtin, - "complex" : check_builtin, - "choice" : check_choice, - } - - - # CHECK_METHODS is a list of unbound method objects; they are called - # by the constructor, in order, after all attributes are - # initialized. The list is created and filled in later, after all - # the methods are actually defined. (I just put it here because I - # like to define and document all class attributes in the same - # place.) Subclasses that add another _check_*() method should - # define their own CHECK_METHODS list that adds their check method - # to those from this class. - CHECK_METHODS = None - - - # -- Constructor/initialization methods ---------------------------- - - def __init__ (self, *opts, **attrs): - # Set _short_opts, _long_opts attrs from 'opts' tuple. - # Have to be set now, in case no option strings are supplied. - self._short_opts = [] - self._long_opts = [] - opts = self._check_opt_strings(opts) - self._set_opt_strings(opts) - - # Set all other attrs (action, type, etc.) from 'attrs' dict - self._set_attrs(attrs) - - # Check all the attributes we just set. There are lots of - # complicated interdependencies, but luckily they can be farmed - # out to the _check_*() methods listed in CHECK_METHODS -- which - # could be handy for subclasses! The one thing these all share - # is that they raise OptionError if they discover a problem. - for checker in self.CHECK_METHODS: - checker(self) - - def _check_opt_strings (self, opts): - # Filter out None because early versions of Optik had exactly - # one short option and one long option, either of which - # could be None. - opts = filter(None, opts) - if not opts: - raise TypeError("at least one option string must be supplied") - return opts - - def _set_opt_strings (self, opts): - for opt in opts: - if len(opt) < 2: - raise OptionError( - "invalid option string %r: " - "must be at least two characters long" % opt, self) - elif len(opt) == 2: - if not (opt[0] == "-" and opt[1] != "-"): - raise OptionError( - "invalid short option string %r: " - "must be of the form -x, (x any non-dash char)" % opt, - self) - self._short_opts.append(opt) - else: - if not (opt[0:2] == "--" and opt[2] != "-"): - raise OptionError( - "invalid long option string %r: " - "must start with --, followed by non-dash" % opt, - self) - self._long_opts.append(opt) - - def _set_attrs (self, attrs): - for attr in self.ATTRS: - if attrs.has_key(attr): - setattr(self, attr, attrs[attr]) - del attrs[attr] - else: - if attr == 'default': - setattr(self, attr, NO_DEFAULT) - else: - setattr(self, attr, None) - if attrs: - raise OptionError( - "invalid keyword arguments: %s" % ", ".join(attrs.keys()), - self) - - - # -- Constructor validation methods -------------------------------- - - def _check_action (self): - if self.action is None: - self.action = "store" - elif self.action not in self.ACTIONS: - raise OptionError("invalid action: %r" % self.action, self) - - def _check_type (self): - if self.type is None: - # XXX should factor out another class attr here: list of - # actions that *require* a type - if self.action in ("store", "append"): - if self.choices is not None: - # The "choices" attribute implies "choice" type. - self.type = "choice" - else: - # No type given? "string" is the most sensible default. - self.type = "string" - else: - if self.type not in self.TYPES: - raise OptionError("invalid option type: %r" % self.type, self) - if self.action not in self.TYPED_ACTIONS: - raise OptionError( - "must not supply a type for action %r" % self.action, self) - - def _check_choice(self): - if self.type == "choice": - if self.choices is None: - raise OptionError( - "must supply a list of choices for type 'choice'", self) - elif type(self.choices) not in (types.TupleType, types.ListType): - raise OptionError( - "choices must be a list of strings ('%s' supplied)" - % str(type(self.choices)).split("'")[1], self) - elif self.choices is not None: - raise OptionError( - "must not supply choices for type %r" % self.type, self) - - def _check_dest (self): - if self.action in self.STORE_ACTIONS and self.dest is None: - # No destination given, and we need one for this action. - # Glean a destination from the first long option string, - # or from the first short option string if no long options. - if self._long_opts: - # eg. "--foo-bar" -> "foo_bar" - self.dest = self._long_opts[0][2:].replace('-', '_') - else: - self.dest = self._short_opts[0][1] - - def _check_const (self): - if self.action != "store_const" and self.const is not None: - raise OptionError( - "'const' must not be supplied for action %r" % self.action, - self) - - def _check_nargs (self): - if self.action in self.TYPED_ACTIONS: - if self.nargs is None: - self.nargs = 1 - elif self.nargs is not None: - raise OptionError( - "'nargs' must not be supplied for action %r" % self.action, - self) - - def _check_callback (self): - if self.action == "callback": - if not callable(self.callback): - raise OptionError( - "callback not callable: %r" % self.callback, self) - if (self.callback_args is not None and - type(self.callback_args) is not types.TupleType): - raise OptionError( - "callback_args, if supplied, must be a tuple: not %r" - % self.callback_args, self) - if (self.callback_kwargs is not None and - type(self.callback_kwargs) is not types.DictType): - raise OptionError( - "callback_kwargs, if supplied, must be a dict: not %r" - % self.callback_kwargs, self) - else: - if self.callback is not None: - raise OptionError( - "callback supplied (%r) for non-callback option" - % self.callback, self) - if self.callback_args is not None: - raise OptionError( - "callback_args supplied for non-callback option", self) - if self.callback_kwargs is not None: - raise OptionError( - "callback_kwargs supplied for non-callback option", self) - - - CHECK_METHODS = [_check_action, - _check_type, - _check_choice, - _check_dest, - _check_const, - _check_nargs, - _check_callback] - - - # -- Miscellaneous methods ----------------------------------------- - - def __str__ (self): - return "/".join(self._short_opts + self._long_opts) - - def takes_value (self): - return self.type is not None - - - # -- Processing methods -------------------------------------------- - - def check_value (self, opt, value): - checker = self.TYPE_CHECKER.get(self.type) - if checker is None: - return value - else: - return checker(self, opt, value) - - def process (self, opt, value, values, parser): - - # First, convert the value(s) to the right type. Howl if any - # value(s) are bogus. - if value is not None: - if self.nargs == 1: - value = self.check_value(opt, value) - else: - value = tuple([self.check_value(opt, v) for v in value]) - - # And then take whatever action is expected of us. - # This is a separate method to make life easier for - # subclasses to add new actions. - return self.take_action( - self.action, self.dest, opt, value, values, parser) - - def take_action (self, action, dest, opt, value, values, parser): - if action == "store": - setattr(values, dest, value) - elif action == "store_const": - setattr(values, dest, self.const) - elif action == "store_true": - setattr(values, dest, True) - elif action == "store_false": - setattr(values, dest, False) - elif action == "append": - values.ensure_value(dest, []).append(value) - elif action == "count": - setattr(values, dest, values.ensure_value(dest, 0) + 1) - elif action == "callback": - args = self.callback_args or () - kwargs = self.callback_kwargs or {} - self.callback(self, opt, value, parser, *args, **kwargs) - elif action == "help": - parser.print_help() - sys.exit(0) - elif action == "version": - parser.print_version() - sys.exit(0) - else: - raise RuntimeError, "unknown action %r" % self.action - - return 1 - -# class Option -"""optik.option_parser - -Provides the OptionParser and Values classes. -""" - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -# created 2001/10/17, GPW (from optik.py) - - - -def get_prog_name (): - return os.path.basename(sys.argv[0]) - - -SUPPRESS_HELP = "SUPPRESS"+"HELP" -SUPPRESS_USAGE = "SUPPRESS"+"USAGE" - -STD_HELP_OPTION = Option("-h", "--help", - action="help", - help="show this help message and exit") -STD_VERSION_OPTION = Option("--version", - action="version", - help="show program's version number and exit") - - -class Values: - - def __init__ (self, defaults=None): - if defaults: - for (attr, val) in defaults.items(): - setattr(self, attr, val) - - def __repr__ (self): - return ("<%s at 0x%x: %r>" - % (self.__class__.__name__, id(self), self.__dict__)) - - def _update_careful (self, dict): - """ - Update the option values from an arbitrary dictionary, but only - use keys from dict that already have a corresponding attribute - in self. Any keys in dict without a corresponding attribute - are silently ignored. - """ - for attr in dir(self): - if dict.has_key(attr): - dval = dict[attr] - if dval is not None: - setattr(self, attr, dval) - - def _update_loose (self, dict): - """ - Update the option values from an arbitrary dictionary, - using all keys from the dictionary regardless of whether - they have a corresponding attribute in self or not. - """ - self.__dict__.update(dict) - - def _update (self, dict, mode): - if mode == "careful": - self._update_careful(dict) - elif mode == "loose": - self._update_loose(dict) - else: - raise ValueError, "invalid update mode: %r" % mode - - def read_module (self, modname, mode="careful"): - __import__(modname) - mod = sys.modules[modname] - self._update(vars(mod), mode) - - def read_file (self, filename, mode="careful"): - vars = {} - execfile(filename, vars) - self._update(vars, mode) - - def ensure_value (self, attr, value): - if not hasattr(self, attr) or getattr(self, attr) is None: - setattr(self, attr, value) - return getattr(self, attr) - - -class OptionContainer: - - """ - Abstract base class. - - Class attributes: - standard_option_list : [Option] - list of standard options that will be accepted by all instances - of this parser class (intended to be overridden by subclasses). - - Instance attributes: - option_list : [Option] - the list of Option objects contained by this OptionContainer - _short_opt : { string : Option } - dictionary mapping short option strings, eg. "-f" or "-X", - to the Option instances that implement them. If an Option - has multiple short option strings, it will appears in this - dictionary multiple times. [1] - _long_opt : { string : Option } - dictionary mapping long option strings, eg. "--file" or - "--exclude", to the Option instances that implement them. - Again, a given Option can occur multiple times in this - dictionary. [1] - defaults : { string : any } - dictionary mapping option destination names to default - values for each destination [1] - - [1] These mappings are common to (shared by) all components of the - controlling OptionParser, where they are initially created. - - """ - - def __init__ (self, option_class, conflict_handler, description): - # Initialize the option list and related data structures. - # This method must be provided by subclasses, and it must - # initialize at least the following instance attributes: - # option_list, _short_opt, _long_opt, defaults. - self._create_option_list() - - self.option_class = option_class - self.set_conflict_handler(conflict_handler) - self.set_description(description) - - def _create_option_mappings (self): - # For use by OptionParser constructor -- create the master - # option mappings used by this OptionParser and all - # OptionGroups that it owns. - self._short_opt = {} # single letter -> Option instance - self._long_opt = {} # long option -> Option instance - self.defaults = {} # maps option dest -> default value - - - def _share_option_mappings (self, parser): - # For use by OptionGroup constructor -- use shared option - # mappings from the OptionParser that owns this OptionGroup. - self._short_opt = parser._short_opt - self._long_opt = parser._long_opt - self.defaults = parser.defaults - - def set_conflict_handler (self, handler): - if handler not in ("ignore", "error", "resolve"): - raise ValueError, "invalid conflict_resolution value %r" % handler - self.conflict_handler = handler - - def set_description (self, description): - self.description = description - - - # -- Option-adding methods ----------------------------------------- - - def _check_conflict (self, option): - conflict_opts = [] - for opt in option._short_opts: - if self._short_opt.has_key(opt): - conflict_opts.append((opt, self._short_opt[opt])) - for opt in option._long_opts: - if self._long_opt.has_key(opt): - conflict_opts.append((opt, self._long_opt[opt])) - - if conflict_opts: - handler = self.conflict_handler - if handler == "ignore": # behaviour for Optik 1.0, 1.1 - pass - elif handler == "error": # new in 1.2 - raise OptionConflictError( - "conflicting option string(s): %s" - % ", ".join([co[0] for co in conflict_opts]), - option) - elif handler == "resolve": # new in 1.2 - for (opt, c_option) in conflict_opts: - if opt.startswith("--"): - c_option._long_opts.remove(opt) - del self._long_opt[opt] - else: - c_option._short_opts.remove(opt) - del self._short_opt[opt] - if not (c_option._short_opts or c_option._long_opts): - c_option.container.option_list.remove(c_option) - - def add_option (self, *args, **kwargs): - """add_option(Option) - add_option(opt_str, ..., kwarg=val, ...) - """ - if type(args[0]) is types.StringType: - option = self.option_class(*args, **kwargs) - elif len(args) == 1 and not kwargs: - option = args[0] - if not isinstance(option, Option): - raise TypeError, "not an Option instance: %r" % option - else: - raise TypeError, "invalid arguments" - - self._check_conflict(option) - - self.option_list.append(option) - option.container = self - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - if option.dest is not None: # option has a dest, we need a default - if option.default is not NO_DEFAULT: - self.defaults[option.dest] = option.default - elif not self.defaults.has_key(option.dest): - self.defaults[option.dest] = None - - return option - - def add_options (self, option_list): - for option in option_list: - self.add_option(option) - - # -- Option query/removal methods ---------------------------------- - - def get_option (self, opt_str): - return (self._short_opt.get(opt_str) or - self._long_opt.get(opt_str)) - - def has_option (self, opt_str): - return (self._short_opt.has_key(opt_str) or - self._long_opt.has_key(opt_str)) - - def remove_option (self, opt_str): - option = self._short_opt.get(opt_str) - if option is None: - option = self._long_opt.get(opt_str) - if option is None: - raise ValueError("no such option %r" % opt_str) - - for opt in option._short_opts: - del self._short_opt[opt] - for opt in option._long_opts: - del self._long_opt[opt] - option.container.option_list.remove(option) - - - # -- Help-formatting methods --------------------------------------- - - def format_option_help (self, formatter): - if not self.option_list: - return "" - result = [] - for option in self.option_list: - if not option.help is SUPPRESS_HELP: - result.append(formatter.format_option(option)) - return "".join(result) - - def format_description (self, formatter): - if self.description: - return formatter.format_description(self.description) - else: - return "" - - def format_help (self, formatter): - if self.description: - desc = self.format_description(formatter) + "\n" - else: - desc = "" - return desc + self.format_option_help(formatter) - - -class OptionGroup (OptionContainer): - - def __init__ (self, parser, title, description=None): - self.parser = parser - OptionContainer.__init__( - self, parser.option_class, parser.conflict_handler, description) - self.title = title - - def _create_option_list (self): - self.option_list = [] - self._share_option_mappings(self.parser) - - def set_title (self, title): - self.title = title - - # -- Help-formatting methods --------------------------------------- - - def format_help (self, formatter): - result = formatter.format_heading(self.title) - formatter.indent() - result += OptionContainer.format_help(self, formatter) - formatter.dedent() - return result - - -class OptionParser (OptionContainer): - - """ - Class attributes: - standard_option_list : [Option] - list of standard options that will be accepted by all instances - of this parser class (intended to be overridden by subclasses). - - Instance attributes: - usage : string - a usage string for your program. Before it is displayed - to the user, "%prog" will be expanded to the name of - your program (self.prog or os.path.basename(sys.argv[0])). - prog : string - the name of the current program (to override - os.path.basename(sys.argv[0])). - - allow_interspersed_args : boolean = true - if true, positional arguments may be interspersed with options. - Assuming -a and -b each take a single argument, the command-line - -ablah foo bar -bboo baz - will be interpreted the same as - -ablah -bboo -- foo bar baz - If this flag were false, that command line would be interpreted as - -ablah -- foo bar -bboo baz - -- ie. we stop processing options as soon as we see the first - non-option argument. (This is the tradition followed by - Python's getopt module, Perl's Getopt::Std, and other argument- - parsing libraries, but it is generally annoying to users.) - - rargs : [string] - the argument list currently being parsed. Only set when - parse_args() is active, and continually trimmed down as - we consume arguments. Mainly there for the benefit of - callback options. - largs : [string] - the list of leftover arguments that we have skipped while - parsing options. If allow_interspersed_args is false, this - list is always empty. - values : Values - the set of option values currently being accumulated. Only - set when parse_args() is active. Also mainly for callbacks. - - Because of the 'rargs', 'largs', and 'values' attributes, - OptionParser is not thread-safe. If, for some perverse reason, you - need to parse command-line arguments simultaneously in different - threads, use different OptionParser instances. - - """ - - standard_option_list = [] - - def __init__ (self, - usage=None, - option_list=None, - option_class=Option, - version=None, - conflict_handler="error", - description=None, - formatter=None, - add_help_option=1, - prog=None): - OptionContainer.__init__( - self, option_class, conflict_handler, description) - self.set_usage(usage) - self.prog = prog - self.version = version - self.allow_interspersed_args = 1 - if formatter is None: - formatter = IndentedHelpFormatter() - self.formatter = formatter - - # Populate the option list; initial sources are the - # standard_option_list class attribute, the 'option_list' - # argument, and the STD_VERSION_OPTION (if 'version' supplied) - # and STD_HELP_OPTION globals. - self._populate_option_list(option_list, - add_help=add_help_option) - - self._init_parsing_state() - - # -- Private methods ----------------------------------------------- - # (used by our or OptionContainer's constructor) - - def _create_option_list (self): - self.option_list = [] - self.option_groups = [] - self._create_option_mappings() - - def _populate_option_list (self, option_list, add_help=1): - if self.standard_option_list: - self.add_options(self.standard_option_list) - if option_list: - self.add_options(option_list) - if self.version: - self.add_option(STD_VERSION_OPTION) - if add_help: - self.add_option(STD_HELP_OPTION) - - def _init_parsing_state (self): - # These are set in parse_args() for the convenience of callbacks. - self.rargs = None - self.largs = None - self.values = None - - - # -- Simple modifier methods --------------------------------------- - - def set_usage (self, usage): - if usage is None: - self.usage = "%prog [options]" - elif usage is SUPPRESS_USAGE: - self.usage = None - elif usage.startswith("usage: "): - # for backwards compatibility with Optik 1.3 and earlier - self.usage = usage[7:] - else: - self.usage = usage - - def enable_interspersed_args (self): - self.allow_interspersed_args = 1 - - def disable_interspersed_args (self): - self.allow_interspersed_args = 0 - - def set_default (self, dest, value): - self.defaults[dest] = value - - def set_defaults (self, **kwargs): - self.defaults.update(kwargs) - - def get_default_values (self): - return Values(self.defaults) - - - # -- OptionGroup methods ------------------------------------------- - - def add_option_group (self, *args, **kwargs): - # XXX lots of overlap with OptionContainer.add_option() - if type(args[0]) is types.StringType: - group = OptionGroup(self, *args, **kwargs) - elif len(args) == 1 and not kwargs: - group = args[0] - if not isinstance(group, OptionGroup): - raise TypeError, "not an OptionGroup instance: %r" % group - if group.parser is not self: - raise ValueError, "invalid OptionGroup (wrong parser)" - else: - raise TypeError, "invalid arguments" - - self.option_groups.append(group) - return group - - def get_option_group (self, opt_str): - option = (self._short_opt.get(opt_str) or - self._long_opt.get(opt_str)) - if option and option.container is not self: - return option.container - return None - - - # -- Option-parsing methods ---------------------------------------- - - def _get_args (self, args): - if args is None: - return sys.argv[1:] - else: - return args[:] # don't modify caller's list - - def parse_args (self, args=None, values=None): - """ - parse_args(args : [string] = sys.argv[1:], - values : Values = None) - -> (values : Values, args : [string]) - - Parse the command-line options found in 'args' (default: - sys.argv[1:]). Any errors result in a call to 'error()', which - by default prints the usage message to stderr and calls - sys.exit() with an error message. On success returns a pair - (values, args) where 'values' is an Values instance (with all - your option values) and 'args' is the list of arguments left - over after parsing options. - """ - rargs = self._get_args(args) - if values is None: - values = self.get_default_values() - - # Store the halves of the argument list as attributes for the - # convenience of callbacks: - # rargs - # the rest of the command-line (the "r" stands for - # "remaining" or "right-hand") - # largs - # the leftover arguments -- ie. what's left after removing - # options and their arguments (the "l" stands for "leftover" - # or "left-hand") - self.rargs = rargs - self.largs = largs = [] - self.values = values - - try: - stop = self._process_args(largs, rargs, values) - except (BadOptionError, OptionValueError), err: - self.error(err.msg) - - args = largs + rargs - return self.check_values(values, args) - - def check_values (self, values, args): - """ - check_values(values : Values, args : [string]) - -> (values : Values, args : [string]) - - Check that the supplied option values and leftover arguments are - valid. Returns the option values and leftover arguments - (possibly adjusted, possibly completely new -- whatever you - like). Default implementation just returns the passed-in - values; subclasses may override as desired. - """ - return (values, args) - - def _process_args (self, largs, rargs, values): - """_process_args(largs : [string], - rargs : [string], - values : Values) - - Process command-line arguments and populate 'values', consuming - options and arguments from 'rargs'. If 'allow_interspersed_args' is - false, stop at the first non-option argument. If true, accumulate any - interspersed non-option arguments in 'largs'. - """ - while rargs: - arg = rargs[0] - # We handle bare "--" explicitly, and bare "-" is handled by the - # standard arg handler since the short arg case ensures that the - # len of the opt string is greater than 1. - if arg == "--": - del rargs[0] - return - elif arg[0:2] == "--": - # process a single long option (possibly with value(s)) - self._process_long_opt(rargs, values) - elif arg[:1] == "-" and len(arg) > 1: - # process a cluster of short options (possibly with - # value(s) for the last one only) - self._process_short_opts(rargs, values) - elif self.allow_interspersed_args: - largs.append(arg) - del rargs[0] - else: - return # stop now, leave this arg in rargs - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt (self, opt): - """_match_long_opt(opt : string) -> string - - Determine which long option string 'opt' matches, ie. which one - it is an unambiguous abbrevation for. Raises BadOptionError if - 'opt' doesn't unambiguously match any long option string. - """ - return _match_abbrev(opt, self._long_opt) - - def _process_long_opt (self, rargs, values): - arg = rargs.pop(0) - - # Value explicitly attached to arg? Pretend it's the next - # argument. - if "=" in arg: - (opt, next_arg) = arg.split("=", 1) - rargs.insert(0, next_arg) - had_explicit_value = 1 - else: - opt = arg - had_explicit_value = 0 - - opt = self._match_long_opt(opt) - option = self._long_opt[opt] - if option.takes_value(): - nargs = option.nargs - if len(rargs) < nargs: - if nargs == 1: - self.error("%s option requires a value" % opt) - else: - self.error("%s option requires %d values" - % (opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - elif had_explicit_value: - self.error("%s option does not take a value" % opt) - - else: - value = None - - option.process(opt, value, values, self) - - def _process_short_opts (self, rargs, values): - arg = rargs.pop(0) - stop = 0 - i = 1 - for ch in arg[1:]: - opt = "-" + ch - option = self._short_opt.get(opt) - i += 1 # we have consumed a character - - if not option: - self.error("no such option: %s" % opt) - if option.takes_value(): - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - rargs.insert(0, arg[i:]) - stop = 1 - - nargs = option.nargs - if len(rargs) < nargs: - if nargs == 1: - self.error("%s option requires a value" % opt) - else: - self.error("%s option requires %s values" - % (opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - else: # option doesn't take a value - value = None - - option.process(opt, value, values, self) - - if stop: - break - - - # -- Feedback methods ---------------------------------------------- - - def error (self, msg): - """error(msg : string) - - Print a usage message incorporating 'msg' to stderr and exit. - If you override this in a subclass, it should not return -- it - should either exit or raise an exception. - """ - self.print_usage(sys.stderr) - sys.exit("%s: error: %s" % (get_prog_name(), msg)) - - def get_usage (self): - if self.usage: - return self.formatter.format_usage( - self.usage.replace("%prog", get_prog_name())) - else: - return "" - - def print_usage (self, file=None): - """print_usage(file : file = stdout) - - Print the usage message for the current program (self.usage) to - 'file' (default stdout). Any occurence of the string "%prog" in - self.usage is replaced with the name of the current program - (basename of sys.argv[0]). Does nothing if self.usage is empty - or not defined. - """ - if self.usage: - print >>file, self.get_usage() - - def get_version (self): - if self.version: - return self.version.replace("%prog", get_prog_name()) - else: - return "" - - def print_version (self, file=None): - """print_version(file : file = stdout) - - Print the version message for this program (self.version) to - 'file' (default stdout). As with print_usage(), any occurence - of "%prog" in self.version is replaced by the current program's - name. Does nothing if self.version is empty or undefined. - """ - if self.version: - print >>file, self.get_version() - - def format_option_help (self, formatter=None): - if formatter is None: - formatter = self.formatter - formatter.store_option_strings(self) - result = [] - result.append(formatter.format_heading("options")) - formatter.indent() - if self.option_list: - result.append(OptionContainer.format_option_help(self, formatter)) - result.append("\n") - for group in self.option_groups: - result.append(group.format_help(formatter)) - result.append("\n") - formatter.dedent() - # Drop the last "\n", or the header if no options or option groups: - return "".join(result[:-1]) - - def format_help (self, formatter=None): - if formatter is None: - formatter = self.formatter - result = [] - if self.usage: - result.append(self.get_usage() + "\n") - if self.description: - result.append(self.format_description(formatter) + "\n") - result.append(self.format_option_help(formatter)) - return "".join(result) - - def print_help (self, file=None): - """print_help(file : file = stdout) - - Print an extended help message, listing all options and any - help text provided with them, to 'file' (default stdout). - """ - if file is None: - file = sys.stdout - file.write(self.format_help()) - -# class OptionParser - - -def _match_abbrev (s, wordmap): - """_match_abbrev(s : string, wordmap : {string : Option}) -> string - - Return the string key in 'wordmap' for which 's' is an unambiguous - abbreviation. If 's' is found to be ambiguous or doesn't match any of - 'words', raise BadOptionError. - """ - # Is there an exact match? - if wordmap.has_key(s): - return s - else: - # Isolate all words with s as a prefix. - possibilities = [word for word in wordmap.keys() - if word.startswith(s)] - # No exact match, so there had better be just one possibility. - if len(possibilities) == 1: - return possibilities[0] - elif not possibilities: - raise BadOptionError("no such option: %s" % s) - else: - # More than one possible completion: ambiguous prefix. - raise BadOptionError("ambiguous option: %s (%s?)" - % (s, ", ".join(possibilities))) -"""Text wrapping and filling. -""" - -# Copyright (C) 1999-2001 Gregory P. Ward. -# Copyright (C) 2002, 2003 Python Software Foundation. -# Written by Greg Ward - - -# Do the right thing with boolean values for all known Python versions. -try: - True, False -except NameError: - (True, False) = (1, 0) - -class TextWrapper: - """ - Object for wrapping/filling text. The public interface consists of - the wrap() and fill() methods; the other methods are just there for - subclasses to override in order to tweak the default behaviour. - If you want to completely replace the main wrapping algorithm, - you'll probably have to override _wrap_chunks(). - - Several instance attributes control various aspects of wrapping: - width (default: 70) - the maximum width of wrapped lines (unless break_long_words - is false) - initial_indent (default: "") - string that will be prepended to the first line of wrapped - output. Counts towards the line's width. - subsequent_indent (default: "") - string that will be prepended to all lines save the first - of wrapped output; also counts towards each line's width. - expand_tabs (default: true) - Expand tabs in input text to spaces before further processing. - Each tab will become 1 .. 8 spaces, depending on its position in - its line. If false, each tab is treated as a single character. - replace_whitespace (default: true) - Replace all whitespace characters in the input text by spaces - after tab expansion. Note that if expand_tabs is false and - replace_whitespace is true, every tab will be converted to a - single space! - fix_sentence_endings (default: false) - Ensure that sentence-ending punctuation is always followed - by two spaces. Off by default becaus the algorithm is - (unavoidably) imperfect. - break_long_words (default: true) - Break words longer than 'width'. If false, those words will not - be broken, and some lines might be longer than 'width'. - """ - - whitespace_trans = string.maketrans(string.whitespace, - ' ' * len(string.whitespace)) - - # This funky little regex is just the trick for splitting - # text up into word-wrappable chunks. E.g. - # "Hello there -- you goof-ball, use the -b option!" - # splits into - # Hello/ /there/ /--/ /you/ /goof-/ball,/ /use/ /the/ /-b/ /option! - # (after stripping out empty strings). - wordsep_re = re.compile(r'(\s+|' # any whitespace - r'-*\w{2,}-(?=\w{2,})|' # hyphenated words - r'(?<=\S)-{2,}(?=\w))') # em-dash - - # XXX will there be a locale-or-charset-aware version of - # string.lowercase in 2.3? - sentence_end_re = re.compile(r'[%s]' # lowercase letter - r'[\.\!\?]' # sentence-ending punct. - r'[\"\']?' # optional end-of-quote - % string.lowercase) - - - def __init__ (self, - width=70, - initial_indent="", - subsequent_indent="", - expand_tabs=True, - replace_whitespace=True, - fix_sentence_endings=False, - break_long_words=True): - self.width = width - self.initial_indent = initial_indent - self.subsequent_indent = subsequent_indent - self.expand_tabs = expand_tabs - self.replace_whitespace = replace_whitespace - self.fix_sentence_endings = fix_sentence_endings - self.break_long_words = break_long_words - - - # -- Private methods ----------------------------------------------- - # (possibly useful for subclasses to override) - - def _munge_whitespace(self, text): - """_munge_whitespace(text : string) -> string - - Munge whitespace in text: expand tabs and convert all other - whitespace characters to spaces. Eg. " foo\tbar\n\nbaz" - becomes " foo bar baz". - """ - if self.expand_tabs: - text = text.expandtabs() - if self.replace_whitespace: - text = text.translate(self.whitespace_trans) - return text - - - def _split(self, text): - """_split(text : string) -> [string] - - Split the text to wrap into indivisible chunks. Chunks are - not quite the same as words; see wrap_chunks() for full - details. As an example, the text - Look, goof-ball -- use the -b option! - breaks into the following chunks: - 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ', - 'use', ' ', 'the', ' ', '-b', ' ', 'option!' - """ - chunks = self.wordsep_re.split(text) - chunks = filter(None, chunks) - return chunks - - def _fix_sentence_endings(self, chunks): - """_fix_sentence_endings(chunks : [string]) - - Correct for sentence endings buried in 'chunks'. Eg. when the - original text contains "... foo.\nBar ...", munge_whitespace() - and split() will convert that to [..., "foo.", " ", "Bar", ...] - which has one too few spaces; this method simply changes the one - space to two. - """ - i = 0 - pat = self.sentence_end_re - while i < len(chunks)-1: - if chunks[i+1] == " " and pat.search(chunks[i]): - chunks[i+1] = " " - i += 2 - else: - i += 1 - - def _handle_long_word(self, chunks, cur_line, cur_len, width): - """_handle_long_word(chunks : [string], - cur_line : [string], - cur_len : int, width : int) - - Handle a chunk of text (most likely a word, not whitespace) that - is too long to fit in any line. - """ - space_left = width - cur_len - - # If we're allowed to break long words, then do so: put as much - # of the next chunk onto the current line as will fit. - if self.break_long_words: - cur_line.append(chunks[0][0:space_left]) - chunks[0] = chunks[0][space_left:] - - # Otherwise, we have to preserve the long word intact. Only add - # it to the current line if there's nothing already there -- - # that minimizes how much we violate the width constraint. - elif not cur_line: - cur_line.append(chunks.pop(0)) - - # If we're not allowed to break long words, and there's already - # text on the current line, do nothing. Next time through the - # main loop of _wrap_chunks(), we'll wind up here again, but - # cur_len will be zero, so the next line will be entirely - # devoted to the long word that we can't handle right now. - - def _wrap_chunks(self, chunks): - """_wrap_chunks(chunks : [string]) -> [string] - - Wrap a sequence of text chunks and return a list of lines of - length 'self.width' or less. (If 'break_long_words' is false, - some lines may be longer than this.) Chunks correspond roughly - to words and the whitespace between them: each chunk is - indivisible (modulo 'break_long_words'), but a line break can - come between any two chunks. Chunks should not have internal - whitespace; ie. a chunk is either all whitespace or a "word". - Whitespace chunks will be removed from the beginning and end of - lines, but apart from that whitespace is preserved. - """ - lines = [] - - while chunks: - - # Start the list of chunks that will make up the current line. - # cur_len is just the length of all the chunks in cur_line. - cur_line = [] - cur_len = 0 - - # Figure out which static string will prefix this line. - if lines: - indent = self.subsequent_indent - else: - indent = self.initial_indent - - # Maximum width for this line. - width = self.width - len(indent) - - # First chunk on line is whitespace -- drop it. - if chunks[0].strip() == '': - del chunks[0] - - while chunks: - l = len(chunks[0]) - - # Can at least squeeze this chunk onto the current line. - if cur_len + l <= width: - cur_line.append(chunks.pop(0)) - cur_len += l - - # Nope, this line is full. - else: - break - - # The current line is full, and the next chunk is too big to - # fit on *any* line (not just this one). - if chunks and len(chunks[0]) > width: - self._handle_long_word(chunks, cur_line, cur_len, width) - - # If the last chunk on this line is all whitespace, drop it. - if cur_line and cur_line[-1].strip() == '': - del cur_line[-1] - - # Convert current line back to a string and store it in list - # of all lines (return value). - if cur_line: - lines.append(indent + ''.join(cur_line)) - - return lines - - - # -- Public interface ---------------------------------------------- - - def wrap(self, text): - """wrap(text : string) -> [string] - - Reformat the single paragraph in 'text' so it fits in lines of - no more than 'self.width' columns, and return a list of wrapped - lines. Tabs in 'text' are expanded with string.expandtabs(), - and all other whitespace characters (including newline) are - converted to space. - """ - text = self._munge_whitespace(text) - indent = self.initial_indent - if len(text) + len(indent) <= self.width: - return [indent + text] - chunks = self._split(text) - if self.fix_sentence_endings: - self._fix_sentence_endings(chunks) - return self._wrap_chunks(chunks) - - def fill(self, text): - """fill(text : string) -> string - - Reformat the single paragraph in 'text' to fit in lines of no - more than 'self.width' columns, and return a new string - containing the entire wrapped paragraph. - """ - return "\n".join(self.wrap(text)) - - -# -- Convenience interface --------------------------------------------- - -def wrap(text, width=70, **kwargs): - """Wrap a single paragraph of text, returning a list of wrapped lines. - - Reformat the single paragraph in 'text' so it fits in lines of no - more than 'width' columns, and return a list of wrapped lines. By - default, tabs in 'text' are expanded with string.expandtabs(), and - all other whitespace characters (including newline) are converted to - space. See TextWrapper class for available keyword args to customize - wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.wrap(text) - -def fill(text, width=70, **kwargs): - """Fill a single paragraph of text, returning a new string. - - Reformat the single paragraph in 'text' to fit in lines of no more - than 'width' columns, and return a new string containing the entire - wrapped paragraph. As with wrap(), tabs are expanded and other - whitespace characters converted to space. See TextWrapper class for - available keyword args to customize wrapping behaviour. - """ - w = TextWrapper(width=width, **kwargs) - return w.fill(text) - -# Copyright (c) 2001-2003 Gregory P. Ward. All rights reserved. -# See the README.txt distributed with Optik for licensing terms. - -__version__ = "1.4.1" - - - - -# Some day, there might be many Option classes. As of Optik 1.3, the -# preferred way to instantiate Options is indirectly, via make_option(), -# which will become a factory function when there are many Option -# classes. -make_option = Option Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Thu Jul 28 18:29:05 2005 @@ -2,20 +2,21 @@ # XXX needs clean-up and reorganization. import os -from pypy.tool import optik -make_option = optik.make_option +import optparse +make_option = optparse.make_option class Options: showwarning = 0 - spaces = [] + objspace = "std" oldstyle = 0 uselibfile = 0 - nofakedmodules = 0 - useparsermodule = "recparser" # "cpython" / "recparser" / "parser" + nofaking = 0 + parser = "recparser" # "cpython" / "recparser" / "parser" compiler = "pyparse" # "cpython" # "pyparse" pypy parser, cpython's compiler package # "pyparseapp" same, running the compiler at app-level # "pycomp" pypy parser and compiler (TBD) + usemodules = [] version = "2.4" # "native" / "2.3" / "2.4" def run_tb_server(option, opt, value, parser): @@ -25,23 +26,25 @@ def get_standard_options(): options = [] - def objspace_callback(option, opt, value, parser): - parser.values.spaces.append(value) - + def usemodules_callback(option, opt, value, parser): + parser.values.usemodules.append(value) + options.append(make_option( - '-o', '--objspace', action="callback", metavar='NAME', - callback=objspace_callback, type="string", + '-o', '--objspace', action="store", type="string", dest="objspace", help="object space to run PyPy on.")) - options.append(make_option( - '--oldstyle', action="store_true",dest="oldstyle", + '--usemodules', action="callback", metavar='NAME', + callback=usemodules_callback, type="string", + help="(mixed) modules to use.")) + options.append(make_option( + '--oldstyle', action="store_true", dest="oldstyle", help="enable oldstyle classes as default metaclass (std objspace only)")) options.append(make_option( - '--file', action="store_true",dest="uselibfile", + '--uselibfile', action="store_true", dest="uselibfile", help="enable our custom file implementation")) options.append(make_option( - '--nofakedmodules', action="store_true",dest="nofakedmodules", - help="don't fake any module")) + '--nofaking', action="store_true", dest="nofaking", + help="avoid faking of modules or objects")) options.append(make_option( '-w', action="store_true", dest="showwarning", help="enable warnings (disabled by default)")) @@ -51,12 +54,12 @@ help="use web browser for traceback info")) options.append(make_option( '--compiler', action="store", type="string", dest="compiler", - help="select the parser/compiler to use internally", - metavar="[cpython|pyparse|pyparseapp]")) + help="select the compiler approach to use internally", + metavar="[pyparser|cpython|pyparseapp]")) options.append(make_option( - '--parsermodule', action="store",type="string", dest="useparsermodule", + '--parser', action="store",type="string", dest="parser", help="select the parser module to use", - metavar="[cpython|recparser|parser]")) + metavar="[recparser|cpython|parser]")) ## for this to work the option module need to be loaded before the grammar! ## options.append(make_option( ## '--version', action="store",type="string", dest="version", @@ -68,29 +71,7 @@ def process_options(optionlist, input_options, argv=None): global Options Options = input_options - op = optik.OptionParser() + op = optparse.OptionParser() op.add_options(optionlist) options, args = op.parse_args(argv, input_options) return args - -def objspace(name='', _spacecache={}): - """ return singleton ObjSpace instance. - - this is configured via the environment variable OBJSPACE - """ - - if not name: - if Options.spaces: - name = Options.spaces[-1] - else: - name = os.environ.get('OBJSPACE', 'std') - - try: - return _spacecache[name] - except KeyError: - module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) - Space = module.Space - space = Space( Options() ) - if name == 'std' and Options.oldstyle: - space.enable_old_style_classes_as_default_metaclass() - return _spacecache.setdefault(name, space) Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Thu Jul 28 18:29:05 2005 @@ -1,10 +1,12 @@ from pypy.rpython.lltype import * from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace class TestLowLevelType: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def getcompiled(self, func, argstypelist=[]): t = Translator(func, simplifying=True) Modified: pypy/dist/pypy/translator/c/test/test_notype.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_notype.py (original) +++ pypy/dist/pypy/translator/c/test/test_notype.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,7 @@ import autopath from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace from pypy.translator.test import snippet @@ -9,7 +10,8 @@ buildpyxmodule.enable_fast_compilation() class TestNoTypeCGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, func, *morefuncs): try: func = func.im_func Modified: pypy/dist/pypy/translator/c/test/test_operation.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_operation.py (original) +++ pypy/dist/pypy/translator/c/test/test_operation.py Thu Jul 28 18:29:05 2005 @@ -1,6 +1,7 @@ import autopath from pypy.objspace.flow.model import * from pypy.objspace.flow.operation import FunctionByName +from pypy.objspace.flow import FlowObjSpace from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator @@ -95,7 +96,8 @@ class TestOperations: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, graph): t = Translator() Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Thu Jul 28 18:29:05 2005 @@ -38,11 +38,7 @@ # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False - from pypy.tool.option import Options - options = Options() - options.uselibfile = True - options.nofakedmodules = True - space = StdObjSpace(options) + space = StdObjSpace(nofaking=True) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') Modified: pypy/dist/pypy/translator/java/test/for_now_dont_test_javatrans.py ============================================================================== --- pypy/dist/pypy/translator/java/test/for_now_dont_test_javatrans.py (original) +++ pypy/dist/pypy/translator/java/test/for_now_dont_test_javatrans.py Thu Jul 28 18:29:05 2005 @@ -5,6 +5,7 @@ from pypy.translator.java.genjava import GenJava from pypy.translator.test import snippet from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace def setup_module(mod): @@ -16,7 +17,8 @@ class TestNoTypeCGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_jfunc(self, func): try: func = func.im_func Modified: pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py (original) +++ pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py Thu Jul 28 18:29:05 2005 @@ -6,6 +6,7 @@ from pypy.translator.tool.buildpyxmodule import build_cfunc from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator +from pypy.objspace.flow import FlowObjSpace from pypy import conftest #from pypy.conftest import option @@ -18,7 +19,8 @@ class TestNoTypePyrexGenTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def build_cfunc(self, func): try: func = func.im_func Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Thu Jul 28 18:29:05 2005 @@ -11,6 +11,7 @@ from pypy.annotation.dictdef import DictDef from pypy.objspace.flow.model import * from pypy.rpython.rarithmetic import r_uint +from pypy.objspace.flow import FlowObjSpace from pypy.translator.test import snippet @@ -34,7 +35,8 @@ class TestAnnotateTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() from pypy.translator.annrpython import RPythonAnnotator Modified: pypy/dist/pypy/translator/test/test_cltrans.py ============================================================================== --- pypy/dist/pypy/translator/test/test_cltrans.py (original) +++ pypy/dist/pypy/translator/test/test_cltrans.py Thu Jul 28 18:29:05 2005 @@ -2,6 +2,7 @@ from pypy.tool.udir import udir import py import os +from pypy.objspace.flow import FlowObjSpace def setup_module(mod): mod.global_cl = os.getenv("PYPY_CL") @@ -36,7 +37,8 @@ from pypy.translator.tool.buildcl import Literal class TestGenCLTestCase: - objspacename = 'flow' + def setup_class(cls): + cls.space = FlowObjSpace() def setup_method(self,method): if not global_cl: From hpk at codespeak.net Thu Jul 28 18:29:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 18:29:43 +0200 (CEST) Subject: [pypy-svn] r15271 - pypy/branch/pypy-newobjspace Message-ID: <20050728162943.C835727B8A@code1.codespeak.net> Author: hpk Date: Thu Jul 28 18:29:43 2005 New Revision: 15271 Removed: pypy/branch/pypy-newobjspace/ Log: branch is closed From arigo at codespeak.net Thu Jul 28 18:38:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 18:38:21 +0200 (CEST) Subject: [pypy-svn] r15273 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050728163821.960EE27B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 18:38:17 2005 New Revision: 15273 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/objspace/std/objspace.py Log: Added a 'space.default_compiler' so that when we have several ExecutionContexts they share the same compiler by default. This is needed right now to allow --compiler=pyparseapp to patch the 'default_compiler' after initialization. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 18:38:17 2005 @@ -226,13 +226,19 @@ def createcompiler(self): "Factory function creating a compiler object." # XXX simple selection logic for now - if self.options.compiler in ('pyparse', 'pyparseapp'): - return PythonCompiler(self) - elif self.options.compiler == 'cpython': - return CPythonCompiler(self) - else: - raise ValueError('unknown --compiler option value: %r' % ( - self.options.compiler,)) + try: + return self.default_compiler + except AttributeError: + if (self.options.compiler == 'pyparse' or + self.options.compiler == 'pyparseapp'): + compiler = PythonCompiler(self) + elif self.options.compiler == 'cpython': + compiler = CPythonCompiler(self) + else: + raise ValueError('unknown --compiler option value: %r' % ( + self.options.compiler,)) + self.default_compiler = compiler + return compiler # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Thu Jul 28 18:38:17 2005 @@ -274,13 +274,10 @@ w_nested_tuples, space.wrap(source_encoding)]) - from pypy.interpreter.error import debug_print - debug_print("app-level compiling...", newline=False) w_code = space.call_function(self.w_applevelcompile, w_nested_tuples, space.wrap(filename), space.wrap(mode)) - debug_print(" done") return w_code Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 18:38:17 2005 @@ -108,7 +108,8 @@ # XXX hack!: patch the compiler after initialization is complete if self.options.compiler == 'pyparseapp': from pypy.interpreter.pycompiler import PythonCompilerApp - self.getexecutioncontext().compiler = PythonCompilerApp(self) + self.default_compiler = PythonCompilerApp(self) + self.getexecutioncontext().compiler = self.default_compiler def enable_old_style_classes_as_default_metaclass(self): self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj) From ale at codespeak.net Thu Jul 28 18:47:20 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 28 Jul 2005 18:47:20 +0200 (CEST) Subject: [pypy-svn] r15274 - in pypy/dist/pypy: module/math rpython rpython/module rpython/module/test Message-ID: <20050728164720.E2D0127B85@code1.codespeak.net> Author: ale Date: Thu Jul 28 18:47:19 2005 New Revision: 15274 Modified: pypy/dist/pypy/module/math/__init__.py pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_math.py pypy/dist/pypy/rpython/module/test/test_ll_math.py Log: added math.fabs (needed for lib-python). test_cmath passes! Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Thu Jul 28 18:47:19 2005 @@ -18,8 +18,7 @@ 'hypot' : 'interp_math.hypot', #'tan' : 'interp_math.tan', #'asin' : 'interp_math.asin', - #'log' : 'interp_math.log', - #'fabs' : 'interp_math.fabs', + 'fabs' : 'interp_math.fabs', 'floor' : 'interp_math.floor', #'sqrt' : 'interp_math.sqrt', 'frexp' : 'interp_math.frexp', Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 28 18:47:19 2005 @@ -100,3 +100,4 @@ declare(math.exp , float , 'll_math/exp') declare(math.ldexp , float , 'll_math/ldexp') declare(math.modf , modfannotation, 'll_math/modf') +declare(math.fabs , float , 'll_math/fabs') Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Thu Jul 28 18:47:19 2005 @@ -88,3 +88,7 @@ fracpart, intpart = math.modf(x) return ll_modf_result(fracpart, intpart) ll_math_modf.suggested_primitive = True + +def ll_math_fabs(x): + return math.fabs(x) +ll_math_fabs.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_math.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_math.py Thu Jul 28 18:47:19 2005 @@ -30,6 +30,9 @@ def test_ll_math_sqrt(): assert ll_math_sqrt(10) == math.sqrt(10) -def test_ll_math_hypot(): - assert ll_math_hypot(math.pi/3,3) == math.hypot(math.pi/3,3) +def test_ll_math_fabs(): + assert ll_math_fabs(math.pi/3,3) == math.fabs(math.pi/3,3) +def test_ll_math_fabs(): + assert ll_math_fabs(math.pi/3) == math.fabs(math.pi/3) + assert ll_math_fabs(-math.pi/3) == math.fabs(-math.pi/3) From hpk at codespeak.net Thu Jul 28 18:51:17 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 18:51:17 +0200 (CEST) Subject: [pypy-svn] r15275 - pypy/dist/pypy/module/posix/test Message-ID: <20050728165117.6667E27B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 18:51:16 2005 New Revision: 15275 Added: pypy/dist/pypy/module/posix/test/test_posix2.py Log: added some basic tests that actually test the appvisible posix module Added: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Thu Jul 28 18:51:16 2005 @@ -0,0 +1,33 @@ +from pypy.objspace.std import StdObjSpace +from pypy.tool.udir import udir + +def setup_module(mod): + mod.space = StdObjSpace(usemodules=['posix']) + mod.path = udir.join('posixtestfile.txt') + mod.path.write("this is a test") + +class AppTestPosix: + def setup_class(cls): + cls.space = space + + def test_posix_is_pypy_s(self): + import posix + assert posix.__file__ + +def test_some_posix_basic_operation(): + w_path = space.wrap(str(path)) + space.appexec([w_path], """(path): + import posix + fd = posix.open(path, posix.O_RDONLY, 0777) + fd2 = posix.dup(fd) + assert not posix.isatty(fd2) + s = posix.read(fd, 1) + assert s == 't' + posix.lseek(fd, 5, 0) + s = posix.read(fd, 1) + assert s == 'i' + stat = posix.fstat(fd) + assert stat # XXX + posix.close(fd2) + posix.close(fd) + """) From rxe at codespeak.net Thu Jul 28 19:03:19 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 19:03:19 +0200 (CEST) Subject: [pypy-svn] r15276 - pypy/dist/pypy/objspace Message-ID: <20050728170319.A2C9527B85@code1.codespeak.net> Author: rxe Date: Thu Jul 28 19:03:15 2005 New Revision: 15276 Modified: pypy/dist/pypy/objspace/trace.py Log: Get rid of remaining XXXs (for now!). Modified: pypy/dist/pypy/objspace/trace.py ============================================================================== --- pypy/dist/pypy/objspace/trace.py (original) +++ pypy/dist/pypy/objspace/trace.py Thu Jul 28 19:03:15 2005 @@ -58,7 +58,8 @@ self.reentrant = True self.tracespace = tracespace self.printer = ResultPrinter(**printer_options) - + self._cache = {} + def append(self, event): if self.reentrant: self.reentrant = False @@ -81,13 +82,13 @@ for event in self.events: yield event - def getdisresult(self, frame, _cache = {}): # XXX Should perhaps be local to TraceResult + def getdisresult(self, frame): """ return (possibly cached) pydis result for the given frame. """ try: - return _cache[id(frame.pycode)] + return self._cache[id(frame.pycode)] except KeyError: - res = _cache[id(frame.pycode)] = pydis.pydis(frame.pycode) + res = self._cache[id(frame.pycode)] = pydis.pydis(frame.pycode) assert res is not None return res @@ -171,9 +172,9 @@ def create_trace_space(space, operations = None): """ Will create a trace object space if no space supplied. Otherwise - will turn the supplied into a tracable space by extending its class.""" + will turn the supplied into a traceable space by extending its class.""" - # Don't trace an already tracable space + # Don't trace an already traceable space if hasattr(space, "__pypytrace__"): return space @@ -223,10 +224,7 @@ trace_clz = type("Trace%s" % repr(space), (Trace,), {}) space.__oldclass__, space.__class__ = space.__class__, trace_clz - # XXX TEMP - also if we do use a config file, should use execfile - from pypy.tool.traceconfig import config - config_options = {} - config_options.update(config) + from pypy.tool.traceconfig import config as config_options # Avoid __getattribute__() woes space._in_cache = 0 From rxe at codespeak.net Thu Jul 28 19:08:48 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 19:08:48 +0200 (CEST) Subject: [pypy-svn] r15277 - pypy/dist/pypy/tool Message-ID: <20050728170848.2A60527B85@code1.codespeak.net> Author: rxe Date: Thu Jul 28 19:08:46 2005 New Revision: 15277 Modified: pypy/dist/pypy/tool/traceop.py Log: Fix up to instantiate std object space ourselves. Modified: pypy/dist/pypy/tool/traceop.py ============================================================================== --- pypy/dist/pypy/tool/traceop.py (original) +++ pypy/dist/pypy/tool/traceop.py Thu Jul 28 19:08:46 2005 @@ -365,16 +365,10 @@ if __name__ == '__main__': - from pypy.objspace import trace - from pypy.tool import option - args = option.process_options(option.get_standard_options(), - option.Options) + from pypy.objspace import std, trace - # Create objspace... - space = option.objspace() - - # Wrap up our space, with a trace space - tspace = trace.create_trace_space(space) + # Wrap up std space, with a trace space + tspace = trace.create_trace_space(std.Space()) def func(x): count = 0 From arigo at codespeak.net Thu Jul 28 19:26:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 19:26:01 +0200 (CEST) Subject: [pypy-svn] r15278 - in pypy/dist/pypy: annotation translator translator/test Message-ID: <20050728172601.11D8F27B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 19:25:55 2005 New Revision: 15278 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/test/test_annrpython.py Log: * Hide AttributeErrors in the annotator, using the can_only_throw mechanism. * Bug fix in said mechanism. * Test. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jul 28 19:25:55 2005 @@ -137,6 +137,7 @@ getbookkeeper().warning('getattr(%r, %r) is not RPythonic enough' % (obj, s_attr)) return SomeObject() + getattr.can_only_throw = [] def bindcallables(obj, classdef): return obj # default unbound __get__ implementation @@ -375,6 +376,7 @@ ins.classdef.check_missing_attribute_update(attr) return s_result return SomeObject() + getattr.can_only_throw = [] def setattr(ins, s_attr, s_value): if s_attr.is_constant() and isinstance(s_attr.const, str): @@ -413,6 +415,7 @@ def getattr(pbc, s_attr): bookkeeper = getbookkeeper() return bookkeeper.pbc_getattr(pbc, s_attr) + getattr.can_only_throw = [] def setattr(pbc, s_attr, s_value): getbookkeeper().warning("setattr not wanted on %r" % (pbc,)) Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jul 28 19:25:55 2005 @@ -459,9 +459,13 @@ if can_only_throw is not None: candidates = can_only_throw - exits = [block.exits[0]] - for link in block.exits[1:]: + candidate_exits = exits + exits = [] + for link in candidate_exits: case = link.exitcase + if case is None: + exits.append(link) + continue covered = [c for c in candidates if issubclass(c, case)] if covered: exits.append(link) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Thu Jul 28 19:25:55 2005 @@ -1481,6 +1481,24 @@ s = a.build_types(f, [bool]) assert s == annmodel.SomeString(can_be_None=True) + def test_dont_see_AttributeError_clause(self): + class Stuff: + def _freeze_(self): + return True + def createcompiler(self): + try: + return self.default_compiler + except AttributeError: + compiler = "yadda" + self.default_compiler = compiler + return compiler + stuff = Stuff() + stuff.default_compiler = 123 + def f(): + return stuff.createcompiler() + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s == a.bookkeeper.immutablevalue(123) def g(n): return [0,1,2,n] From cfbolz at codespeak.net Thu Jul 28 19:26:57 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 19:26:57 +0200 (CEST) Subject: [pypy-svn] r15279 - in pypy/dist/pypy/rpython: . module Message-ID: <20050728172657.5ACB227B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 19:26:55 2005 New Revision: 15279 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_math.py Log: added missing math functions to external function table Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Thu Jul 28 19:26:55 2005 @@ -83,21 +83,24 @@ declare(time.time , float , 'll_time/time') declare(time.clock , float , 'll_time/clock') declare(time.sleep , noneannotation, 'll_time/sleep') -declare(math.log10 , float , 'll_math/log10') -declare(math.log , float , 'll_math/log') -declare(math.cos , float , 'll_math/cos') -declare(math.sin , float , 'll_math/sin') -declare(math.sinh , float , 'll_math/sinh') -declare(math.cosh , float , 'll_math/cosh') -declare(math.acos , float , 'll_math/acos') -declare(math.sqrt , float , 'll_math/sqrt') -declare(math.hypot , float , 'll_math/hypot') -declare(math.ceil , float , 'll_math/ceil') + +# ___________________________ +# math functions + declare(math.frexp , frexpannotation, 'll_math/frexp') declare(math.atan2 , float , 'll_math/atan2') declare(math.fmod , float , 'll_math/fmod') declare(math.floor , float , 'll_math/floor') -declare(math.exp , float , 'll_math/exp') declare(math.ldexp , float , 'll_math/ldexp') declare(math.modf , modfannotation, 'll_math/modf') -declare(math.fabs , float , 'll_math/fabs') +declare(math.hypot , float , 'll_math/hypot') + +# the following functions all take one float, return one float +# and are part of math.h +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +for name in simple_math_functions: + declare(getattr(math, name), float, 'll_math/%s' % name) Modified: pypy/dist/pypy/rpython/module/ll_math.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_math.py (original) +++ pypy/dist/pypy/rpython/module/ll_math.py Thu Jul 28 19:26:55 2005 @@ -1,46 +1,19 @@ from pypy.rpython import lltype import math +import py -def ll_math_cos(x): - return math.cos(x) -ll_math_cos.suggested_primitive = True - -def ll_math_sin(x): - return math.sin(x) -ll_math_sin.suggested_primitive = True - -def ll_math_acos(x): - return math.acos(x) -ll_math_acos.suggested_primitive = True - -def ll_math_sinh(x): - return math.sinh(x) -ll_math_sinh.suggested_primitive = True - -def ll_math_cosh(x): - return math.cosh(x) -ll_math_cosh.suggested_primitive = True - -def ll_math_hypot(x, y): - return math.hypot(x, y) -ll_math_hypot.suggested_primitive = True - -def ll_math_sqrt(x): - return math.sqrt(x) -ll_math_sqrt.suggested_primitive = True - -def ll_math_log(x): - return math.log(x) -ll_math_log.suggested_primitive = True - -def ll_math_log10(x): - return math.log10(x) -ll_math_log10.suggested_primitive = True - -def ll_math_ceil(x): - return math.ceil(x) -ll_math_ceil.suggested_primitive = True +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +for name in simple_math_functions: + exec py.code.Source(""" + def ll_math_%(name)s(x): + return math.%(name)s(x) + ll_math_%(name)s.suggested_primitive = True + """ % {"name": name}).compile() FREXP_RESULT = lltype.GcStruct('tuple2', ('item0', lltype.Float), @@ -65,15 +38,9 @@ return math.fmod(x, y) ll_math_fmod.suggested_primitive = True -def ll_math_floor(x): - return math.floor(x) -ll_math_floor.suggested_primitive = True - -def ll_math_exp(x): - return math.exp(x) - def ll_math_ldexp(x, y): return math.ldexp(x, y) +ll_math_ldexp.suggested_primitive = True MODF_RESULT = lltype.GcStruct('tuple2', ('item0', lltype.Float), ('item1', lltype.Float)) @@ -89,6 +56,6 @@ return ll_modf_result(fracpart, intpart) ll_math_modf.suggested_primitive = True -def ll_math_fabs(x): - return math.fabs(x) -ll_math_fabs.suggested_primitive = True +def ll_math_hypot(x, y): + return math.hypot(x, y) +ll_math_hypot.suggested_primitive = True From cfbolz at codespeak.net Thu Jul 28 19:31:41 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 19:31:41 +0200 (CEST) Subject: [pypy-svn] r15280 - pypy/dist/pypy/module/math Message-ID: <20050728173141.1F6B827B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 19:31:38 2005 New Revision: 15280 Modified: pypy/dist/pypy/module/math/__init__.py pypy/dist/pypy/module/math/interp_math.py Log: enabled all math functions since there are now external function definitions for everything. Modified: pypy/dist/pypy/module/math/__init__.py ============================================================================== --- pypy/dist/pypy/module/math/__init__.py (original) +++ pypy/dist/pypy/module/math/__init__.py Thu Jul 28 19:31:38 2005 @@ -10,35 +10,33 @@ # is that we need to add support to # extfunctable/translation interpleveldefs = { - 'e' : 'interp_math.get(space).w_e', - 'pi' : 'interp_math.get(space).w_pi', - #'pow' : 'interp_math.pow', - 'cosh' : 'interp_math.cosh', - 'ldexp' : 'interp_math.ldexp', - 'hypot' : 'interp_math.hypot', - #'tan' : 'interp_math.tan', - #'asin' : 'interp_math.asin', - 'fabs' : 'interp_math.fabs', - 'floor' : 'interp_math.floor', - #'sqrt' : 'interp_math.sqrt', - 'frexp' : 'interp_math.frexp', - #'degrees' : 'interp_math.degrees', - 'log' : 'interp_math.log', - 'log10' : 'interp_math.log10', - 'fmod' : 'interp_math.fmod', - #'atan' : 'interp_math.atan', - 'ceil' : 'interp_math.ceil', - 'sinh' : 'interp_math.sinh', - 'acos' : 'interp_math.acos', - 'sin' : 'interp_math.sin', - 'sqrt' : 'interp_math.sqrt', - 'cos' : 'interp_math.cos', - #'tanh' : 'interp_math.tanh', - #'radians' : 'interp_math.radians', - #'sin' : 'interp_math.sin', - 'atan2' : 'interp_math.atan2', - 'modf' : 'interp_math.modf', - 'exp' : 'interp_math.exp', - 'acos' : 'interp_math.acos', - + 'e' : 'interp_math.get(space).w_e', + 'pi' : 'interp_math.get(space).w_pi', + 'pow' : 'interp_math.pow', + 'cosh' : 'interp_math.cosh', + 'ldexp' : 'interp_math.ldexp', + 'hypot' : 'interp_math.hypot', + 'tan' : 'interp_math.tan', + 'asin' : 'interp_math.asin', + 'log' : 'interp_math.log', + 'fabs' : 'interp_math.fabs', + 'floor' : 'interp_math.floor', + 'sqrt' : 'interp_math.sqrt', + 'frexp' : 'interp_math.frexp', + 'degrees' : 'interp_math.degrees', + 'log' : 'interp_math.log', + 'log10' : 'interp_math.log10', + 'fmod' : 'interp_math.fmod', + 'atan' : 'interp_math.atan', + 'ceil' : 'interp_math.ceil', + 'sinh' : 'interp_math.sinh', + 'cos' : 'interp_math.cos', + 'tanh' : 'interp_math.tanh', + 'radians' : 'interp_math.radians', + 'sin' : 'interp_math.sin', + 'atan2' : 'interp_math.atan2', + 'modf' : 'interp_math.modf', + 'exp' : 'interp_math.exp', + 'acos' : 'interp_math.acos', } + Modified: pypy/dist/pypy/module/math/interp_math.py ============================================================================== --- pypy/dist/pypy/module/math/interp_math.py (original) +++ pypy/dist/pypy/module/math/interp_math.py Thu Jul 28 19:31:38 2005 @@ -14,7 +14,7 @@ Return x**y (x to the power of y). """ - return space.wrap(math.pow(x, y)) + return space.wrap(x ** y) pow.unwrap_spec = [ObjSpace, float, float] def cosh(space, x): @@ -101,10 +101,12 @@ return space.newtuple([space.wrap(mant), space.wrap(expo)]) frexp.unwrap_spec = [ObjSpace, float] +degToRad = math.pi / 180.0 + def degrees(space, x): """degrees(x) -> converts angle x from radians to degrees """ - return space.wrap(math.degrees(x)) + return space.wrap(x * degToRad) degrees.unwrap_spec = [ObjSpace, float] def log10(space, x): @@ -165,7 +167,7 @@ def radians(space, x): """radians(x) -> converts angle x from degrees to radians """ - return space.wrap(math.radians(x)) + return space.wrap(x / degToRad) radians.unwrap_spec = [ObjSpace, float] def sin(space, x): From cfbolz at codespeak.net Thu Jul 28 19:33:16 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 19:33:16 +0200 (CEST) Subject: [pypy-svn] r15281 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050728173316.749D227B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 19:33:14 2005 New Revision: 15281 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added C implementations for all neccessary math functions plus a test Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Jul 28 19:33:14 2005 @@ -17,18 +17,26 @@ ll_os .ll_os_stat: 'LL_os_stat', ll_os .ll_os_fstat: 'LL_os_fstat', ll_time.ll_time_clock: 'LL_time_clock', - ll_math.ll_math_ceil: 'LL_math_ceil', ll_math.ll_math_frexp: 'LL_math_frexp', ll_math.ll_math_atan2: 'LL_math_atan2', ll_math.ll_math_fmod : 'LL_math_fmod', - ll_math.ll_math_floor: 'LL_math_floor', - ll_math.ll_math_exp: 'LL_math_exp', ll_math.ll_math_ldexp: 'LL_math_ldexp', - ll_math.ll_math_log10: 'LL_math_log10', - ll_math.ll_math_log: 'LL_math_log', ll_math.ll_math_modf: 'LL_math_modf', } +#______________________________________________________ +# insert 'simple' math functions into EXTERNALs table: + +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +for name in simple_math_functions: + EXTERNALS[getattr(ll_math, 'll_math_%s' % name)] = 'LL_math_%s' % name + +#______________________________________________________ + def predeclare_common_types(db, rtyper): # Common types Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Thu Jul 28 19:33:14 2005 @@ -12,9 +12,6 @@ /* XXX completely ignoring exceptions/error checking for now */ -double LL_math_ceil(double x) { - return ceil(x); -} RPyFREXP_RESULT* LL_math_frexp(double x) { int expo; @@ -29,28 +26,80 @@ double LL_math_fmod(double x, double y) { return fmod(x, y); } -double LL_math_floor(double x) { - return floor(x); + +double LL_math_ldexp(double x, long y) { + return ldexp(x, (int) y); +} + + +RPyMODF_RESULT* LL_math_modf(double x) { + double intpart; + double fracpart = modf(x, &intpart); + return ll_modf_result(fracpart, intpart); +} + +/* simple math function */ + +double LL_math_acos(double x) { + return acos(x); +} + +double LL_math_asin(double x) { + return asin(x); +} + +double LL_math_atan(double x) { + return atan(x); +} + +double LL_math_ceil(double x) { + return ceil(x); +} + +double LL_math_cos(double x) { + return cos(x); } + +double LL_math_cosh(double x) { + return cosh(x); +} + double LL_math_exp(double x) { - return exp(x); + return exp(x); } -double LL_math_ldexp(double x, long y) { - return ldexp(x, (int) y); + +double LL_math_fabs(double x) { + return fabs(x); +} + +double LL_math_floor(double x) { + return floor(x); } double LL_math_log(double x) { - return log(x); + return log(x); } double LL_math_log10(double x) { - return log10(x); + return log10(x); } +double LL_math_sin(double x) { + return sin(x); +} -RPyMODF_RESULT* LL_math_modf(double x) { - double intpart; - double fracpart = modf(x, &intpart); - return ll_modf_result(fracpart, intpart); +double LL_math_sinh(double x) { + return sinh(x); } +double LL_math_sqrt(double x) { + return sqrt(x); +} + +double LL_math_tan(double x) { + return tan(x); +} + +double LL_math_tanh(double x) { + return tanh(x); +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Thu Jul 28 19:33:14 2005 @@ -87,13 +87,6 @@ res = f1() assert res == os.getcwd() -def test_math_exp(): - from math import exp - def fn(f): - return exp(f) - f = compile(fn, [float]) - assert f(1.0) == exp(1.0) - def test_math_frexp(): from math import frexp def fn(x): @@ -108,12 +101,26 @@ f = compile(fn, [float]) assert f(10.123) == modf(10.123) -def test_math_log(): - from math import log10, log +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +def math_function_test(funcname): + import random + import math + mathfn = getattr(math, funcname) + print funcname, def fn(x): - return log10(x) + log(x) + return mathfn(x) f = compile(fn, [float]) - assert f(32675312.32123) == fn(32675312.32123) + for x in [0.12334, 0.3, 0.5, 0.9883]: + print x + assert f(x) == mathfn(x) + +def test_simple_math_functions(): + for funcname in simple_math_functions: + yield math_function_test, funcname def test_os_path_exists(): tmpfile = str(udir.join('test_os_path_exists.TMP')) @@ -136,3 +143,4 @@ return os.path.isdir(directory) f = compile(fn, []) assert f() == False + From arigo at codespeak.net Thu Jul 28 19:34:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 19:34:42 +0200 (CEST) Subject: [pypy-svn] r15282 - in pypy/dist/pypy: module/posix/test rpython/module/test Message-ID: <20050728173442.7114927B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 19:34:37 2005 New Revision: 15282 Added: pypy/dist/pypy/rpython/module/test/test_posix.py - copied unchanged from r15271, pypy/dist/pypy/module/posix/test/test_posix.py Removed: pypy/dist/pypy/module/posix/test/test_posix.py Log: Moved test_posix to the directory that contains what it tests, i.e. rpython/module/test/. Deleted: /pypy/dist/pypy/module/posix/test/test_posix.py ============================================================================== --- /pypy/dist/pypy/module/posix/test/test_posix.py Thu Jul 28 19:34:37 2005 +++ (empty file) @@ -1,102 +0,0 @@ -from pypy.rpython.test.test_llinterp import interpret -from pypy.tool.udir import udir -import os, posix - -def setup_module(module): - testf = udir.join('test.txt') - testfile = testf.open('w') - testfile.write('This is a test') - testfile.close() - module.path = testf.strpath - -def test_open(): - def f(): - ff = posix.open(path,posix.O_RDONLY,0777) - return ff - func = interpret(f,[]) - assert type(func) == int - -def test_dup(): - def ff(fi): - g = posix.dup(fi) - return g - fi = os.open(path,os.O_RDONLY,0755) - g = interpret(ff,[fi]) - assert os.fstat(g) == os.fstat(fi) - -def test_fstat(): - def fo(fi): - g = posix.fstat(fi) - return g - fi = os.open(path,os.O_RDONLY,0777) - func = interpret(fo,[fi]) - stat = os.fstat(fi) - for i in range(len(stat)): - stat0 = getattr(func, 'item%d' % i) - assert stat0 == stat[i] - -def test_lseek(): - def f(fi,pos): - posix.lseek(fi,pos,0) - fi = os.open(path,os.O_RDONLY,0777) - func = interpret(f,[fi,5]) - res = os.read(fi,2) - assert res =='is' - -def test_isatty(): - def f(fi): - posix.isatty(fi) - fi = os.open(path,os.O_RDONLY,0777) - func = interpret(f,[fi]) - assert not func - os.close(fi) - func = interpret(f,[fi]) - assert not func - -def test_getcwd(): - def f(): - return posix.getcwd() - res = interpret(f,[]) - cwd = os.getcwd() - print res.chars,cwd - assert ''.join([x for x in res.chars]) == cwd - -def test_write(): - def f(fi): - text = 'This is a test' - return posix.write(fi,text) - fi = os.open(path,os.O_WRONLY,0777) - text = 'This is a test' - func = interpret(f,[fi]) - os.close(fi) - fi = os.open(path,os.O_RDONLY,0777) - res = os.read(fi,20) - assert res == text - -def test_read(): - def f(fi,len): - return posix.read(fi,len) - fi = os.open(path,os.O_WRONLY,0777) - text = 'This is a test' - os.write(fi,text) - os.close(fi) - fi = os.open(path,os.O_RDONLY,0777) - res = interpret(f,[fi,20]) - assert ''.join([x for x in res.chars]) == text - -def test_close(): - def f(fi): - return posix.close(fi) - fi = os.open(path,os.O_WRONLY,0777) - text = 'This is a test' - os.write(fi,text) - res = interpret(f,[fi]) - raises( OSError, os.fstat, fi) - -def test_ftruncate(): - def f(fi,len): - posix.ftruncate(fi,len) - fi = os.open(path,os.O_RDWR,0777) - func = interpret(f,[fi,6]) - assert os.fstat(fi).st_size == 6 - From hpk at codespeak.net Thu Jul 28 19:49:11 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 28 Jul 2005 19:49:11 +0200 (CEST) Subject: [pypy-svn] r15283 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050728174911.4CA4C27B85@code1.codespeak.net> Author: hpk Date: Thu Jul 28 19:49:10 2005 New Revision: 15283 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/std/objspace.py Log: untangle initialization regarding options for object spaces a bit. however, since some time '--oldstyle' does not seem to work correctly (with or without this change) Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 19:49:10 2005 @@ -107,7 +107,9 @@ nofaking=False, uselibfile=False, parser="recparser", - compiler="pyparse"): + compiler="pyparse", + **kw + ): "NOT_RPYTHON: Basic initialization of objects." self.fromcache = InternalSpaceCache(self).getorbuild self.threadlocals = ThreadLocals() @@ -119,8 +121,14 @@ self.options.uselibfile = uselibfile or nofaking self.options.compiler = compiler self.options.usemodules = usemodules + if kw: + self.setoptions(kw) self.initialize() + def setoptions(self, kw): + # override this in subclasses for extra-options + raise TypeError("got unknown keyword arguments: %r" %(kw,)) + def __repr__(self): return self.__class__.__name__ Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 19:49:10 2005 @@ -29,11 +29,12 @@ PACKAGE_PATH = 'objspace.std' - def __init__(self, oldstyle=False, **kw): - super(StdObjSpace, self).__init__(**kw) - self.options.oldstyle = oldstyle - if oldstyle: - self.enable_old_style_classes_as_default_metaclass() + def setoptions(self, kw): + optionlist = 'oldstyle'.split() + for name in kw: + if name not in optionlist: + raise TypeError("don't know about option %r" % (name,)) + setattr(self.options, name, kw[name]) def initialize(self): "NOT_RPYTHON: only for initializing the space." @@ -111,6 +112,9 @@ self.default_compiler = PythonCompilerApp(self) self.getexecutioncontext().compiler = self.default_compiler + if self.options.oldstyle: + self.enable_old_style_classes_as_default_metaclass() + def enable_old_style_classes_as_default_metaclass(self): self.setitem(self.builtin.w_dict, self.wrap('__metaclass__'), self.w_classobj) From cfbolz at codespeak.net Thu Jul 28 20:22:43 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 20:22:43 +0200 (CEST) Subject: [pypy-svn] r15284 - in pypy/dist/pypy: interpreter lib/_stablecompiler Message-ID: <20050728182243.CF9C627B85@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 20:22:40 2005 New Revision: 15284 Added: pypy/dist/pypy/lib/_stablecompiler/ - copied from r15281, pypy/dist/pypy/interpreter/stablecompiler/ Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/lib/_stablecompiler/future.py pypy/dist/pypy/lib/_stablecompiler/pyassem.py pypy/dist/pypy/lib/_stablecompiler/pycodegen.py pypy/dist/pypy/lib/_stablecompiler/symbols.py pypy/dist/pypy/lib/_stablecompiler/syntax.py pypy/dist/pypy/lib/_stablecompiler/transformer.py pypy/dist/pypy/lib/_stablecompiler/visitor.py Log: (cfbolz, arigo) Copied the stablecompiler to lib/ and made it purely app-level. Started to remove calls to eval(). Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Thu Jul 28 20:22:40 2005 @@ -242,11 +242,11 @@ debug_print("importing the 'compiler' package at app-level...", newline=False) self.w_applevelcompile = space.appexec([], r'''(): - from compiler.misc import set_filename - from compiler.pycodegen import ModuleCodeGenerator - from compiler.pycodegen import InteractiveCodeGenerator - from compiler.pycodegen import ExpressionCodeGenerator - from compiler.transformer import Transformer + from _stablecompiler.misc import set_filename + from _stablecompiler.pycodegen import ModuleCodeGenerator + from _stablecompiler.pycodegen import InteractiveCodeGenerator + from _stablecompiler.pycodegen import ExpressionCodeGenerator + from _stablecompiler.transformer import Transformer def applevelcompile(tuples, filename, mode): transformer = Transformer() Modified: pypy/dist/pypy/lib/_stablecompiler/future.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/future.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/future.py Thu Jul 28 20:22:40 2005 @@ -2,7 +2,8 @@ """ -from pypy.interpreter.stablecompiler import ast, walk +import ast +from visitor import walk def is_future(stmt): """Return true if statement is a well-formed future statement""" @@ -61,7 +62,7 @@ if __name__ == "__main__": import sys - from pypy.interpreter.stablecompiler import parseFile, walk + import parseFile, walk for file in sys.argv[1:]: print file Modified: pypy/dist/pypy/lib/_stablecompiler/pyassem.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/pyassem.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/pyassem.py Thu Jul 28 20:22:40 2005 @@ -5,9 +5,8 @@ import sys import types -from pypy.interpreter.stablecompiler import misc -from pypy.interpreter.stablecompiler.consts \ - import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS +import misc +from consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS class FlowGraph: def __init__(self): Modified: pypy/dist/pypy/lib/_stablecompiler/pycodegen.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/pycodegen.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/pycodegen.py Thu Jul 28 20:22:40 2005 @@ -6,13 +6,14 @@ import types from cStringIO import StringIO -from pypy.interpreter.stablecompiler import ast, parse, walk, syntax -from pypy.interpreter.stablecompiler import pyassem, misc, future, symbols -from pypy.interpreter.stablecompiler.consts import SC_LOCAL, SC_GLOBAL, \ - SC_FREE, SC_CELL -from pypy.interpreter.stablecompiler.consts import CO_VARARGS, CO_VARKEYWORDS, \ +import ast, syntax +from transformer import parse +from visitor import walk +import pyassem, misc, future, symbols +from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL +from consts import CO_VARARGS, CO_VARKEYWORDS, \ CO_NEWLOCALS, CO_NESTED, CO_GENERATOR, CO_GENERATOR_ALLOWED, CO_FUTURE_DIVISION -from pypy.interpreter.stablecompiler.pyassem import TupleArg +from pyassem import TupleArg # XXX The version-specific code can go, since this code only works with 2.x. # Do we have Python 1.x or Python 2.x? Modified: pypy/dist/pypy/lib/_stablecompiler/symbols.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/symbols.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/symbols.py Thu Jul 28 20:22:40 2005 @@ -1,9 +1,8 @@ """Module symbol-table generator""" -from pypy.interpreter.stablecompiler import ast -from pypy.interpreter.stablecompiler.consts import SC_LOCAL, SC_GLOBAL, \ - SC_FREE, SC_CELL, SC_UNKNOWN -from pypy.interpreter.stablecompiler.misc import mangle +import ast +from consts import SC_LOCAL, SC_GLOBAL, SC_FREE, SC_CELL, SC_UNKNOWN +from misc import mangle import types @@ -420,7 +419,7 @@ if __name__ == "__main__": import sys - from pypy.interpreter.stablecompiler import parseFile, walk + import parseFile, walk import symtable def get_names(syms): Modified: pypy/dist/pypy/lib/_stablecompiler/syntax.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/syntax.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/syntax.py Thu Jul 28 20:22:40 2005 @@ -9,7 +9,8 @@ errors. """ -from pypy.interpreter.stablecompiler import ast, walk +import ast +from visitor import walk def check(tree, multi=None): v = SyntaxErrorChecker(multi) Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/transformer.py Thu Jul 28 20:22:40 2005 @@ -25,12 +25,10 @@ # http://www.opensource.org/licenses/bsd-license.html # and replace OWNER, ORGANIZATION, and YEAR as appropriate. -# make sure we import the parser with the correct grammar -import pypy.interpreter.pyparser.pythonparse -from pypy.interpreter.stablecompiler.ast import * +from ast import * import parser -import pypy.interpreter.pyparser.pysymbol as symbol -import pypy.interpreter.pyparser.pytoken as token +import symbol +import token import sys class WalkerError(StandardError): @@ -715,7 +713,15 @@ def atom_number(self, nodelist): ### need to verify this matches compile.c - k = eval(nodelist[0][1]) + s = nodelist[0][1] + if 'j' in s or 'J' in s: + k = complex(s) + elif '.' in s or 'e' in s or 'E' in s: + k = float(s) + elif 'l' in s or 'L' in s: + k = long(s) + else: + k = int(s) return Const(k, lineno=nodelist[0][2]) def decode_literal(self, lit): @@ -725,9 +731,10 @@ # tokenizer.c must be reflected here. if self.encoding not in ['utf-8', 'iso-8859-1']: lit = unicode(lit, 'utf-8').encode(self.encoding) + #XXX no clue what the following line does return eval("# coding: %s\n%s" % (self.encoding, lit)) else: - return eval(lit) + return parser.decode_string_literal(lit) def atom_string(self, nodelist): k = '' Modified: pypy/dist/pypy/lib/_stablecompiler/visitor.py ============================================================================== --- pypy/dist/pypy/interpreter/stablecompiler/visitor.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/visitor.py Thu Jul 28 20:22:40 2005 @@ -1,4 +1,4 @@ -from pypy.interpreter.stablecompiler import ast +import ast # XXX should probably rename ASTVisitor to ASTWalker # XXX can it be made even more generic? From arigo at codespeak.net Thu Jul 28 20:46:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 20:46:01 +0200 (CEST) Subject: [pypy-svn] r15285 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050728184601.6D3AE27B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 20:45:57 2005 New Revision: 15285 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/objspace/std/objspace.py Log: Changed the space.setoptions() interface to pass options by keyword again. This avoids a problem where the attribute 'space.options.oldstyle' is not set at all (instead of getting a default of False) if the space is built without specifying an 'oldstyle' keyword. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Thu Jul 28 20:45:57 2005 @@ -121,13 +121,12 @@ self.options.uselibfile = uselibfile or nofaking self.options.compiler = compiler self.options.usemodules = usemodules - if kw: - self.setoptions(kw) + self.setoptions(**kw) self.initialize() - def setoptions(self, kw): + def setoptions(self): # override this in subclasses for extra-options - raise TypeError("got unknown keyword arguments: %r" %(kw,)) + pass def __repr__(self): return self.__class__.__name__ Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 20:45:57 2005 @@ -29,12 +29,8 @@ PACKAGE_PATH = 'objspace.std' - def setoptions(self, kw): - optionlist = 'oldstyle'.split() - for name in kw: - if name not in optionlist: - raise TypeError("don't know about option %r" % (name,)) - setattr(self.options, name, kw[name]) + def setoptions(self, oldstyle=False): + self.options.oldstyle = oldstyle def initialize(self): "NOT_RPYTHON: only for initializing the space." From arigo at codespeak.net Thu Jul 28 20:58:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 20:58:22 +0200 (CEST) Subject: [pypy-svn] r15286 - pypy/dist/pypy/interpreter Message-ID: <20050728185822.003A027B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 20:58:20 2005 New Revision: 15286 Modified: pypy/dist/pypy/interpreter/error.py pypy/dist/pypy/interpreter/interactive.py Log: Restored the broken old hack that allows the interactive command-line to print tracebacks showing lines from the interactively entered source code. Modified: pypy/dist/pypy/interpreter/error.py ============================================================================== --- pypy/dist/pypy/interpreter/error.py (original) +++ pypy/dist/pypy/interpreter/error.py Thu Jul 28 20:58:20 2005 @@ -96,7 +96,7 @@ lines = fname.split('\n') fname = lines[0].strip() try: - l = lines[lineno] + l = lines[lineno+1] except IndexError: l = '' else: Modified: pypy/dist/pypy/interpreter/interactive.py ============================================================================== --- pypy/dist/pypy/interpreter/interactive.py (original) +++ pypy/dist/pypy/interpreter/interactive.py Thu Jul 28 20:58:20 2005 @@ -159,7 +159,8 @@ raise NotImplementedError def runsource(self, source, ignored_filename="", symbol="single"): - hacked_filename = '' + source + # the following hacked file name is recognized specially by error.py + hacked_filename = '\n' + source compiler = self.space.getexecutioncontext().compiler def doit(): From arigo at codespeak.net Thu Jul 28 21:05:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 21:05:31 +0200 (CEST) Subject: [pypy-svn] r15287 - pypy/dist/pypy/interpreter Message-ID: <20050728190531.F3AAC27B85@code1.codespeak.net> Author: arigo Date: Thu Jul 28 21:05:31 2005 New Revision: 15287 Modified: pypy/dist/pypy/interpreter/error.py Log: Reverted this change. The previous version was right. The problem appears to be related to the line numbers produced by the parser or compiler: a simple expression line "1/0" produces an error that shows up with the number of the previous line. A statement like "a = 1/0" gets the correctt line number. Modified: pypy/dist/pypy/interpreter/error.py ============================================================================== --- pypy/dist/pypy/interpreter/error.py (original) +++ pypy/dist/pypy/interpreter/error.py Thu Jul 28 21:05:31 2005 @@ -96,7 +96,7 @@ lines = fname.split('\n') fname = lines[0].strip() try: - l = lines[lineno+1] + l = lines[lineno] except IndexError: l = '' else: From tismer at codespeak.net Thu Jul 28 21:09:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 21:09:39 +0200 (CEST) Subject: [pypy-svn] r15288 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050728190939.5B0AB27B85@code1.codespeak.net> Author: tismer Date: Thu Jul 28 21:09:36 2005 New Revision: 15288 Added: pypy/dist/pypy/interpreter/pyparser/parsestring.py (contents, props changed) pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py (contents, props changed) Log: Samuele & Chris: added parsestring.py, which parses a Python string literal. Seems to work basically. No intense testing of unicode cases, yet. please review the interface. Right now we accept native argument, but return and raise wrapped results. Added: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Thu Jul 28 21:09:36 2005 @@ -0,0 +1,216 @@ +from pypy.interpreter import gateway +from pypy.interpreter.error import OperationError + +def parsestr(space, encoding, s): + # compiler.transformer.Transformer.decode_literal depends on what + # might seem like minor details of this function -- changes here + # must be reflected there. + + # we use ps as "pointer to s" + # q is the virtual last char index of the string + ps = 0 + quote = s[ps] + rawmode = False + unicode = False + + # string decoration handling + if quote.isalpha() or quote == '_': + if quote == 'u' or quote == 'U': + ps += 1 + quote = s[ps] + unicode = True + if quote == 'r' or quote == 'R': + ps += 1 + quote = s[ps] + rawmode = True + if quote != "'" and quote != '"': + raise_app_valueerror('Internal error: parser passed unquoted literal') + ps += 1 + q = len(s) - 1 + if s[q] != quote: + raise_app_valueerror('Internal error: parser passed unmatched ' + 'quotes in literal') + if q-ps >= 4 and s[ps] == quote and s[ps+1] == quote: + # triple quotes + ps += 2 + if s[q-1] != quote or s[q-2] != quote: + raise_app_valueerror('Internal error: parser passed unmatched ' + 'triple quotes in literal') + q -= 2 + + if unicode: # XXX Py_UnicodeFlag is ignored for now + if encoding is None or encoding == "iso-8859-1": + buf = s + bufp = ps + bufq = q + u = None + else: + # "\XX" may become "\u005c\uHHLL" (12 bytes) + lis = [] # using a list to assemble the value + end = q + while ps < end: + if s[ps] == '\\': + lis.append(s[ps]) + ps += 1 + if ord(s[ps]) & 0x80: + lis.append("u005c") + if ord(s[ps]) & 0x80: # XXX inefficient + w, ps = decode_utf8(space, s, ps, end, "utf-16-be") + rn = len(w) + assert rn % 2 == 0 + for i in range(0, rn, 2): + lis.append('\\u') + lis.append(hexbyte(ord(w[i]))) + lis.append(hexbyte(ord(w[i+1]))) + else: + lis.append(s[ps]) + ps += 1 + buf = ''.join(lis) + bufp = 0 + bufq = len(buf) + if rawmode: + w_v = PyUnicode_DecodeRawUnicodeEscape(space, space.wrap(buf[bufp : bufq])) + else: + w_v = PyUnicode_DecodeUnicodeEscape(space, space.wrap(buf[bufp : bufq])) + return w_v + + need_encoding = (encoding is not None and + encoding != "utf-8" and encoding != "iso-8859-1") + # XXX add strchr like interface to rtyper + if rawmode or '\\' not in s[ps:]: + if need_encoding: + w_u = PyUnicode_DecodeUTF8(space, space.wrap(s[ps : q])) + w_v = PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) + return w_v + else: + return space.wrap(s[ps : q]) + + enc = None + if need_encoding: + enc = encoding + v = PyString_DecodeEscape(space, s[ps : q], unicode, enc) + return space.wrap(v) + + +def PyString_DecodeEscape(space, s, unicode, recode_encoding): + """ + Unescape a backslash-escaped string. If unicode is non-zero, + the string is a u-literal. If recode_encoding is non-zero, + the string is UTF-8 encoded and should be re-encoded in the + specified encoding. + """ + lis = [] + ps = 0 + end = len(s) + while ps < end: + if s[ps] != '\\': + # note that the C code has a label here. + # the logic is the same. + if recode_encoding and ord(s[ps]) & 0x80: + w, ps = decode_utf8(space, s, ps, q, recode_encoding) + # Append bytes to output buffer. + lis.append(w) + else: + lis.append(s[ps]) + ps += 1 + continue + ps += 1 + if ps == end: + raise_app_valueerror('Trailing \\ in string') + ch = s[ps] + ps += 1 + # XXX This assumes ASCII! + if ch == '\n': + pass + elif ch == '\\': + lis.append('\\') + elif ch == "'": + lis.append("'") + elif ch == '"': + lis.append("'") + elif ch == 'b': + lis.append("\'") + elif ch == 'f': + lis.append('\014') # FF + elif ch == 't': + lis.append('\t') + elif ch == 'n': + lis.append('\n') + elif ch == 'r': + lis.append('\r') + elif ch == 'v': + lis.append('\013') # VT + elif ch == 'a': + lis.append('\007') # BEL, not classic C + elif ch >= '0' and ch <= '7': + c = ord(s[ps - 1]) - ord('0') + if '0' <= s[ps] <= '7': + c = (c << 3) + ord(s[ps]) - ord('0') + ps += 1 + if '0' <= s[ps] <= '7': + c = (c << 3) + ord(s[ps]) - ord('0') + lis.append(chr(c)) + elif ch == 'x': + if isxdigit(s[ps]) and isxdigit(s[ps + 1]): + lis.append(chr(int(s[ps : ps + 2], 16))) + ps += 2 + else: + raise_app_valueerror('invalid \\x escape') + # ignored replace and ignore for now + + elif unicode and (ch == 'u' or ch == 'U' or ch == 'N'): + raise_app_valueerror('Unicode escapes not legal ' + 'when Unicode disabled') + else: + # this was not an escape, so the backslash + # has to be added, and we start over in + # non-escape mode. + lis.append('\\') + ps -= 1 + continue + # an arbitry number of unescaped UTF-8 bytes may follow. + + buf = ''.join(lis) + return buf + + +def isxdigit(ch): + return (ch >= '0' and ch <= '9' or + ch >= 'a' and ch <= 'f' or + ch >= 'A' and ch <= 'F') + +app = gateway.applevel(r''' + def PyUnicode_DecodeUnicodeEscape(data): + import _codecs + return _codecs.unicode_escape_decode(data)[0] + + def PyUnicode_DecodeRawUnicodeEscape(data): + import _codecs + return _codecs.raw_unicode_escape_decode(data)[0] + + def PyUnicode_DecodeUTF8(data): + import _codecs + return _codecs.utf_8_decode(data)[0] + + def PyUnicode_AsEncodedString(data, encoding): + import _codecs + return _codecs.encode(data, encoding) +''') + +PyUnicode_DecodeUnicodeEscape = app.interphook('PyUnicode_DecodeUnicodeEscape') +PyUnicode_DecodeRawUnicodeEscape = app.interphook('PyUnicode_DecodeRawUnicodeEscape') +PyUnicode_DecodeUTF8 = app.interphook('PyUnicode_DecodeUTF8') +PyUnicode_AsEncodedString = app.interphook('PyUnicode_DecodeUTF8') + +def decode_utf8(space, s, ps, end, encoding): + pt = ps + # while (s < end && *s != '\\') s++; */ /* inefficient for u".." + while ps < end and ord(s[ps]) & 0x80: + ps += 1 + w_u = PyUnicode_DecodeUTF8(space, space.wrap(s[pt : ps])) + w_v = PyUnicode_AsEncodedString(space, w_u, space.unwrap(encoding)) + v = space.str_w(w_v) + return v, ps + +def raise_app_valueerror(space, msg): + raise OperationError(space.w_ValueError, space.wrap(msg)) Added: pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Thu Jul 28 21:09:36 2005 @@ -0,0 +1,37 @@ +from pypy.interpreter.pyparser import parsestring + +class TestParsetring: + def test_simple(self): + space = self.space + s = 'hello world' + w_ret = parsestring.parsestr(space, None, repr(s)) + assert space.str_w(w_ret) == s + s = 'hello\n world' + w_ret = parsestring.parsestr(space, None, repr(s)) + assert space.str_w(w_ret) == s + s = "'''hello\\x42 world'''" + w_ret = parsestring.parsestr(space, None, s) + assert space.str_w(w_ret) == 'hello\x42 world' + + def test_unicode(self): + space = self.space + s = u'hello world' + w_ret = parsestring.parsestr(space, None, repr(s)) + ret = space.unwrap(w_ret) + assert isinstance(ret, unicode) + assert ret == s + s = u'hello\n world' + w_ret = parsestring.parsestr(self.space, None, repr(s)) + ret = space.unwrap(w_ret) + assert isinstance(ret, unicode) + assert ret == s + s = "u'''hello\\x42 world'''" + w_ret = parsestring.parsestr(self.space, None, s) + ret = space.unwrap(w_ret) + assert isinstance(ret, unicode) + assert ret == u'hello\x42 world' + s = "u'''hello\\u0842 world'''" + w_ret = parsestring.parsestr(self.space, None, s) + ret = space.unwrap(w_ret) + assert isinstance(ret, unicode) + assert ret == u'hello\u0842 world' From tismer at codespeak.net Thu Jul 28 21:25:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 28 Jul 2005 21:25:11 +0200 (CEST) Subject: [pypy-svn] r15291 - pypy/dist/pypy/module/_codecs Message-ID: <20050728192511.D4E1E27B8C@code1.codespeak.net> Author: tismer Date: Thu Jul 28 21:25:10 2005 New Revision: 15291 Modified: pypy/dist/pypy/module/_codecs/app_codecs.py Log: added a note about app_codecs, which is now and should stay RPythonic (geninterp-able). Modified: pypy/dist/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/app_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Thu Jul 28 21:25:10 2005 @@ -1,3 +1,7 @@ +# Note: +# This *is* now explicitly RPython. +# Please make sure not to break this. + """ _codecs -- Provides access to the codec registry and the builtin @@ -198,7 +202,7 @@ """None """ res = PyUnicode_DecodeUnicodeEscape(data,len(data),errors) - res = ''.join(res) + res = u''.join(res) return res, len(res) From cfbolz at codespeak.net Thu Jul 28 21:26:18 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 21:26:18 +0200 (CEST) Subject: [pypy-svn] r15292 - in pypy/dist/pypy: interpreter/pyparser lib/_stablecompiler module/recparser Message-ID: <20050728192618.D7B1427B8C@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 21:26:15 2005 New Revision: 15292 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py pypy/dist/pypy/lib/_stablecompiler/transformer.py pypy/dist/pypy/module/recparser/__init__.py pypy/dist/pypy/module/recparser/pyparser.py Log: (arigo) * Intergrated parsestr() with the app-level _stablecompiler. * Fix in parsestr(). Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Thu Jul 28 21:26:15 2005 @@ -24,18 +24,19 @@ quote = s[ps] rawmode = True if quote != "'" and quote != '"': - raise_app_valueerror('Internal error: parser passed unquoted literal') + raise_app_valueerror(space, + 'Internal error: parser passed unquoted literal') ps += 1 q = len(s) - 1 if s[q] != quote: - raise_app_valueerror('Internal error: parser passed unmatched ' - 'quotes in literal') + raise_app_valueerror(space, 'Internal error: parser passed unmatched ' + 'quotes in literal') if q-ps >= 4 and s[ps] == quote and s[ps+1] == quote: # triple quotes ps += 2 if s[q-1] != quote or s[q-2] != quote: - raise_app_valueerror('Internal error: parser passed unmatched ' - 'triple quotes in literal') + raise_app_valueerror(space, 'Internal error: parser passed ' + 'unmatched triple quotes in literal') q -= 2 if unicode: # XXX Py_UnicodeFlag is ignored for now @@ -116,7 +117,7 @@ continue ps += 1 if ps == end: - raise_app_valueerror('Trailing \\ in string') + raise_app_valueerror(space, 'Trailing \\ in string') ch = s[ps] ps += 1 # XXX This assumes ASCII! @@ -155,12 +156,12 @@ lis.append(chr(int(s[ps : ps + 2], 16))) ps += 2 else: - raise_app_valueerror('invalid \\x escape') + raise_app_valueerror(space, 'invalid \\x escape') # ignored replace and ignore for now elif unicode and (ch == 'u' or ch == 'U' or ch == 'N'): - raise_app_valueerror('Unicode escapes not legal ' - 'when Unicode disabled') + raise_app_valueerror(space, 'Unicode escapes not legal ' + 'when Unicode disabled') else: # this was not an escape, so the backslash # has to be added, and we start over in Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/lib/_stablecompiler/transformer.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/transformer.py Thu Jul 28 21:26:15 2005 @@ -731,10 +731,7 @@ # tokenizer.c must be reflected here. if self.encoding not in ['utf-8', 'iso-8859-1']: lit = unicode(lit, 'utf-8').encode(self.encoding) - #XXX no clue what the following line does - return eval("# coding: %s\n%s" % (self.encoding, lit)) - else: - return parser.decode_string_literal(lit) + return parser.decode_string_literal(lit, self.encoding) def atom_string(self, nodelist): k = '' Modified: pypy/dist/pypy/module/recparser/__init__.py ============================================================================== --- pypy/dist/pypy/module/recparser/__init__.py (original) +++ pypy/dist/pypy/module/recparser/__init__.py Thu Jul 28 21:26:15 2005 @@ -40,5 +40,8 @@ ## #'tuple2ast' : 'pyparser.tuple2ast', ## #'_pickler' : 'pyparser._pickler', ## #'compilest' : 'pyparser.compilest', + + # PyPy extension + 'decode_string_literal': 'pyparser.decode_string_literal', } Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Thu Jul 28 21:26:15 2005 @@ -193,3 +193,12 @@ syntaxtree = unwrap_syntax_tree( space, w_sequence ) return space.wrap( STType(space, syntaxtree) ) + +def decode_string_literal(space, s, w_encoding=None): + from pypy.interpreter.pyparser.parsestring import parsestr + if space.is_true(w_encoding): + encoding = space.str_w(w_encoding) + else: + encoding = None + return parsestr(space, encoding, s) +decode_string_literal.unwrap_spec = [ObjSpace, str, W_Root] From cfbolz at codespeak.net Thu Jul 28 21:39:42 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 21:39:42 +0200 (CEST) Subject: [pypy-svn] r15294 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050728193942.A8C5527B8C@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 21:39:41 2005 New Revision: 15294 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py Log: (samuele, cfbolz): added missing hexbyte Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Thu Jul 28 21:39:41 2005 @@ -92,6 +92,11 @@ v = PyString_DecodeEscape(space, s[ps : q], unicode, enc) return space.wrap(v) +def hexbyte(val): + result = "%x" % val + if len(result) == 1: + result = "0" + result + return result def PyString_DecodeEscape(space, s, unicode, recode_encoding): """ From cfbolz at codespeak.net Thu Jul 28 22:16:37 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Jul 2005 22:16:37 +0200 (CEST) Subject: [pypy-svn] r15297 - pypy/dist/pypy/lib/_stablecompiler Message-ID: <20050728201637.E53E627B8A@code1.codespeak.net> Author: cfbolz Date: Thu Jul 28 22:16:36 2005 New Revision: 15297 Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py Log: (arigo, cfbolz) removed another eval Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/lib/_stablecompiler/transformer.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/transformer.py Thu Jul 28 22:16:36 2005 @@ -1319,7 +1319,7 @@ if node[0][0] == token.STRING: s = '' for t in node: - s = s + eval(t[1]) + s = s + parser.decode_string_literal(t[1]) return s return None if n == symbol.stmt or n == symbol.simple_stmt \ From arigo at codespeak.net Thu Jul 28 22:30:29 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 22:30:29 +0200 (CEST) Subject: [pypy-svn] r15298 - pypy/dist/pypy/objspace/std Message-ID: <20050728203029.8A80F27B83@code1.codespeak.net> Author: arigo Date: Thu Jul 28 22:30:26 2005 New Revision: 15298 Modified: pypy/dist/pypy/objspace/std/floatobject.py Log: Do the correct thing in int__Float() with respect to longs. Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Thu Jul 28 22:30:26 2005 @@ -49,10 +49,12 @@ return W_FloatObject(space, a) def int__Float(space, w_value): - value = int(w_value.floatval) - if isinstance(value, long): # XXX cheating + try: + value = ovfcheck_float_to_int(w_value.floatval) + except OverflowError: return space.long(w_value) - return space.newint(value) + else: + return space.newint(value) def float_w__Float(space, w_float): return w_float.floatval From arigo at codespeak.net Thu Jul 28 23:19:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 23:19:33 +0200 (CEST) Subject: [pypy-svn] r15301 - pypy/dist/pypy/objspace/std Message-ID: <20050728211933.6C2CF27B7B@code1.codespeak.net> Author: arigo Date: Thu Jul 28 23:19:29 2005 New Revision: 15301 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Bootstrapping (and, side-effectedly, performance) hack. Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Thu Jul 28 23:19:29 2005 @@ -77,6 +77,24 @@ unicode_from_object = app.interphook('unicode_from_object') unicode_from_encoded_object = app.interphook('unicode_from_encoded_object') +def unicode_from_string(space, w_str): + # this is a performance and bootstrapping hack + from pypy.objspace.std.unicodeobject import W_UnicodeObject + w_encoding = space.call_function(space.sys.get('getdefaultencoding')) + if not space.eq_w(w_encoding, space.wrap('ascii')): + return unicode_from_object(space, w_str) + s = space.str_w(w_str) + codelist = [] + for i in range(len(s)): + code = ord(s[i]) + if code >= 128: + raise OperationError(space.w_UnicodeDecodeError, + "'ascii' codec can't decode byte %s in " + "position %d: ordinal not in range(128)" % ( + hex(code), i)) + codelist.append(unichr(code)) + return W_UnicodeObject(space, codelist) + def descr__new__(space, w_unicodetype, w_obj=None, w_encoding=None, w_errors=None): from pypy.objspace.std.unicodeobject import W_UnicodeObject @@ -94,7 +112,9 @@ w_value = W_UnicodeObject(space, []) 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_unicode)): + if space.is_true(space.isinstance(w_obj, space.w_str)): + w_value = unicode_from_string(space, w_obj) + elif space.is_true(space.isinstance(w_obj, space.w_unicode)): w_value = w_obj else: w_value = unicode_from_object(space, w_obj) From rxe at codespeak.net Thu Jul 28 23:29:55 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 23:29:55 +0200 (CEST) Subject: [pypy-svn] r15302 - pypy/dist/pypy/tool Message-ID: <20050728212955.42E1A27B7B@code1.codespeak.net> Author: rxe Date: Thu Jul 28 23:29:53 2005 New Revision: 15302 Modified: pypy/dist/pypy/tool/traceconfig.py pypy/dist/pypy/tool/traceop.py Log: issue25 in-progress Added an option to use wrapped/unwrapped reprs & clean up the code mess. Modified: pypy/dist/pypy/tool/traceconfig.py ============================================================================== --- pypy/dist/pypy/tool/traceconfig.py (original) +++ pypy/dist/pypy/tool/traceconfig.py Thu Jul 28 23:29:53 2005 @@ -5,6 +5,9 @@ # An optional filename to use for trace output. None is stdout "output_filename" : None, + # Use a simple wrapped repr (fast) or try to do something more intelligent (slow) + "repr_type_simple" : True, + # Some internal interpreter code is written at applevel - by default # it is a good idea to hide this. "show_hidden_applevel" : False, Modified: pypy/dist/pypy/tool/traceop.py ============================================================================== --- pypy/dist/pypy/tool/traceop.py (original) +++ pypy/dist/pypy/tool/traceop.py Thu Jul 28 23:29:53 2005 @@ -1,8 +1,6 @@ # # support code for the trace object space # -from __future__ import generators - import autopath import sys @@ -27,12 +25,14 @@ class ResultPrinter: def __init__(self, + indentor = ' ', + repr_type_simple = True, + show_bytecode = True, output_filename = None, show_hidden_applevel = False, recursive_operations = False, - show_bytecode = True, - indentor = ' ', - show_wrapped_consts_bytecode = True): + show_wrapped_consts_bytecode = True, + ): if output_filename is None: self.out = sys.stdout @@ -45,7 +45,11 @@ self.show_hidden_applevel = show_hidden_applevel self.recursive_operations = recursive_operations self.show_wrapped_consts_bytecode = show_wrapped_consts_bytecode - + if repr_type_simple: + self.repr_value = simple_repr + else: + self.repr_value = repr_value + # Keeps a stack of current state to handle # showing of applevel and recursive operations self.indent_state = Stack() @@ -113,7 +117,7 @@ s = " " * 4 s += "%s" % name - s += "(" + ", ".join([repr_value(space, ii) for ii in args]) + ")" + s += "(" + ", ".join([self.repr_value(space, ii) for ii in args]) + ")" self.print_line(s, new_line=False) def print_op_leave(self, space, name, res): @@ -125,7 +129,7 @@ else: s = " " - s += "-> %s" % repr_value(space, res) + s += "-> %s" % self.repr_value(space, res) self.print_line(s) def print_op_exc(self, name, exc, space): @@ -136,13 +140,9 @@ s = " " * 4 else: s = " " - s += "-> (%s)" % repr_value(space, exc) + s += "-> (%s)" % self.repr_value(space, exc) self.print_line(s) - - def print_result(self, space, event_result): - for event in event_result.getevents(): - print_event(space, event, event_result) def print_event(self, space, event_result, event): from pypy.objspace import trace @@ -210,139 +210,58 @@ for c, t, f in reversed(self.indent_state): if f is not None: return f - -print_result = ResultPrinter().print_result -## XXX Sort out for next release :-( - -## def isinstance2(space, w_obj, cls): -## return space.is_true(space.appexec([w_obj, (space.wrap(cls.__name__))], -## """(o,c): -## return o.__class__.__name__ == c""")) - -## def get_dict_repr(space, w_obj): -## return space.str_w(space.appexec([w_obj],"""(d): -## s = "{" -## it = iter(d.items()) -## ii = 3 -## try: -## k, v = it.next() -## while True: -## s += "%s=%s" % (k,v) -## ii -= 1 -## if ii == 0: -## break -## k, v = it.next() -## s += ", " -## except StopIteration: -## pass -## s += "}" -## return s""")) -## def repr_value(space, obj): -## """ representations for debugging purposes """ +def simple_repr(space, obj): + res = repr(obj) + if len(res) > 80: + res = res[:76] + "..." + return res -## # Special case true and false (from space.is_true()) - we use a -## # different representation from a wrapped object reprs method. -## if obj == True: -## return "TRUE" - -## elif obj == False: -## return "FALSE" - -## # Special case - arguments -## from pypy.interpreter.argument import Arguments -## if isinstance(obj, Arguments): -## return "Arguments XXX" - -## # Special case - operation error -## from pypy.interpreter.error import OperationError -## if isinstance(obj, OperationError): -## return "OperationError(%s, %s)" % (repr_value(space, obj.w_type), -## repr_value(space, obj.w_value)) - - -## if hasattr(obj, "iter"): -## return repr([repr_value(x) for x in obj]) -## # pypy isintacnce macro type -## # if dict/list/tuple -## # iter over first 3 types -## try: -## if isinstance2(space, obj, dict): -## return simple_repr(obj) -## if isinstance2(space, obj, tuple): -## return simple_repr2(obj) -## if isinstance2(space, obj, list): -## return simple_repr2(obj) -## except: -## pass -## # Ok belows might take a long time... - -## # Try object's repr -## try: -## return space.str_w(space.repr(obj)) -## except: -## pass - -## # Arggh - unwrap repr -## try: -## return repr(space.unwrap(obj)) -## except: -## pass - -## # Give up... -## return repr(obj) - - -## res = simple_repr(obj) - -## try: -## from pypy.interpreter.baseobjspace import W_Root -## from pypy.interpreter.argument import Argument -## if isinstance(obj, W_Root): -## return simple_repr(space.unwrap(obj)) - -## if isinstance(obj, Argument): -## args_w, kwds_w = obj.unpack() -## res = "Argument(" -## res += ", ".join([repr_value(ii) for ii in args_w]) -## res += ")" -## except: -## pass - - -## elif space.is_true(space.appexec([w_value, space.wrap("keys")], """(x,y): -## return hasattr(x,y)""")): -## res = "Dict(%s)" % (space.str_w(space.repr(space.call_method(w_value, "keys")))[:40]) - - -## except: -## try: -## # XXX Sure this won't go down well - didn't really want -## # to clutter up the interpeter code -## from pypy.interpreter.function import Function, Method -## from pypy.interpreter.eval import Code - -## if isinstance(w_value, Function): -## res = "Function(%s)" % value.name - -## if isinstance(w_value, Method): -## res = "Method(%s)" % value.w_function.name +def repr_value_complex(space, obj): + """ representations - very slow """ -## raise Exception, "XXX only certain types or toooo slow" -## except: -## res = str(w_value) + from pypy.interpreter.argument import Arguments + from pypy.interpreter.error import OperationError -## return res[:80] + # Special case true and false (from space.is_true()) - we use a + # different representation from a wrapped object reprs method. + if obj is True: + return "TRUE" + + elif obj is False: + return "FALSE" + + if hasattr(obj, "__iter__"): + return ", ".join([repr_value(space, ii) for ii in obj]) + + # Special case - arguments + if isinstance(obj, Arguments): + args = [repr_value(space, ii) for ii in obj.arguments_w] + args += ["%s = %s" % (k, repr_value(space, v)) + for k, v in obj.kwds_w.items()] + if not obj.w_stararg is None: + args.append("*" + repr_value_complex(space, obj.w_stararg)) + if not obj.w_starstararg is None: + args.append("**" + repr_value_complex(space, obj.w_starstararg)) + return "Args(%s)" % (", ".join(args)) + + # Special case - operation error + if isinstance(obj, OperationError): + return "OpError(%s, %s)" % (repr_value(space, obj.w_type), + repr_value(space, obj.w_value)) + + # Try object repr + try: + return space.str_w(space.repr(obj)) + except: + # Give up + return repr(obj) -def simple_repr(space, obj): - res = repr(obj) - if len(res) > 80: - res = res[:76] + "..." - return res -repr_value = simple_repr +def repr_value(space, obj): + return repr_value_complex(space, obj)[:120] # __________________________________________________________________________ From arigo at codespeak.net Thu Jul 28 23:37:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 23:37:57 +0200 (CEST) Subject: [pypy-svn] r15303 - pypy/dist/pypy/objspace/std Message-ID: <20050728213757.8597C27B7B@code1.codespeak.net> Author: arigo Date: Thu Jul 28 23:37:54 2005 New Revision: 15303 Modified: pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/objspace.py Log: Fixed space.newlong(). Required a minor refactoring in longobject.py. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu Jul 28 23:37:54 2005 @@ -90,6 +90,34 @@ w_self.sign = sign assert len(w_self.digits) + def fromint(space, intval): + if intval < 0: + sign = -1 + ival = -intval + elif intval > 0: + sign = 1 + ival = intval + else: + return W_LongObject(space, [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 + # needed. + t = ival + ndigits = 0 + while t: + ndigits += 1 + t >>= SHIFT + v = W_LongObject(space, [0] * ndigits, sign) + t = ival + p = 0 + while t: + v.digits[p] = t & MASK + t >>= SHIFT + p += 1 + return v + fromint = staticmethod(fromint) + def longval(self): #YYYYYY l = 0 digits = list(self.digits) @@ -162,31 +190,7 @@ return W_LongObject(space, digits, sign) def long__Int(space, w_intobj): - if w_intobj.intval < 0: - sign = -1 - ival = -w_intobj.intval - elif w_intobj.intval > 0: - sign = 1 - ival = w_intobj.intval - else: - return W_LongObject(space, [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 - # needed. - t = ival - ndigits = 0 - while t: - ndigits += 1 - t >>= SHIFT - v = W_LongObject(space, [0] * ndigits, sign) - t = ival - p = 0 - while t: - v.digits[p] = t & MASK - t >>= SHIFT - p += 1 - return v + return W_LongObject.fromint(space, w_intobj.intval) def int__Long(space, w_value): try: Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu Jul 28 23:37:54 2005 @@ -319,12 +319,8 @@ return W_FloatObject(self, floatval) def newlong(self, val): # val is an int - if val == 0: - sign = 0 - else: - sign = 1 - return W_LongObject(self, [val], sign) - + return W_LongObject.fromint(self, val) + def newtuple(self, list_w): assert isinstance(list_w, list) return W_TupleObject(self, list_w) From rxe at codespeak.net Thu Jul 28 23:38:11 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Thu, 28 Jul 2005 23:38:11 +0200 (CEST) Subject: [pypy-svn] r15304 - pypy/dist/pypy/documentation Message-ID: <20050728213811.33A2C27B7B@code1.codespeak.net> Author: rxe Date: Thu Jul 28 23:38:09 2005 New Revision: 15304 Modified: pypy/dist/pypy/documentation/objspace.txt Log: issue25 in-progress One line doc pointing to config options. Modified: pypy/dist/pypy/documentation/objspace.txt ============================================================================== --- pypy/dist/pypy/documentation/objspace.txt (original) +++ pypy/dist/pypy/documentation/objspace.txt Thu Jul 28 23:38:09 2005 @@ -240,9 +240,12 @@ operations are usually shown. A quick introduction on how to use the trace object space can be `found here`_. +A number of options for configuration is here in `traceconfig.py`_. + .. _`found here` : getting_started.html#tracing-bytecode-and-operations-on-objects .. _`Abstract Interpretation`: theory.html#abstract-interpretation +.. _`traceconfig.py`: http://codespeak.net/svn/pypy/dist/pypy/tool/traceconfig.py The Thunk Object Space From arigo at codespeak.net Thu Jul 28 23:39:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 23:39:30 +0200 (CEST) Subject: [pypy-svn] r15305 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050728213930.EA08427B7B@code1.codespeak.net> Author: arigo Date: Thu Jul 28 23:39:27 2005 New Revision: 15305 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py Log: Typo. Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Thu Jul 28 23:39:27 2005 @@ -113,7 +113,7 @@ # note that the C code has a label here. # the logic is the same. if recode_encoding and ord(s[ps]) & 0x80: - w, ps = decode_utf8(space, s, ps, q, recode_encoding) + w, ps = decode_utf8(space, s, ps, end, recode_encoding) # Append bytes to output buffer. lis.append(w) else: From arigo at codespeak.net Thu Jul 28 23:59:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Jul 2005 23:59:23 +0200 (CEST) Subject: [pypy-svn] r15306 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050728215923.5FF7427B7B@code1.codespeak.net> Author: arigo Date: Thu Jul 28 23:59:20 2005 New Revision: 15306 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py Log: str.isalpha() is not RPython. Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Thu Jul 28 23:59:20 2005 @@ -14,7 +14,9 @@ unicode = False # string decoration handling - if quote.isalpha() or quote == '_': + o = ord(quote) + isalpha = (o>=97 and o<=122) or (o>=65 and o<=90) + if isalpha or quote == '_': if quote == 'u' or quote == 'U': ps += 1 quote = s[ps] From arigo at codespeak.net Fri Jul 29 00:48:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 00:48:01 +0200 (CEST) Subject: [pypy-svn] r15307 - pypy/dist/pypy/objspace/std Message-ID: <20050728224801.D7AD227B48@code1.codespeak.net> Author: arigo Date: Fri Jul 29 00:47:59 2005 New Revision: 15307 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Forgot to space.wrap() the error message :-( Raising UnicodeDecodeError needs 5 arguments anyway. Work around... Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Fri Jul 29 00:47:59 2005 @@ -88,10 +88,8 @@ for i in range(len(s)): code = ord(s[i]) if code >= 128: - raise OperationError(space.w_UnicodeDecodeError, - "'ascii' codec can't decode byte %s in " - "position %d: ordinal not in range(128)" % ( - hex(code), i)) + # 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) From arigo at codespeak.net Fri Jul 29 01:21:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 01:21:53 +0200 (CEST) Subject: [pypy-svn] r15308 - in pypy/dist/pypy: annotation interpreter rpython rpython/test translator/goal Message-ID: <20050728232153.119B627B4D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 01:21:45 2005 New Revision: 15308 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/rpython/objectmodel.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: (pedronis, arigo) * added an RPython helper function we_are_translated() which returns False when run on top of CPython, but True if the code has been translated. Using it is considered bad style or performance hacks. * used this function in pycompiler.py to speed up (quite a lot) translate_pypy.py Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Fri Jul 29 01:21:45 2005 @@ -233,6 +233,9 @@ clsdef = clsdef.commonbase(getbookkeeper().getclassdef(cls)) return SomeInstance(clsdef) +def robjmodel_we_are_translated(): + return immutablevalue(True) + ##def rarith_ovfcheck(s_obj): ## if isinstance(s_obj, SomeInteger) and s_obj.unsigned: @@ -269,6 +272,8 @@ ##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask BUILTIN_ANALYZERS[pypy.rpython.objectmodel.instantiate] = robjmodel_instantiate +BUILTIN_ANALYZERS[pypy.rpython.objectmodel.we_are_translated] = ( + robjmodel_we_are_translated) BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init BUILTIN_ANALYZERS[OSError.__init__.im_func] = exception_init Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Jul 29 01:21:45 2005 @@ -108,6 +108,7 @@ uselibfile=False, parser="recparser", compiler="pyparse", + translating=False, **kw ): "NOT_RPYTHON: Basic initialization of objects." @@ -121,6 +122,7 @@ self.options.uselibfile = uselibfile or nofaking self.options.compiler = compiler self.options.usemodules = usemodules + self.options.translating = translating self.setoptions(**kw) self.initialize() Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Fri Jul 29 01:21:45 2005 @@ -4,6 +4,7 @@ """ from codeop import PyCF_DONT_IMPLY_DEDENT from pypy.interpreter.error import OperationError +from pypy.rpython.objectmodel import we_are_translated class AbstractCompiler: @@ -266,6 +267,13 @@ def compile_parse_result(self, parse_result, filename, mode): space = self.space + if space.options.translating and not we_are_translated(): + # to avoid to spend too much time in the app-level compiler + # while translating PyPy, we can cheat here. The annotator + # doesn't see this because it thinks that we_are_translated() + # returns True. + return PythonCompiler.compile_parse_result(self, parse_result, + filename, mode) source_encoding, stack_element = parse_result w_nested_tuples = stack_element.as_w_tuple(space, lineno=True) if source_encoding is not None: Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Fri Jul 29 01:21:45 2005 @@ -12,3 +12,7 @@ return object.__new__(cls) else: return new.instance(cls) + +def we_are_translated(): + return False +# annotation -> True Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri Jul 29 01:21:45 2005 @@ -207,6 +207,9 @@ klass = s_class.const return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops) +def rtype_we_are_translated(hop): + return hop.inputconst(lltype.Bool, True) + # collect all functions import __builtin__ @@ -257,6 +260,7 @@ BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate +BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated from pypy.rpython import extfunctable Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Fri Jul 29 01:21:45 2005 @@ -1,6 +1,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test import test_llinterp -from pypy.rpython.objectmodel import instantiate +from pypy.rpython.objectmodel import instantiate, we_are_translated from pypy.rpython import lltype from pypy.objspace.flow import model as flowmodel from pypy.tool import udir @@ -211,3 +211,8 @@ res = interpret(f, [1]) assert res is False +def test_we_are_translated(): + def f(): + return we_are_translated() + res = interpret(f, []) + assert res is True and f() is False Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jul 29 01:21:45 2005 @@ -38,7 +38,9 @@ # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False - space = StdObjSpace(nofaking=True) + space = StdObjSpace(nofaking=True, + compiler="pyparseapp", + translating=True) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From arigo at codespeak.net Fri Jul 29 01:29:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 01:29:23 +0200 (CEST) Subject: [pypy-svn] r15309 - pypy/dist/pypy/interpreter Message-ID: <20050728232923.BA1A127B57@code1.codespeak.net> Author: arigo Date: Fri Jul 29 01:29:21 2005 New Revision: 15309 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: Missing import. Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Fri Jul 29 01:29:21 2005 @@ -277,6 +277,7 @@ source_encoding, stack_element = parse_result w_nested_tuples = stack_element.as_w_tuple(space, lineno=True) if source_encoding is not None: + from pypy.interpreter.pyparser import pysymbol w_nested_tuples = space.newtuple([ space.wrap(pysymbol.encoding_decl), w_nested_tuples, From arigo at codespeak.net Fri Jul 29 01:57:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 01:57:36 +0200 (CEST) Subject: [pypy-svn] r15310 - pypy/dist/pypy/interpreter Message-ID: <20050728235736.B380427B50@code1.codespeak.net> Author: arigo Date: Fri Jul 29 01:57:34 2005 New Revision: 15310 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: Check that the app-level compiler returns a code object. (Needed to help the annotator, too) Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Fri Jul 29 01:57:34 2005 @@ -115,7 +115,7 @@ except TypeError,e: raise OperationError(space.w_TypeError,space.wrap(str(e))) from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) + return PyCode(space)._from_code(c) compile._annspecialcase_ = "override:cpy_compile" def getcodeflags(self, code): @@ -189,8 +189,7 @@ except ParseError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, filename)) - w_code = self.compile_parse_result(parse_result, filename, mode) - return w_code + return self.compile_parse_result(parse_result, filename, mode) def compile_parse_result(self, parse_result, filename, mode): """NOT_RPYTHON""" @@ -230,7 +229,7 @@ raise OperationError(space.w_TypeError,space.wrap(str(e))) # __________ end of XXX above from pypy.interpreter.pycode import PyCode - return space.wrap(PyCode(space)._from_code(c)) + return PyCode(space)._from_code(c) compile_parse_result._annspecialcase_ = 'override:cpy_stablecompiler' @@ -287,7 +286,11 @@ w_nested_tuples, space.wrap(filename), space.wrap(mode)) - return w_code + code = space.interpclass_w(w_code) + if not isinstance(code, PyCode): + raise OperationError(space.w_RuntimeError, + space.wrap("code object expected")) + return code class PyPyCompiler(CPythonCompiler): From arigo at codespeak.net Fri Jul 29 02:05:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 02:05:26 +0200 (CEST) Subject: [pypy-svn] r15311 - pypy/dist/pypy/interpreter Message-ID: <20050729000526.0EA9427B50@code1.codespeak.net> Author: arigo Date: Fri Jul 29 02:05:25 2005 New Revision: 15311 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: Missing import. Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Fri Jul 29 02:05:25 2005 @@ -287,6 +287,7 @@ space.wrap(filename), space.wrap(mode)) code = space.interpclass_w(w_code) + from pypy.interpreter.pycode import PyCode if not isinstance(code, PyCode): raise OperationError(space.w_RuntimeError, space.wrap("code object expected")) From arigo at codespeak.net Fri Jul 29 02:19:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 02:19:44 +0200 (CEST) Subject: [pypy-svn] r15312 - pypy/dist/pypy/translator/goal Message-ID: <20050729001944.7D6CA27B50@code1.codespeak.net> Author: arigo Date: Fri Jul 29 02:19:42 2005 New Revision: 15312 Modified: pypy/dist/pypy/translator/goal/order.py Log: Additionally sort by module name if the module list is not precise enough. Modified: pypy/dist/pypy/translator/goal/order.py ============================================================================== --- pypy/dist/pypy/translator/goal/order.py (original) +++ pypy/dist/pypy/translator/goal/order.py Fri Jul 29 02:19:42 2005 @@ -41,7 +41,7 @@ if len(pfx) > len(prefixes[match]): match = i i += 1 - cache[tag] = match + cache[tag] = match, module return match pending.sort(lambda blk1, blk2: cmp(indx(blk1), indx(blk2))) From arigo at codespeak.net Fri Jul 29 02:22:02 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 02:22:02 +0200 (CEST) Subject: [pypy-svn] r15313 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050729002202.0B8BE27B50@code1.codespeak.net> Author: arigo Date: Fri Jul 29 02:21:59 2005 New Revision: 15313 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py Log: ! (arigo, pedronis) Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Fri Jul 29 02:21:59 2005 @@ -216,7 +216,7 @@ while ps < end and ord(s[ps]) & 0x80: ps += 1 w_u = PyUnicode_DecodeUTF8(space, space.wrap(s[pt : ps])) - w_v = PyUnicode_AsEncodedString(space, w_u, space.unwrap(encoding)) + w_v = PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) v = space.str_w(w_v) return v, ps From arigo at codespeak.net Fri Jul 29 02:27:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 02:27:16 +0200 (CEST) Subject: [pypy-svn] r15314 - pypy/dist/pypy/objspace/std Message-ID: <20050729002716.D953427B50@code1.codespeak.net> Author: arigo Date: Fri Jul 29 02:27:14 2005 New Revision: 15314 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: We don't use any more the W_LongObject(space, 123456789L) constructor signature. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Fri Jul 29 02:27:14 2005 @@ -84,8 +84,8 @@ def __init__(w_self, space, digits, sign=0): W_Object.__init__(w_self, space) - if isinstance(digits, long): #YYYYYY - digits, sign = args_from_long(digits) + #if isinstance(digits, long): #YYYYYY + # digits, sign = args_from_long(digits) w_self.digits = DigitArray(digits) w_self.sign = sign assert len(w_self.digits) From pedronis at codespeak.net Fri Jul 29 02:56:42 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 02:56:42 +0200 (CEST) Subject: [pypy-svn] r15315 - in pypy/dist/pypy: interpreter/pyparser interpreter/pyparser/test module/_codecs Message-ID: <20050729005642.8167F27B55@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 02:56:39 2005 New Revision: 15315 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py pypy/dist/pypy/module/_codecs/__init__.py Log: - fix in decode_utf8 - involved test to exercise it - _codecs should export 'encode' and 'decode' Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Fri Jul 29 02:56:39 2005 @@ -208,7 +208,7 @@ PyUnicode_DecodeUnicodeEscape = app.interphook('PyUnicode_DecodeUnicodeEscape') PyUnicode_DecodeRawUnicodeEscape = app.interphook('PyUnicode_DecodeRawUnicodeEscape') PyUnicode_DecodeUTF8 = app.interphook('PyUnicode_DecodeUTF8') -PyUnicode_AsEncodedString = app.interphook('PyUnicode_DecodeUTF8') +PyUnicode_AsEncodedString = app.interphook('PyUnicode_AsEncodedString') def decode_utf8(space, s, ps, end, encoding): pt = ps Modified: pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Fri Jul 29 02:56:39 2005 @@ -35,3 +35,8 @@ ret = space.unwrap(w_ret) assert isinstance(ret, unicode) assert ret == u'hello\u0842 world' + s = "u'\x81'" + s = s.decode("koi8-u").encode("utf8") + w_ret = parsestring.parsestr(self.space, 'koi8-u', s) + ret = space.unwrap(w_ret) + assert ret == u'\u2502' Modified: pypy/dist/pypy/module/_codecs/__init__.py ============================================================================== --- pypy/dist/pypy/module/_codecs/__init__.py (original) +++ pypy/dist/pypy/module/_codecs/__init__.py Fri Jul 29 02:56:39 2005 @@ -37,6 +37,8 @@ 'utf_7_encode' : 'app_codecs.utf_7_encode', 'utf_8_decode' : 'app_codecs.utf_8_decode', 'utf_8_encode' : 'app_codecs.utf_8_encode', + 'encode': 'app_codecs.encode', + 'decode': 'app_codecs.decode' } interpleveldefs = { } From pedronis at codespeak.net Fri Jul 29 02:59:00 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 02:59:00 +0200 (CEST) Subject: [pypy-svn] r15316 - pypy/dist/pypy/interpreter/pyparser/test Message-ID: <20050729005900.55B5027B55@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 02:58:58 2005 New Revision: 15316 Modified: pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Log: reformulate the test Modified: pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Fri Jul 29 02:58:58 2005 @@ -39,4 +39,4 @@ s = s.decode("koi8-u").encode("utf8") w_ret = parsestring.parsestr(self.space, 'koi8-u', s) ret = space.unwrap(w_ret) - assert ret == u'\u2502' + assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") From arigo at codespeak.net Fri Jul 29 03:01:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 03:01:45 +0200 (CEST) Subject: [pypy-svn] r15317 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20050729010145.51C3A27B55@code1.codespeak.net> Author: arigo Date: Fri Jul 29 03:01:43 2005 New Revision: 15317 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py Log: Some asserts to help convince the annotator that the slice indices are not negative. Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Fri Jul 29 03:01:43 2005 @@ -71,27 +71,31 @@ buf = ''.join(lis) bufp = 0 bufq = len(buf) + assert 0 <= bufp <= bufq + w_substr = space.wrap(buf[bufp : bufq]) if rawmode: - w_v = PyUnicode_DecodeRawUnicodeEscape(space, space.wrap(buf[bufp : bufq])) + w_v = PyUnicode_DecodeRawUnicodeEscape(space, w_substr) else: - w_v = PyUnicode_DecodeUnicodeEscape(space, space.wrap(buf[bufp : bufq])) + w_v = PyUnicode_DecodeUnicodeEscape(space, w_substr) return w_v need_encoding = (encoding is not None and encoding != "utf-8" and encoding != "iso-8859-1") # XXX add strchr like interface to rtyper + assert 0 <= ps <= q + substr = s[ps : q] if rawmode or '\\' not in s[ps:]: if need_encoding: - w_u = PyUnicode_DecodeUTF8(space, space.wrap(s[ps : q])) + w_u = PyUnicode_DecodeUTF8(space, space.wrap(substr)) w_v = PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) return w_v else: - return space.wrap(s[ps : q]) + return space.wrap(substr) enc = None if need_encoding: enc = encoding - v = PyString_DecodeEscape(space, s[ps : q], unicode, enc) + v = PyString_DecodeEscape(space, substr, unicode, enc) return space.wrap(v) def hexbyte(val): @@ -175,6 +179,7 @@ # non-escape mode. lis.append('\\') ps -= 1 + assert ps >= 0 continue # an arbitry number of unescaped UTF-8 bytes may follow. @@ -211,6 +216,7 @@ PyUnicode_AsEncodedString = app.interphook('PyUnicode_AsEncodedString') def decode_utf8(space, s, ps, end, encoding): + assert ps >= 0 pt = ps # while (s < end && *s != '\\') s++; */ /* inefficient for u".." while ps < end and ord(s[ps]) & 0x80: From pedronis at codespeak.net Fri Jul 29 03:27:36 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 03:27:36 +0200 (CEST) Subject: [pypy-svn] r15318 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20050729012736.B437427B57@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 03:27:33 2005 New Revision: 15318 Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Log: new test, doesn't work right now failing somewhere from app_codecs. parsestr itself is correct because encoding through cheating passes the test the problem need to be tracked and fixed Modified: pypy/dist/pypy/interpreter/pyparser/parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/parsestring.py Fri Jul 29 03:27:33 2005 @@ -87,6 +87,7 @@ if rawmode or '\\' not in s[ps:]: if need_encoding: w_u = PyUnicode_DecodeUTF8(space, space.wrap(substr)) + #w_v = space.wrap(space.unwrap(w_u).encode(encoding)) this works w_v = PyUnicode_AsEncodedString(space, w_u, space.wrap(encoding)) return w_v else: Modified: pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_parsestring.py Fri Jul 29 03:27:33 2005 @@ -1,4 +1,5 @@ from pypy.interpreter.pyparser import parsestring +import py class TestParsetring: def test_simple(self): @@ -40,3 +41,13 @@ w_ret = parsestring.parsestr(self.space, 'koi8-u', s) ret = space.unwrap(w_ret) assert ret == eval("# -*- coding: koi8-u -*-\nu'\x81'") + + def test_simple_enc_roundtrip(self): + py.test.skip("crashes in app_codecs, but when cheating using .encode at interp-level passes?!") + space = self.space + s = "'\x81'" + s = s.decode("koi8-u").encode("utf8") + w_ret = parsestring.parsestr(self.space, 'koi8-u', s) + ret = space.unwrap(w_ret) + assert ret == eval("# -*- coding: koi8-u -*-\n'\x81'") + From arigo at codespeak.net Fri Jul 29 03:44:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 03:44:57 +0200 (CEST) Subject: [pypy-svn] r15319 - pypy/dist/pypy/rpython Message-ID: <20050729014457.8078427B57@code1.codespeak.net> Author: arigo Date: Fri Jul 29 03:44:55 2005 New Revision: 15319 Modified: pypy/dist/pypy/rpython/rslice.py Log: Fix for a bug that hides an unknown number of "slice indices must be proved non-negative". Picking the key for the rtyper repr must be done veeeery carefully... (pedronis, arigo) Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Fri Jul 29 03:44:55 2005 @@ -40,14 +40,9 @@ return startstop_slice_repr def rtyper_makekey(self): - if (self.start.is_constant() and self.start.const in (None, 0) and - self.stop.is_constant() and self.stop.const == -1): - kind = "minusone" # [:-1] - elif self.stop.is_constant() and self.stop.const is None: - kind = "startonly" - else: - kind = "startstop" - return self.__class__, kind + # use the repr itself as the key (it can only be one of the three + # prebuilt reprs below). + return self.__class__, self.rtyper_makerepr(None) class SliceRepr(Repr): From ale at codespeak.net Fri Jul 29 09:09:58 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 29 Jul 2005 09:09:58 +0200 (CEST) Subject: [pypy-svn] r15320 - pypy/dist/pypy/lib Message-ID: <20050729070958.397CA27B5E@code1.codespeak.net> Author: ale Date: Fri Jul 29 09:09:56 2005 New Revision: 15320 Modified: pypy/dist/pypy/lib/struct.py Log: removed a check for size of signed short. It seems that test_binhex relies on struct to truncate the value. Modified: pypy/dist/pypy/lib/struct.py ============================================================================== --- pypy/dist/pypy/lib/struct.py (original) +++ pypy/dist/pypy/lib/struct.py Fri Jul 29 09:09:56 2005 @@ -1,37 +1,37 @@ -"""Functions to convert between Python values and C structs. -Python strings are used to hold the data representing the C struct +"""Functions to convert between Python values and C structs. +Python strings are used to hold the data representing the C struct and also as format strings to describe the layout of data in the C struct. -The optional first format char indicates byte order, size and alignment: - @: native order, size & alignment (default) - =: native order, std. size & alignment - <: little-endian, std. size & alignment - >: big-endian, std. size & alignment - !: same as > - -The remaining chars indicate types of args and must match exactly; -these can be preceded by a decimal repeat count: - x: pad byte (no data); - c:char; - b:signed byte; - B:unsigned byte; - h:short; - H:unsigned short; - i:int; - I:unsigned int; - l:long; - L:unsigned long; - f:float; - d:double. -Special cases (preceding decimal count indicates length): - s:string (array of char); p: pascal string (with count byte). -Special case (only available in native format): - P:an integer type that is wide enough to hold a pointer. -Special case (not in native mode unless 'long long' in platform C): - q:long long; - Q:unsigned long long -Whitespace between formats is ignored. - +The optional first format char indicates byte order, size and alignment: + @: native order, size & alignment (default) + =: native order, std. size & alignment + <: little-endian, std. size & alignment + >: big-endian, std. size & alignment + !: same as > + +The remaining chars indicate types of args and must match exactly; +these can be preceded by a decimal repeat count: + x: pad byte (no data); + c:char; + b:signed byte; + B:unsigned byte; + h:short; + H:unsigned short; + i:int; + I:unsigned int; + l:long; + L:unsigned long; + f:float; + d:double. +Special cases (preceding decimal count indicates length): + s:string (array of char); p: pascal string (with count byte). +Special case (only available in native format): + P:an integer type that is wide enough to hold a pointer. +Special case (not in native mode unless 'long long' in platform C): + q:long long; + Q:unsigned long long +Whitespace between formats is ignored. + The variable struct.error is an exception raised on errors.""" import math, sys @@ -51,11 +51,11 @@ def unpack_signed_int(data,index,size,le): number = unpack_int(data,index,size,le) - max = 2**(size*8) + max = 2**(size*8) if number > 2**(size*8 - 1) - 1: number = int(-1*(max - number)) return number - + def unpack_float(data,index,size,le): bytes = [ord(b) for b in data[index:index+size]] if len(bytes) != size: @@ -72,42 +72,37 @@ bias = 1023 exp = 11 prec = 52 -# print bytes,size,index,len(data),data mantissa = long(bytes[size-2] & (2**(15-exp)-1)) -# print mantissa for b in bytes[size-3::-1]: mantissa = mantissa << 8 | b -# print mantissa mantissa = 1 + (1.0*mantissa)/(2**(prec)) mantissa /= 2 -# print mantissa e = (bytes[-1] & 0x7f) << (exp - 7) e += (bytes[size-2] >> (15 - exp)) & (2**(exp - 7) -1) e -= bias e += 1 sign = bytes[-1] & 0x80 number = math.ldexp(mantissa,e) -# print number,index,mantissa,e,bytes#,data if sign : number *= -1 return number def unpack_char(data,index,size,le): return data[index:index+size] - + def pack_int(number,size,le): x=number res=[] for i in range(size): res.append(chr(x&0xff)) - x >>= 8 + x >>= 8 if le == 'big': res.reverse() - return ''.join(res) - + return ''.join(res) + def pack_signed_int(number,size,le): if not isinstance(number, (int,long)): raise StructError,"argument for i,I,l,L,q,Q,h,H must be integer" - if number > 2**(8*size-1)-1 or number < -1*2**(8*size-1): + if number < -1*2**(8*size-1): #number > 2**(8*size-1)-1 or raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) @@ -119,22 +114,21 @@ if number > 2**(8*size)-1: raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) - + def pack_char(char,size,le): -# print char return str(char) def sane_float(man,e): # TODO: XXX Implement checks for floats return True - + def pack_float(number, size, le): - + if number < 0: sign = 1 number *= -1 elif number == 0.0: - return "\x00" * size + return "\x00" * size else: sign = 0 if size == 4: @@ -145,7 +139,7 @@ bias = 1023 exp = 11 prec = 52 - + man, e = math.frexp(number) if 0.5 <= man and man < 1.0: man *= 2 @@ -153,12 +147,12 @@ if sane_float(man,e): man -= 1 e += bias - mantissa = int(2**prec *(man) +0.5) + mantissa = int(2**prec *(man) +0.5) res=[] if mantissa >> prec : mantissa = 0 e += 1 - + for i in range(size-2): res += [ mantissa & 0xff] mantissa >>= 8 @@ -168,7 +162,7 @@ res.reverse() return ''.join([chr(x) for x in res]) # TODO: What todo with insane floats/doubles. handle in sanefloat? - + big_endian_format = { 'x':{ 'size' : 1, 'alignment' : 0, 'pack' : None, 'unpack' : None}, 'b':{ 'size' : 1, 'alignment' : 0, 'pack' : pack_signed_int, 'unpack' : unpack_signed_int}, @@ -188,12 +182,12 @@ 'd':{ 'size' : 8, 'alignment' : 0, 'pack' : pack_float, 'unpack' : unpack_float}, } default = big_endian_format -formatmode={ '<' : (default, 'little'), - '>' : (default, 'big'), +formatmode={ '<' : (default, 'little'), + '>' : (default, 'big'), '!' : (default, 'big'), '=' : (default, sys.byteorder), '@' : (default, sys.byteorder) - } + } def getmode(fmt): try: @@ -214,12 +208,12 @@ i += 1 cur = fmt[i] return num,i - + def calcsize(fmt): - """calcsize(fmt) -> int - Return size of C struct described by format string fmt. + """calcsize(fmt) -> int + Return size of C struct described by format string fmt. See struct.__doc__ for more on format strings.""" - + formatdef,endianness,i = getmode(fmt) num = 0 result = 0 @@ -237,10 +231,10 @@ num = 0 i += 1 return result - + def pack(fmt,*args): - """pack(fmt, v1, v2, ...) -> string - Return string containing values v1, v2, ... packed according to fmt. + """pack(fmt, v1, v2, ...) -> string + Return string containing values v1, v2, ... packed according to fmt. See struct.__doc__ for more on format strings.""" formatdef,endianness,i = getmode(fmt) args = list(args) @@ -258,7 +252,7 @@ num = 1 else: num_s = num - + if cur == 'x': result += ['\0'*num] elif cur == 's': @@ -271,7 +265,7 @@ elif cur == 'p': if isinstance(args[0], str): padding = num - len(args[0]) - 1 - + if padding > 0: result += [chr(len(args[0])) + args[0][:num-1] + '\0'*padding] else: @@ -282,7 +276,7 @@ args.pop(0) else: raise StructError,"arg for string format not a string" - + else: if len(args) == 0: raise StructError,"insufficient arguments to pack" @@ -294,14 +288,13 @@ if len(args) != 0: raise StructError,"too many arguments for pack format" return ''.join(result) - + def unpack(fmt,data): """unpack(fmt, string) -> (v1, v2, ...) Unpack the string, containing packed C structure data, according to fmt. Requires len(string)==calcsize(fmt). See struct.__doc__ for more on format strings.""" formatdef,endianness,i = getmode(fmt) -# print fmt,data j = 0 num = 0 result = [] @@ -315,7 +308,7 @@ format = formatdef[cur] except KeyError: raise StructError,"%s is not a valid format"%cur - + if not num : num = 1 if cur == 'x': @@ -332,7 +325,7 @@ result.append(data[j+1:j+n+1]) j += num i += 1 - else: + else: for n in range(num): result += [format['unpack'](data,j,format['size'],endianness)] j += format['size'] @@ -344,4 +337,4 @@ print pack_float(1.23,4,'little') import struct print (struct.pack('f',1.23), pack('f',1.23)) - print unpack('f',pack('f',1.23)) + print unpack('f',pack('f',1.23)) From arigo at codespeak.net Fri Jul 29 10:43:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 10:43:25 +0200 (CEST) Subject: [pypy-svn] r15324 - in pypy/dist/pypy: interpreter/pyparser module/recparser objspace/std Message-ID: <20050729084325.37AA927B64@code1.codespeak.net> Author: arigo Date: Fri Jul 29 10:43:23 2005 New Revision: 15324 Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py pypy/dist/pypy/module/recparser/pyparser.py pypy/dist/pypy/objspace/std/longobject.py Log: Fix what are apparently the last three remaining errors "slice start must be proved non-negative". Modified: pypy/dist/pypy/interpreter/pyparser/pythonlexer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonlexer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonlexer.py Fri Jul 29 10:43:23 2005 @@ -25,7 +25,7 @@ >>> py_encoding.search(comment) """ index = comment.find('coding') - if index == -1: + if index < 0: return None next_char = comment[index + 6] if next_char not in ':=': Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Fri Jul 29 10:43:23 2005 @@ -29,8 +29,10 @@ for n in node.nodes: n.visit(self) n = len(node.nodes) - l = [ space.wrap( node.name ) ] + self.tuple_stack_w[-n:] - del self.tuple_stack_w[-n:] + start = len(self.tuple_stack_w) - n + assert start >= 0 # annotator hint + l = [ space.wrap( node.name ) ] + self.tuple_stack_w[start:] + del self.tuple_stack_w[start:] self.tuple_stack_w.append( space.newtuple( l ) ) def visit_tempsyntaxnode( self, node ): Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Fri Jul 29 10:43:23 2005 @@ -1488,6 +1488,8 @@ p -= 1 s[p] = '-' + assert p >= 0 # otherwise, buffer overflow (this is also a + # hint for the annotator for the slice below) if p == 0: return ''.join(s) else: From ale at codespeak.net Fri Jul 29 11:55:17 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 29 Jul 2005 11:55:17 +0200 (CEST) Subject: [pypy-svn] r15327 - in pypy/dist: lib-python/modified-2.4.1 pypy/lib Message-ID: <20050729095517.2BD6E27B6A@code1.codespeak.net> Author: ale Date: Fri Jul 29 11:55:15 2005 New Revision: 15327 Added: pypy/dist/lib-python/modified-2.4.1/binhex.py - copied, changed from r15319, pypy/dist/lib-python/2.4.1/binhex.py Modified: pypy/dist/pypy/lib/struct.py Log: changed binhex.py to use unsigned short in crc instead of signed short. reverted previous checkin to struct Copied: pypy/dist/lib-python/modified-2.4.1/binhex.py (from r15319, pypy/dist/lib-python/2.4.1/binhex.py) ============================================================================== --- pypy/dist/lib-python/2.4.1/binhex.py (original) +++ pypy/dist/lib-python/modified-2.4.1/binhex.py Fri Jul 29 11:55:15 2005 @@ -217,7 +217,7 @@ def _writecrc(self): # XXXX Should this be here?? # self.crc = binascii.crc_hqx('\0\0', self.crc) - self.ofp.write(struct.pack('>h', self.crc)) + self.ofp.write(struct.pack('>H', self.crc)) self.crc = 0 def write(self, data): Modified: pypy/dist/pypy/lib/struct.py ============================================================================== --- pypy/dist/pypy/lib/struct.py (original) +++ pypy/dist/pypy/lib/struct.py Fri Jul 29 11:55:15 2005 @@ -102,7 +102,7 @@ def pack_signed_int(number,size,le): if not isinstance(number, (int,long)): raise StructError,"argument for i,I,l,L,q,Q,h,H must be integer" - if number < -1*2**(8*size-1): #number > 2**(8*size-1)-1 or + if number > 2**(8*size-1)-1 or number < -1*2**(8*size-1): raise OverflowError,"Number:%i too large to convert" % number return pack_int(number,size,le) From ericvrp at codespeak.net Fri Jul 29 12:22:42 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 12:22:42 +0200 (CEST) Subject: [pypy-svn] r15328 - pypy/dist/pypy/translator/llvm2/tool Message-ID: <20050729102242.3FA2927B6C@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 12:22:41 2005 New Revision: 15328 Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Log: Fixed bug whereby it looked asif ll_os_path required all the ll_os suggested primitives again Modified: pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py (original) +++ pypy/dist/pypy/translator/llvm2/tool/suggested_primitive.py Fri Jul 29 12:22:41 2005 @@ -7,8 +7,10 @@ from pypy.translator.llvm2.module.extfunction import extfunctions def main(): + seen = Set() for module in (ll_os, ll_os_path, ll_time, ll_math): #XXX keep this list up-to-date too - suggested_primitives = Set( [func for func in dir(module) if getattr(module.__dict__[func], 'suggested_primitive', False)] ) + suggested_primitives = Set( [func for func in dir(module) if func not in seen and getattr(module.__dict__[func], 'suggested_primitive', False)] ) + seen |= suggested_primitives implemented_primitives = Set( [f[1:] for f in extfunctions.keys()] ) missing_primitives = suggested_primitives - implemented_primitives print 'Missing llvm primitives for %s:' % module.__name__ From ericvrp at codespeak.net Fri Jul 29 12:23:24 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 12:23:24 +0200 (CEST) Subject: [pypy-svn] r15329 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050729102324.8E51927B7B@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 12:23:23 2005 New Revision: 15329 Modified: pypy/dist/pypy/translator/llvm2/genllvm.py Log: nicer error message for missing external functions Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 29 12:23:23 2005 @@ -82,7 +82,10 @@ deps.reverse() for dep in deps: if dep not in depdone: - llvm_code = extfunctions[dep][1] + try: + llvm_code = extfunctions[dep][1] + except KeyError: + raise Exception('primitive function %s has no implementation' %(dep,)) for extfunc in llvm_code.split('\n'): codewriter.append(extfunc) depdone[dep] = True From ericvrp at codespeak.net Fri Jul 29 12:33:24 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 12:33:24 +0200 (CEST) Subject: [pypy-svn] r15330 - in pypy/dist/pypy/translator/llvm2: module test Message-ID: <20050729103324.EAA4827B88@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 12:33:23 2005 New Revision: 15330 Added: pypy/dist/pypy/translator/llvm2/module/ll_math.py pypy/dist/pypy/translator/llvm2/module/ll_os.py pypy/dist/pypy/translator/llvm2/module/ll_os_path.py pypy/dist/pypy/translator/llvm2/module/ll_time.py pypy/dist/pypy/translator/llvm2/module/support.py Modified: pypy/dist/pypy/translator/llvm2/module/extfunction.py pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Log: added simple os.math functions and tests Modified: pypy/dist/pypy/translator/llvm2/module/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/module/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/module/extfunction.py Fri Jul 29 12:33:23 2005 @@ -1,25 +1,16 @@ -extdeclarations = """ +extdeclarations = """;gc-type dependent mallocs declare sbyte* %gc_malloc(uint) declare sbyte* %gc_malloc_atomic(uint) -declare int %time(int*) ;void* actually -declare int %clock() -declare void %sleep(int) -declare int %dup(int) -declare void %close(int) -declare int %open(sbyte*, int, int) -declare int %write(int, sbyte*, int) -declare int %read(int, sbyte*, int) -declare sbyte* %strncpy(sbyte*, sbyte*, int) - +;rpython stuff %structtype.rpy_string = type {int, {int, [0 x sbyte]}} +;exception handling globals %last_exception_type = global long 0 %last_exception_value = global long 0 """ -gc_boehm = """ -declare sbyte* %GC_malloc(uint) +gc_boehm = """declare sbyte* %GC_malloc(uint) declare sbyte* %GC_malloc_atomic(uint) sbyte* %gc_malloc(uint %n) { @@ -31,11 +22,9 @@ %ptr = call sbyte* %GC_malloc_atomic(uint %n) ret sbyte* %ptr } - """ -gc_disabled = """ -sbyte* %gc_malloc(uint %n) { +gc_disabled = """sbyte* %gc_malloc(uint %n) { %ptr = malloc sbyte, uint %n ret sbyte* %ptr } @@ -44,111 +33,16 @@ %ptr = malloc sbyte, uint %n ret sbyte* %ptr } - """ extfunctions = {} #dependencies, llvm-code -extfunctions["%cast"] = ((), """ -sbyte* %cast(%structtype.rpy_string* %structstring) { - %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - %length = add int %reallength, 1 - %ulength = cast int %length to uint - %dest = call sbyte* %gc_malloc_atomic(uint %ulength) - - %source1ptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 - %source1 = cast [0 x sbyte]* %source1ptr to sbyte* - %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) - - %zeropos1 = cast sbyte* %dest to int - %zeropos2 = add int %zeropos1, %reallength - %zerodest = cast int %zeropos2 to sbyte* - store sbyte 0, sbyte* %zerodest - - ret sbyte* %dest -} - -""") - -extfunctions["%ll_time_time"] = ((), """ -double %ll_time_time() { - %v0 = call int %time(int* null) - %v1 = cast int %v0 to double - ret double %v1 -} - -""") - -extfunctions["%ll_time_clock"] = ((), """ -double %ll_time_clock() { - %v0 = call int %clock() - %v1 = cast int %v0 to double - ; XXX how to get at the proper division (or any other) constant per platform? - %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC accrdoing to single unix spec - ret double %v2 -} - -""") - -extfunctions["%ll_time_sleep"] = ((), """ -void %ll_time_sleep(double %f) { - %i = cast double %f to int - call void %sleep(int %i) - ret void -} - -""") - -extfunctions["%ll_os_dup"] = ((), """ -int %ll_os_dup(int %fd) { - %ret = call int %dup(int %fd) - ret int %ret -} - -""") - -extfunctions["%ll_os_close"] = ((), """ -void %ll_os_close(int %fd) { - call void %close(int %fd) - ret void -} - -""") - -extfunctions["%ll_os_open"] = (("%cast",), """ -int %ll_os_open(%structtype.rpy_string* %structstring, int %flag, int %mode) { - %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) - %fd = call int %open(sbyte* %dest, int %flag, int %mode) - ret int %fd -} - -""") - -extfunctions["%ll_os_write"] = (("%cast",), """ -int %ll_os_write(int %fd, %structtype.rpy_string* %structstring) { - %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) - %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) - ret int %byteswritten -} - -""") - -extfunctions["%ll_read_into"] = ((), """ -int %ll_read_into(int %fd, %structtype.rpy_string* %structstring) { - %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 - %reallength = load int* %reallengthptr - - %destptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 - %dest = cast [0 x sbyte]* %destptr to sbyte* - - %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength) - ret int %bytesread -} +import support, ll_os, ll_os_path, ll_time, ll_math -""") +for module in (support, ll_os, ll_os_path, ll_time, ll_math): + extdeclarations += module.extdeclarations + extfunctions.update(module.extfunctions) +extdeclarations += '\n;application function prototypes' def dependencies(funcname, deplist): deplist.append(funcname) Added: pypy/dist/pypy/translator/llvm2/module/ll_math.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/module/ll_math.py Fri Jul 29 12:33:23 2005 @@ -0,0 +1,37 @@ +extdeclarations = """ +;ll_math.py +declare double %acos(double) +declare double %asin(double) +declare double %atan(double) +declare double %ceil(double) +declare double %cos(double) +declare double %cosh(double) +declare double %exp(double) +declare double %fabs(double) +declare double %floor(double) +declare double %log(double) +declare double %log10(double) +declare double %sin(double) +declare double %sinh(double) +declare double %sqrt(double) +declare double %tan(double) +declare double %tanh(double) +""" + +extfunctions = {} + +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +func_template = """ +double %%ll_math_%(func)s(double %%x) { + %%t = call double %%%(func)s(double %%x) + ret double %%t +} + +""" + +for func in simple_math_functions: + extfunctions["%ll_math_" + func] = ((), func_template % locals()) Added: pypy/dist/pypy/translator/llvm2/module/ll_os.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/module/ll_os.py Fri Jul 29 12:33:23 2005 @@ -0,0 +1,61 @@ +extdeclarations = """ +;ll_os.py +declare int %dup(int) +declare void %close(int) +declare int %open(sbyte*, int, int) +declare int %write(int, sbyte*, int) +declare int %read(int, sbyte*, int) +declare sbyte* %strncpy(sbyte*, sbyte*, int) +""" + +extfunctions = {} + +extfunctions["%ll_os_dup"] = ((), """ +int %ll_os_dup(int %fd) { + %ret = call int %dup(int %fd) + ret int %ret +} + +""") + +extfunctions["%ll_os_close"] = ((), """ +void %ll_os_close(int %fd) { + call void %close(int %fd) + ret void +} + +""") + +extfunctions["%ll_os_open"] = (("%cast",), """ +int %ll_os_open(%structtype.rpy_string* %structstring, int %flag, int %mode) { + %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) + %fd = call int %open(sbyte* %dest, int %flag, int %mode) + ret int %fd +} + +""") + +extfunctions["%ll_os_write"] = (("%cast",), """ +int %ll_os_write(int %fd, %structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr + %dest = call sbyte* %cast(%structtype.rpy_string* %structstring) + %byteswritten = call int %write(int %fd, sbyte* %dest, int %reallength) + ret int %byteswritten +} + +""") + +extfunctions["%ll_read_into"] = ((), """ +int %ll_read_into(int %fd, %structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr + + %destptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 + %dest = cast [0 x sbyte]* %destptr to sbyte* + + %bytesread = call int %read(int %fd, sbyte* %dest, int %reallength) + ret int %bytesread +} + +""") Added: pypy/dist/pypy/translator/llvm2/module/ll_os_path.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/module/ll_os_path.py Fri Jul 29 12:33:23 2005 @@ -0,0 +1,3 @@ +extdeclarations = "" + +extfunctions = {} Added: pypy/dist/pypy/translator/llvm2/module/ll_time.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/module/ll_time.py Fri Jul 29 12:33:23 2005 @@ -0,0 +1,37 @@ +extdeclarations = ''' +;ll_time.py +declare int %time(int*) ;void* actually +declare int %clock() +declare void %sleep(int) +''' + +extfunctions = {} + +extfunctions["%ll_time_time"] = ((), """ +double %ll_time_time() { + %v0 = call int %time(int* null) + %v1 = cast int %v0 to double + ret double %v1 +} + +""") + +extfunctions["%ll_time_clock"] = ((), """ +double %ll_time_clock() { + %v0 = call int %clock() + %v1 = cast int %v0 to double + ; XXX how to get at the proper division (or any other) constant per platform? + %v2 = div double %v1, 1000000.0 ;CLOCKS_PER_SEC accrdoing to single unix spec + ret double %v2 +} + +""") + +extfunctions["%ll_time_sleep"] = ((), """ +void %ll_time_sleep(double %f) { + %i = cast double %f to int + call void %sleep(int %i) + ret void +} + +""") Added: pypy/dist/pypy/translator/llvm2/module/support.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/module/support.py Fri Jul 29 12:33:23 2005 @@ -0,0 +1,25 @@ +extdeclarations = "" + +extfunctions = {} + +extfunctions["%cast"] = ((), """ +sbyte* %cast(%structtype.rpy_string* %structstring) { + %reallengthptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 0 + %reallength = load int* %reallengthptr + %length = add int %reallength, 1 + %ulength = cast int %length to uint + %dest = call sbyte* %gc_malloc_atomic(uint %ulength) + + %source1ptr = getelementptr %structtype.rpy_string* %structstring, int 0, uint 1, uint 1 + %source1 = cast [0 x sbyte]* %source1ptr to sbyte* + %dummy = call sbyte* %strncpy(sbyte* %dest, sbyte* %source1, int %reallength) + + %zeropos1 = cast sbyte* %dest to int + %zeropos2 = add int %zeropos1, %reallength + %zerodest = cast int %zeropos2 to sbyte* + store sbyte 0, sbyte* %zerodest + + ret sbyte* %dest +} + +""") Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Fri Jul 29 12:33:23 2005 @@ -54,14 +54,14 @@ assert f(False) == 2 def test_global_instance(self): - py.test.skip("not working yet") + py.test.skip("modify global instance not working properly yet") f = compile_function(llvmsnippet.global_instance, [int]) assert f(-1) == llvmsnippet.global_instance(-1) for i in range(20): assert f(i) == llvmsnippet.global_instance(i) def test_call_degrading_func(self): - py.test.skip("not working yet") + py.test.skip("call degrading not working yet") f = compile_function(llvmsnippet.call_degrading_func, [bool]) assert f(True) == llvmsnippet.call_degrading_func(True) #-36 assert f(False) == llvmsnippet.call_degrading_func(False) #14 Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Fri Jul 29 12:33:23 2005 @@ -91,3 +91,102 @@ assert os.path.exists(path) assert open(path).read() == path * 3 assert result is len(path) * 3 + +# following from translator/c/test/test_extfunc.py Revision: 15320 (jul 29th 2005) + +def test_os_stat(): + py.test.skip("ll_os_stat not implemented") + filename = str(py.magic.autopath()) + def call_stat(): + st = os.stat(filename) + return st + f = compile_function(call_stat, []) + result = f() + assert result[0] == os.stat(filename)[0] + assert result[1] == os.stat(filename)[1] + assert result[2] == os.stat(filename)[2] + +def test_os_fstat(): + py.test.skip("ll_os_fstat not implemented") + filename = str(py.magic.autopath()) + def call_fstat(): + fd = os.open(filename, os.O_RDONLY, 0777) + st = os.fstat(fd) + os.close(fd) + return st + f = compile_function(call_fstat, []) + result = f() + assert result[0] == os.stat(filename)[0] + assert result[1] == os.stat(filename)[1] + assert result[2] == os.stat(filename)[2] + +def test_getcwd(): + py.test.skip("ll_os_getcwd not implemented") + def does_stuff(): + return os.getcwd() + f1 = compile_function(does_stuff, []) + res = f1() + assert res == os.getcwd() + +def test_math_frexp(): + py.test.skip("ll_math_frexp not implemented") + from math import frexp + def fn(x): + return frexp(x) + f = compile_function(fn, [float]) + assert f(10.123) == frexp(10.123) + +def test_math_modf(): + py.test.skip("ll_math_modf not implemented (next)") + from math import modf + def fn(x): + return modf(x) + f = compile_function(fn, [float]) + assert f(10.123) == modf(10.123) + +simple_math_functions = [ + 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', + 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' + ] + +def math_function_test(funcname): + import random + import math + mathfn = getattr(math, funcname) + print funcname, + def fn(x): + return mathfn(x) + f = compile_function(fn, [float]) + for x in [0.12334, 0.3, 0.5, 0.9883]: + print x + assert f(x) == mathfn(x) + +def test_simple_math_functions(): + for funcname in simple_math_functions: + yield math_function_test, funcname + +def test_os_path_exists(): + py.test.skip("ll_os_stat not implemented") + tmpfile = str(udir.join('test_os_path_exists.TMP')) + def fn(): + return os.path.exists(tmpfile) + f = compile_function(fn, []) + open(tmpfile, 'w').close() + assert f() == True + os.unlink(tmpfile) + assert f() == False + +def test_os_path_isdir(): + py.test.skip("ll_os_stat not implemented") + directory = "./." + def fn(): + return os.path.isdir(directory) + f = compile_function(fn, []) + assert f() == True + directory = "some/random/name" + def fn(): + return os.path.isdir(directory) + f = compile_function(fn, []) + assert f() == False + +# end of tests taken from c backend Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Fri Jul 29 12:33:23 2005 @@ -16,7 +16,7 @@ assert f() == 1 def test_simple_function_pointer(): - py.test.skip("not working yet") + py.test.skip("function pointers not working yet") def f1(x): return x + 1 def f2(x): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Fri Jul 29 12:33:23 2005 @@ -89,7 +89,7 @@ assert f(3) == 8 def test_pbc_function2(self): - py.test.skip("not working yet") + py.test.skip("pbc circular not working yet") f = compile_function(llvmsnippet.pbc_function2, [int]) assert f(0) == 13 assert f(1) == 15 From cfbolz at codespeak.net Fri Jul 29 12:49:02 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 12:49:02 +0200 (CEST) Subject: [pypy-svn] r15331 - pypy/extradoc/sprintinfo Message-ID: <20050729104902.32BFD27B90@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 12:49:01 2005 New Revision: 15331 Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: planning for today Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-done.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-done.txt Fri Jul 29 12:49:01 2005 @@ -104,3 +104,24 @@ - Richard, Chris track down remaining .pyc file issues. + + + +Getting rid of faking:: + + DONE. no faking left if you use --file --nofakedmodules. + (of course in this case you can't import most modules like + _sre at all.) + + + - DONE unify the way stdobjspace is configured. + the basic objspace configuration interface + becomes a set of keyword arguments. The current + command line arguments will be mapped onto this + interface. + This also includes configuration of which modules + should be loaded. + + - DONE extend the testing framework to allow to specify + a space with options for a test. Related to the latter. + Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Fri Jul 29 12:49:01 2005 @@ -1,4 +1,5 @@ + PyPy Hildesheim2 sprint planning (25th-31st July) ------------------------------------------------------- @@ -57,34 +58,42 @@ Ultimately the compiler and marshal should both be at interp-level anyway. -Getting rid of faking:: - - DONE. no faking left if you use --file --nofakedmodules. - (of course in this case you can't import most modules like - _sre at all.) Left:: - - unify the way stdobjspace is configured. - the basic objspace configuration interface - becomes a set of keyword arguments. The current - command line arguments will be mapped onto this - interface. - This also includes configuration of which modules - should be loaded. - - - extend the testing framework to allow to specify - a space with options for a test. Related to the latter. - - bug to be fixed: applevel test stdout is no longer captured. - running translate_pypy! + - finish and polish and test our own posix module + + - try to plug in niklaus' sre implementation + + - write an answer eMail/FAQ entry + + - finally start with garbage collection (CF) + + - investigate the possibility of translating the interactive part of PyPy + or alternatively (probably preferably) running it completely at applevel + + - working on LLVM (need to contact Eric on LLVM) + + - rewriting the marshal module on interplevel + + Pairing ------- -configuration of the stdobjspace (holger, richard) +basically everyone should keep an eye on targetpypymain, in the meantime +working on a subtask.. + + - samuele, carl friedrich: garbage collection + + - richard: plugin in sre + + - christian: rewriting marshal + + - armin, holger: applevel stdout -compiler + translate_pypy (christian, samuele, armin, carl friedrich) -(trying to sub-pair internally) + - armin: write nik mail, fix the entrypoint From arigo at codespeak.net Fri Jul 29 12:59:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 12:59:33 +0200 (CEST) Subject: [pypy-svn] r15332 - pypy/dist/pypy/translator/goal Message-ID: <20050729105933.D14E127B92@code1.codespeak.net> Author: arigo Date: Fri Jul 29 12:59:32 2005 New Revision: 15332 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: Cannot pass a list to the entry_point function. Using a hackish workaround... Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jul 29 12:59:32 2005 @@ -18,7 +18,8 @@ # __________ Entry point __________ -def entry_point(argv): +def entry_point(argvstring): + argv = argvstring.split('\x00') w_argv = space.newlist([space.wrap(s) for s in argv]) w_exitcode = space.call(w_entry_point, w_argv) # try to pull it all in @@ -48,11 +49,10 @@ space.exec_(open(filename).read(), w_dict, w_dict) w_entry_point = space.getitem(w_dict, space.wrap('entry_point')) - s_list_of_strings = SomeList(ListDef(None, SomeString())) - return entry_point, [s_list_of_strings] + return entry_point, [SomeString()] # _____ Run translated _____ def run(c_entry_point): argv = [os.path.join(this_dir, 'app_example.py')] - exitcode = c_entry_point(argv) + exitcode = c_entry_point('\x00'.join(argv)) assert exitcode == 0 From hpk at codespeak.net Fri Jul 29 13:12:22 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 29 Jul 2005 13:12:22 +0200 (CEST) Subject: [pypy-svn] r15333 - pypy/extradoc/sprintinfo Message-ID: <20050729111222.1AB3927B4B@code1.codespeak.net> Author: hpk Date: Fri Jul 29 13:12:21 2005 New Revision: 15333 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: finally added issue101 for the translation rev-breaking discovery tool. Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Fri Jul 29 13:12:21 2005 @@ -27,14 +27,10 @@ Misc -------- -* -> TRACKER write a tool that discovers which revision of the pypy tree - broke the high level annotator (in that it produced SomeObjects). - Consider distributing the actual annotation to multiple hosts. (holger) - -* -> TRACKER: (mostly done) add missing docstrings on app-level built-in types and - functions, etc. (Laura): there now is a program that generates the - docstrings into the appropriate places but it needs prettification. - (christian) +* -> TRACKER: (mostly done?) add missing docstrings on + app-level built-in types and functions, etc. (Laura): there + now is a program that generates the docstrings into the + appropriate places but it needs prettification. (christian) Current Main task: RTYPER issues ----------------------------------- From pedronis at codespeak.net Fri Jul 29 13:20:18 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 13:20:18 +0200 (CEST) Subject: [pypy-svn] r15334 - pypy/dist/pypy/objspace/std Message-ID: <20050729112018.6209127B8D@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 13:20:16 2005 New Revision: 15334 Modified: pypy/dist/pypy/objspace/std/multimethod.py Log: be careful with list default args Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Fri Jul 29 13:20:16 2005 @@ -22,8 +22,8 @@ self.arity = arity self.root_class = root_class self.dispatch_tree = {} - self.argnames_before = argnames_before - self.argnames_after = argnames_after + self.argnames_before = list(argnames_before) + self.argnames_after = list(argnames_after) def register(self, function, *types, **kwds): assert len(types) == self.arity From pedronis at codespeak.net Fri Jul 29 13:21:37 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 13:21:37 +0200 (CEST) Subject: [pypy-svn] r15335 - pypy/dist/pypy/objspace/std Message-ID: <20050729112137.60F7D27B94@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 13:21:35 2005 New Revision: 15335 Modified: pypy/dist/pypy/objspace/std/model.py Log: added support to specify general extra_args= for space multimethods Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Fri Jul 29 13:21:35 2005 @@ -153,13 +153,14 @@ break else: self.name = operatorsymbol - + if extras.get('general__args__', False): self.argnames_after = ['__args__'] if extras.get('w_varargs', False): self.argnames_after = ['w_args'] if extras.get('varargs_w', False): self.argnames_after = ['args_w'] + self.argnames_after += extras.get('extra_args', []) def install_not_sliced(self, typeorder, baked_perform_call=True): return self.install(prefix = '__mm_' + self.name, From pedronis at codespeak.net Fri Jul 29 13:22:42 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 13:22:42 +0200 (CEST) Subject: [pypy-svn] r15336 - pypy/dist/pypy/objspace/std Message-ID: <20050729112242.F1A0827B96@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 13:22:41 2005 New Revision: 15336 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: commented out template for to be introduced marshal_w space multi method Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Jul 29 13:22:41 2005 @@ -441,6 +441,7 @@ str_w = MultiMethod('str_w', 1, []) # returns an unwrapped string float_w = MultiMethod('float_w', 1, []) # returns an unwrapped float uint_w = MultiMethod('uint_w', 1, []) # returns an unwrapped unsigned int (r_uint) + #marshal_w = MultiMethod('marshal_w', 1, [], extra_args=['foo']) # add all regular multimethods here for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable: From hpk at codespeak.net Fri Jul 29 13:44:24 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 29 Jul 2005 13:44:24 +0200 (CEST) Subject: [pypy-svn] r15337 - pypy/dist/pypy/documentation/website Message-ID: <20050729114424.DBC6827B4D@code1.codespeak.net> Author: hpk Date: Fri Jul 29 13:44:24 2005 New Revision: 15337 Modified: pypy/dist/pypy/documentation/website/news.txt Log: newsitem about the ongoing sprint (including ref to pictures which i am currently uploading) Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Fri Jul 29 13:44:24 2005 @@ -9,6 +9,23 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: ../architecture.html#mission-statement +PyPy Hildesheim2 sprint ongoing ... +====================================================== + +Up until 31st August we are in a PyPy sprint at `Trillke-Gut`_. +Carl has written a `report about day 1`_ and Holger +about `day 2 and day 3`_ including some `pictures from the sprint`_. +There has been some great progress already in that we now succeed +to fully annotate the PyPy code base and have a mode where +we don't borrow object implementations from CPython anymore +(which of course means that we have some modules missing). +Stay tuned. + +.. _`report about day 1`: http://codespeak.net/pipermail/pypy-dev/2005q3/002217.html +.. _`day 2 and day 3`: http://codespeak.net/pipermail/pypy-dev/2005q3/002220.html +.. _`pictures from the sprint`: http://codespeak.net/~hpk/hildesheim2-sprint-www/ +.. _`Trillke-Gut`: http://www.trillke.net/images/HomePagePictureSmall.jpg + EuroPython 2005 sprints finished ====================================================== From arigo at codespeak.net Fri Jul 29 13:49:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 13:49:32 +0200 (CEST) Subject: [pypy-svn] r15339 - pypy/dist/pypy/rpython Message-ID: <20050729114932.6D43B27B4D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 13:49:30 2005 New Revision: 15339 Modified: pypy/dist/pypy/rpython/llinterp.py Log: Skip setfield and setarrayitem if the item being set is a Void. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jul 29 13:49:30 2005 @@ -184,13 +184,18 @@ def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer - setattr(obj, fieldname, fieldvalue) + FIELDTYPE = getattr(typeOf(obj).TO, fieldname) + if FIELDTYPE != Void: + setattr(obj, fieldname, fieldvalue) def op_getarrayitem(self, array, index): return array[index] def op_setarrayitem(self, array, index, item): - array[index] = item + # array should be a pointer + ITEMTYPE = typeOf(array).TO.OF + if ITEMTYPE != Void: + array[index] = item def op_direct_call(self, f, *args): has_callable = getattr(f._obj, '_callable', None) is not None From ericvrp at codespeak.net Fri Jul 29 14:30:50 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 14:30:50 +0200 (CEST) Subject: [pypy-svn] r15342 - pypy/dist/pypy/translator/llvm2/module Message-ID: <20050729123050.B062A27B52@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 14:30:50 2005 New Revision: 15342 Modified: pypy/dist/pypy/translator/llvm2/module/ll_math.py Log: - refactoring - added atan2+fmod implementation Modified: pypy/dist/pypy/translator/llvm2/module/ll_math.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/module/ll_math.py (original) +++ pypy/dist/pypy/translator/llvm2/module/ll_math.py Fri Jul 29 14:30:50 2005 @@ -16,22 +16,27 @@ declare double %sqrt(double) declare double %tan(double) declare double %tanh(double) +declare double %atan2(double,double) +declare double %fmod(double,double) """ extfunctions = {} -simple_math_functions = [ - 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', - 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' +#functions with a one-to-one C equivalent +simple_functions = [ + ('double %x', ['acos','asin','atan','ceil','cos','cosh','exp','fabs', + 'floor','log','log10','sin','sinh','sqrt','tan','tanh']), + ('double %x, double %y', ['atan2','fmod']), ] -func_template = """ -double %%ll_math_%(func)s(double %%x) { - %%t = call double %%%(func)s(double %%x) +simple_function_template = """ +double %%ll_math_%(function)s(%(params)s) { + %%t = call double %%%(function)s(%(params)s) ret double %%t } """ -for func in simple_math_functions: - extfunctions["%ll_math_" + func] = ((), func_template % locals()) +for params, functions in simple_functions: + for function in functions: + extfunctions["%ll_math_" + function] = ((), simple_function_template % locals()) From cfbolz at codespeak.net Fri Jul 29 14:53:24 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 14:53:24 +0200 (CEST) Subject: [pypy-svn] r15344 - pypy/dist/pypy/objspace/flow Message-ID: <20050729125324.1701227B52@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 14:53:23 2005 New Revision: 15344 Modified: pypy/dist/pypy/objspace/flow/model.py Log: link.copy needs to copy llexitcase as well, if it's there. This doesn't fix our current problem, though. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Fri Jul 29 14:53:23 2005 @@ -108,6 +108,8 @@ newlink.prevblock = self.prevblock newlink.last_exception = rename(self.last_exception) newlink.last_exc_value = rename(self.last_exc_value) + if hasattr(self, 'llexitcase'): + newlink.llexitcase = self.llexitcase return newlink def __repr__(self): From rxe at codespeak.net Fri Jul 29 15:19:57 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 29 Jul 2005 15:19:57 +0200 (CEST) Subject: [pypy-svn] r15348 - pypy/branch/pypy-sre Message-ID: <20050729131957.1A22827B53@code1.codespeak.net> Author: rxe Date: Fri Jul 29 15:19:56 2005 New Revision: 15348 Added: pypy/branch/pypy-sre/ - copied from r15347, pypy/dist/ Log: Creating branch to test nik's _sre modules under pypy. From rxe at codespeak.net Fri Jul 29 15:23:12 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 29 Jul 2005 15:23:12 +0200 (CEST) Subject: [pypy-svn] r15349 - in pypy/branch/pypy-sre: lib-python/modified-2.4.1 pypy/lib pypy/module/_sre_pypy Message-ID: <20050729132312.118DE27B53@code1.codespeak.net> Author: rxe Date: Fri Jul 29 15:23:07 2005 New Revision: 15349 Added: pypy/branch/pypy-sre/pypy/lib/_sre.py pypy/branch/pypy-sre/pypy/lib/_sre_support.py Removed: pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_compile.py pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_constants.py pypy/branch/pypy-sre/pypy/module/_sre_pypy/ Log: Integrate _sre for testing. Deleted: /pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_compile.py ============================================================================== --- /pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_compile.py Fri Jul 29 15:23:07 2005 +++ (empty file) @@ -1,521 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# convert template to internal format -# -# Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. -# -# See the sre.py file for information on usage and redistribution. -# - -"""Internal support module for sre""" - -import _sre, sys - -from sre_constants import * - -# XXX see PyPy hack in sre_constants to support both the 2.3 and 2.4 _sre.c implementation. -#assert _sre.MAGIC == MAGIC, "SRE module mismatch" - -if _sre.CODESIZE == 2: - MAXCODE = 65535 -else: - MAXCODE = 0xFFFFFFFFL - -def _identityfunction(x): - return x - -def _compile(code, pattern, flags): - # internal: compile a (sub)pattern - emit = code.append - _len = len - LITERAL_CODES = {LITERAL:1, NOT_LITERAL:1} - REPEATING_CODES = {REPEAT:1, MIN_REPEAT:1, MAX_REPEAT:1} - SUCCESS_CODES = {SUCCESS:1, FAILURE:1} - ASSERT_CODES = {ASSERT:1, ASSERT_NOT:1} - for op, av in pattern: - if op in LITERAL_CODES: - if flags & SRE_FLAG_IGNORECASE: - emit(OPCODES[OP_IGNORE[op]]) - emit(_sre.getlower(av, flags)) - else: - emit(OPCODES[op]) - emit(av) - elif op is IN: - if flags & SRE_FLAG_IGNORECASE: - emit(OPCODES[OP_IGNORE[op]]) - def fixup(literal, flags=flags): - return _sre.getlower(literal, flags) - else: - emit(OPCODES[op]) - fixup = _identityfunction - skip = _len(code); emit(0) - _compile_charset(av, flags, code, fixup) - code[skip] = _len(code) - skip - elif op is ANY: - if flags & SRE_FLAG_DOTALL: - emit(OPCODES[ANY_ALL]) - else: - emit(OPCODES[ANY]) - elif op in REPEATING_CODES: - if flags & SRE_FLAG_TEMPLATE: - raise error, "internal: unsupported template operator" - emit(OPCODES[REPEAT]) - skip = _len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - emit(OPCODES[SUCCESS]) - code[skip] = _len(code) - skip - elif _simple(av) and op is not REPEAT: - if op is MAX_REPEAT: - emit(OPCODES[REPEAT_ONE]) - else: - emit(OPCODES[MIN_REPEAT_ONE]) - skip = _len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - emit(OPCODES[SUCCESS]) - code[skip] = _len(code) - skip - else: - emit(OPCODES[REPEAT]) - skip = _len(code); emit(0) - emit(av[0]) - emit(av[1]) - _compile(code, av[2], flags) - code[skip] = _len(code) - skip - if op is MAX_REPEAT: - emit(OPCODES[MAX_UNTIL]) - else: - emit(OPCODES[MIN_UNTIL]) - elif op is SUBPATTERN: - if av[0]: - emit(OPCODES[MARK]) - emit((av[0]-1)*2) - # _compile_info(code, av[1], flags) - _compile(code, av[1], flags) - if av[0]: - emit(OPCODES[MARK]) - emit((av[0]-1)*2+1) - elif op in SUCCESS_CODES: - emit(OPCODES[op]) - elif op in ASSERT_CODES: - emit(OPCODES[op]) - skip = _len(code); emit(0) - if av[0] >= 0: - emit(0) # look ahead - else: - lo, hi = av[1].getwidth() - if lo != hi: - raise error, "look-behind requires fixed-width pattern" - emit(lo) # look behind - _compile(code, av[1], flags) - emit(OPCODES[SUCCESS]) - code[skip] = _len(code) - skip - elif op is CALL: - emit(OPCODES[op]) - skip = _len(code); emit(0) - _compile(code, av, flags) - emit(OPCODES[SUCCESS]) - code[skip] = _len(code) - skip - elif op is AT: - emit(OPCODES[op]) - if flags & SRE_FLAG_MULTILINE: - av = AT_MULTILINE.get(av, av) - if flags & SRE_FLAG_LOCALE: - av = AT_LOCALE.get(av, av) - elif flags & SRE_FLAG_UNICODE: - av = AT_UNICODE.get(av, av) - emit(ATCODES[av]) - elif op is BRANCH: - emit(OPCODES[op]) - tail = [] - tailappend = tail.append - for av in av[1]: - skip = _len(code); emit(0) - # _compile_info(code, av, flags) - _compile(code, av, flags) - emit(OPCODES[JUMP]) - tailappend(_len(code)); emit(0) - code[skip] = _len(code) - skip - emit(0) # end of branch - for tail in tail: - code[tail] = _len(code) - tail - elif op is CATEGORY: - emit(OPCODES[op]) - if flags & SRE_FLAG_LOCALE: - av = CH_LOCALE[av] - elif flags & SRE_FLAG_UNICODE: - av = CH_UNICODE[av] - emit(CHCODES[av]) - elif op is GROUPREF: - if flags & SRE_FLAG_IGNORECASE: - emit(OPCODES[OP_IGNORE[op]]) - else: - emit(OPCODES[op]) - emit(av-1) - elif op is GROUPREF_EXISTS: - emit(OPCODES[op]) - emit((av[0]-1)*2) - skipyes = _len(code); emit(0) - _compile(code, av[1], flags) - if av[2]: - emit(OPCODES[JUMP]) - skipno = _len(code); emit(0) - code[skipyes] = _len(code) - skipyes + 1 - _compile(code, av[2], flags) - code[skipno] = _len(code) - skipno - else: - code[skipyes] = _len(code) - skipyes + 1 - else: - raise ValueError, ("unsupported operand type", op) - -def _compile_charset(charset, flags, code, fixup=None): - # compile charset subprogram - emit = code.append - if fixup is None: - fixup = _identityfunction - for op, av in _optimize_charset(charset, fixup): - emit(OPCODES[op]) - if op is NEGATE: - pass - elif op is LITERAL: - emit(fixup(av)) - elif op is RANGE: - emit(fixup(av[0])) - emit(fixup(av[1])) - elif op is CHARSET: - code.extend(av) - elif op is BIGCHARSET: - code.extend(av) - elif op is CATEGORY: - if flags & SRE_FLAG_LOCALE: - emit(CHCODES[CH_LOCALE[av]]) - elif flags & SRE_FLAG_UNICODE: - emit(CHCODES[CH_UNICODE[av]]) - else: - emit(CHCODES[av]) - else: - raise error, "internal: unsupported set operator" - emit(OPCODES[FAILURE]) - -def _optimize_charset(charset, fixup): - # internal: optimize character set - out = [] - outappend = out.append - charmap = [0]*256 - try: - for op, av in charset: - if op is NEGATE: - outappend((op, av)) - elif op is LITERAL: - charmap[fixup(av)] = 1 - elif op is RANGE: - for i in range(fixup(av[0]), fixup(av[1])+1): - charmap[i] = 1 - elif op is CATEGORY: - # XXX: could append to charmap tail - return charset # cannot compress - except IndexError: - # character set contains unicode characters - return _optimize_unicode(charset, fixup) - # compress character map - i = p = n = 0 - runs = [] - runsappend = runs.append - for c in charmap: - if c: - if n == 0: - p = i - n = n + 1 - elif n: - runsappend((p, n)) - n = 0 - i = i + 1 - if n: - runsappend((p, n)) - if len(runs) <= 2: - # use literal/range - for p, n in runs: - if n == 1: - outappend((LITERAL, p)) - else: - outappend((RANGE, (p, p+n-1))) - if len(out) < len(charset): - return out - else: - # use bitmap - data = _mk_bitmap(charmap) - outappend((CHARSET, data)) - return out - return charset - -def _mk_bitmap(bits): - data = [] - dataappend = data.append - if _sre.CODESIZE == 2: - start = (1, 0) - else: - start = (1L, 0L) - m, v = start - for c in bits: - if c: - v = v + m - m = m + m - if m > MAXCODE: - dataappend(v) - m, v = start - return data - -# To represent a big charset, first a bitmap of all characters in the -# set is constructed. Then, this bitmap is sliced into chunks of 256 -# characters, duplicate chunks are eliminitated, and each chunk is -# given a number. In the compiled expression, the charset is -# represented by a 16-bit word sequence, consisting of one word for -# the number of different chunks, a sequence of 256 bytes (128 words) -# of chunk numbers indexed by their original chunk position, and a -# sequence of chunks (16 words each). - -# Compression is normally good: in a typical charset, large ranges of -# Unicode will be either completely excluded (e.g. if only cyrillic -# letters are to be matched), or completely included (e.g. if large -# subranges of Kanji match). These ranges will be represented by -# chunks of all one-bits or all zero-bits. - -# Matching can be also done efficiently: the more significant byte of -# the Unicode character is an index into the chunk number, and the -# less significant byte is a bit index in the chunk (just like the -# CHARSET matching). - -# In UCS-4 mode, the BIGCHARSET opcode still supports only subsets -# of the basic multilingual plane; an efficient representation -# for all of UTF-16 has not yet been developed. This means, -# in particular, that negated charsets cannot be represented as -# bigcharsets. - -def _optimize_unicode(charset, fixup): - try: - import array - except ImportError: - return charset - charmap = [0]*65536 - negate = 0 - try: - for op, av in charset: - if op is NEGATE: - negate = 1 - elif op is LITERAL: - charmap[fixup(av)] = 1 - elif op is RANGE: - for i in xrange(fixup(av[0]), fixup(av[1])+1): - charmap[i] = 1 - elif op is CATEGORY: - # XXX: could expand category - return charset # cannot compress - except IndexError: - # non-BMP characters - return charset - if negate: - if sys.maxunicode != 65535: - # XXX: negation does not work with big charsets - return charset - for i in xrange(65536): - charmap[i] = not charmap[i] - comps = {} - mapping = [0]*256 - block = 0 - data = [] - for i in xrange(256): - chunk = tuple(charmap[i*256:(i+1)*256]) - new = comps.setdefault(chunk, block) - mapping[i] = new - if new == block: - block = block + 1 - data = data + _mk_bitmap(chunk) - header = [block] - if _sre.CODESIZE == 2: - code = 'H' - else: - code = 'I' - # Convert block indices to byte array of 256 bytes - mapping = array.array('b', mapping).tostring() - # Convert byte array to word array - mapping = array.array(code, mapping) - assert mapping.itemsize == _sre.CODESIZE - header = header + mapping.tolist() - data[0:0] = header - return [(BIGCHARSET, data)] - -def _simple(av): - # check if av is a "simple" operator - lo, hi = av[2].getwidth() - if lo == 0 and hi == MAXREPEAT: - raise error, "nothing to repeat" - return lo == hi == 1 and av[2][0][0] != SUBPATTERN - -def _compile_info(code, pattern, flags): - # internal: compile an info block. in the current version, - # this contains min/max pattern width, and an optional literal - # prefix or a character map - lo, hi = pattern.getwidth() - if lo == 0: - return # not worth it - # look for a literal prefix - prefix = [] - prefixappend = prefix.append - prefix_skip = 0 - charset = [] # not used - charsetappend = charset.append - if not (flags & SRE_FLAG_IGNORECASE): - # look for literal prefix - for op, av in pattern.data: - if op is LITERAL: - if len(prefix) == prefix_skip: - prefix_skip = prefix_skip + 1 - prefixappend(av) - elif op is SUBPATTERN and len(av[1]) == 1: - op, av = av[1][0] - if op is LITERAL: - prefixappend(av) - else: - break - else: - break - # if no prefix, look for charset prefix - if not prefix and pattern.data: - op, av = pattern.data[0] - if op is SUBPATTERN and av[1]: - op, av = av[1][0] - if op is LITERAL: - charsetappend((op, av)) - elif op is BRANCH: - c = [] - cappend = c.append - for p in av[1]: - if not p: - break - op, av = p[0] - if op is LITERAL: - cappend((op, av)) - else: - break - else: - charset = c - elif op is BRANCH: - c = [] - cappend = c.append - for p in av[1]: - if not p: - break - op, av = p[0] - if op is LITERAL: - cappend((op, av)) - else: - break - else: - charset = c - elif op is IN: - charset = av -## if prefix: -## print "*** PREFIX", prefix, prefix_skip -## if charset: -## print "*** CHARSET", charset - # add an info block - emit = code.append - emit(OPCODES[INFO]) - skip = len(code); emit(0) - # literal flag - mask = 0 - if prefix: - mask = SRE_INFO_PREFIX - if len(prefix) == prefix_skip == len(pattern.data): - mask = mask + SRE_INFO_LITERAL - elif charset: - mask = mask + SRE_INFO_CHARSET - emit(mask) - # pattern length - if lo < MAXCODE: - emit(lo) - else: - emit(MAXCODE) - prefix = prefix[:MAXCODE] - if hi < MAXCODE: - emit(hi) - else: - emit(0) - # add literal prefix - if prefix: - emit(len(prefix)) # length - emit(prefix_skip) # skip - code.extend(prefix) - # generate overlap table - table = [-1] + ([0]*len(prefix)) - for i in xrange(len(prefix)): - table[i+1] = table[i]+1 - while table[i+1] > 0 and prefix[i] != prefix[table[i+1]-1]: - table[i+1] = table[table[i+1]-1]+1 - code.extend(table[1:]) # don't store first entry - elif charset: - _compile_charset(charset, flags, code) - code[skip] = len(code) - skip - -try: - unicode -except NameError: - STRING_TYPES = (type(""),) -else: - STRING_TYPES = (type(""), type(unicode(""))) - -def isstring(obj): - for tp in STRING_TYPES: - if isinstance(obj, tp): - return 1 - return 0 - -def _code(p, flags): - - flags = p.pattern.flags | flags - code = [] - - # compile info block - _compile_info(code, p, flags) - - # compile the pattern - _compile(code, p.data, flags) - - code.append(OPCODES[SUCCESS]) - - return code - -def compile(p, flags=0): - # internal: convert pattern list to internal format - - if isstring(p): - import sre_parse - pattern = p - p = sre_parse.parse(p, flags) - else: - pattern = None - - code = _code(p, flags) - - # print code - - # XXX: get rid of this limitation! - if p.pattern.groups > 100: - raise AssertionError( - "sorry, but this version only supports 100 named groups" - ) - - # map in either direction - groupindex = p.pattern.groupdict - indexgroup = [None] * p.pattern.groups - for k, i in groupindex.items(): - indexgroup[i] = k - - return _sre.compile( - pattern, flags, code, - p.pattern.groups-1, - groupindex, indexgroup - ) Deleted: /pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_constants.py ============================================================================== --- /pypy/branch/pypy-sre/lib-python/modified-2.4.1/sre_constants.py Fri Jul 29 15:23:07 2005 +++ (empty file) @@ -1,269 +0,0 @@ -# -# Secret Labs' Regular Expression Engine -# -# various symbols used by the regular expression engine. -# run this script to update the _sre include files! -# -# Copyright (c) 1998-2001 by Secret Labs AB. All rights reserved. -# -# See the sre.py file for information on usage and redistribution. -# - -"""Internal support module for sre""" - -# update when constants are added or removed - -MAGIC = 20031017 - -# max code word in this release - -MAXREPEAT = 65535 - -# SRE standard exception (access as sre.error) -# should this really be here? - -class error(Exception): - pass - -# operators - -FAILURE = "failure" -SUCCESS = "success" - -ANY = "any" -ANY_ALL = "any_all" -ASSERT = "assert" -ASSERT_NOT = "assert_not" -AT = "at" -BIGCHARSET = "bigcharset" -BRANCH = "branch" -CALL = "call" -CATEGORY = "category" -CHARSET = "charset" -GROUPREF = "groupref" -GROUPREF_IGNORE = "groupref_ignore" -GROUPREF_EXISTS = "groupref_exists" -IN = "in" -IN_IGNORE = "in_ignore" -INFO = "info" -JUMP = "jump" -LITERAL = "literal" -LITERAL_IGNORE = "literal_ignore" -MARK = "mark" -MAX_REPEAT = "max_repeat" -MAX_UNTIL = "max_until" -MIN_REPEAT = "min_repeat" -MIN_UNTIL = "min_until" -NEGATE = "negate" -NOT_LITERAL = "not_literal" -NOT_LITERAL_IGNORE = "not_literal_ignore" -RANGE = "range" -REPEAT = "repeat" -REPEAT_ONE = "repeat_one" -SUBPATTERN = "subpattern" -MIN_REPEAT_ONE = "min_repeat_one" - -# positions -AT_BEGINNING = "at_beginning" -AT_BEGINNING_LINE = "at_beginning_line" -AT_BEGINNING_STRING = "at_beginning_string" -AT_BOUNDARY = "at_boundary" -AT_NON_BOUNDARY = "at_non_boundary" -AT_END = "at_end" -AT_END_LINE = "at_end_line" -AT_END_STRING = "at_end_string" -AT_LOC_BOUNDARY = "at_loc_boundary" -AT_LOC_NON_BOUNDARY = "at_loc_non_boundary" -AT_UNI_BOUNDARY = "at_uni_boundary" -AT_UNI_NON_BOUNDARY = "at_uni_non_boundary" - -# categories -CATEGORY_DIGIT = "category_digit" -CATEGORY_NOT_DIGIT = "category_not_digit" -CATEGORY_SPACE = "category_space" -CATEGORY_NOT_SPACE = "category_not_space" -CATEGORY_WORD = "category_word" -CATEGORY_NOT_WORD = "category_not_word" -CATEGORY_LINEBREAK = "category_linebreak" -CATEGORY_NOT_LINEBREAK = "category_not_linebreak" -CATEGORY_LOC_WORD = "category_loc_word" -CATEGORY_LOC_NOT_WORD = "category_loc_not_word" -CATEGORY_UNI_DIGIT = "category_uni_digit" -CATEGORY_UNI_NOT_DIGIT = "category_uni_not_digit" -CATEGORY_UNI_SPACE = "category_uni_space" -CATEGORY_UNI_NOT_SPACE = "category_uni_not_space" -CATEGORY_UNI_WORD = "category_uni_word" -CATEGORY_UNI_NOT_WORD = "category_uni_not_word" -CATEGORY_UNI_LINEBREAK = "category_uni_linebreak" -CATEGORY_UNI_NOT_LINEBREAK = "category_uni_not_linebreak" - -OPCODES = [ - - # failure=0 success=1 (just because it looks better that way :-) - FAILURE, SUCCESS, - - ANY, ANY_ALL, - ASSERT, ASSERT_NOT, - AT, - BRANCH, - CALL, - CATEGORY, - CHARSET, BIGCHARSET, - GROUPREF, GROUPREF_EXISTS, GROUPREF_IGNORE, - IN, IN_IGNORE, - INFO, - JUMP, - LITERAL, LITERAL_IGNORE, - MARK, - MAX_UNTIL, - MIN_UNTIL, - NOT_LITERAL, NOT_LITERAL_IGNORE, - NEGATE, - RANGE, - REPEAT, - REPEAT_ONE, - SUBPATTERN, - MIN_REPEAT_ONE - -] - -# PyPy hack to make the sre_*.py files from 2.4.1 work on the _sre -# engine of 2.3. -import _sre -if _sre.MAGIC < 20031017: - OPCODES.remove(GROUPREF_EXISTS) -del _sre - - -ATCODES = [ - AT_BEGINNING, AT_BEGINNING_LINE, AT_BEGINNING_STRING, AT_BOUNDARY, - AT_NON_BOUNDARY, AT_END, AT_END_LINE, AT_END_STRING, - AT_LOC_BOUNDARY, AT_LOC_NON_BOUNDARY, AT_UNI_BOUNDARY, - AT_UNI_NON_BOUNDARY -] - -CHCODES = [ - CATEGORY_DIGIT, CATEGORY_NOT_DIGIT, CATEGORY_SPACE, - CATEGORY_NOT_SPACE, CATEGORY_WORD, CATEGORY_NOT_WORD, - CATEGORY_LINEBREAK, CATEGORY_NOT_LINEBREAK, CATEGORY_LOC_WORD, - CATEGORY_LOC_NOT_WORD, CATEGORY_UNI_DIGIT, CATEGORY_UNI_NOT_DIGIT, - CATEGORY_UNI_SPACE, CATEGORY_UNI_NOT_SPACE, CATEGORY_UNI_WORD, - CATEGORY_UNI_NOT_WORD, CATEGORY_UNI_LINEBREAK, - CATEGORY_UNI_NOT_LINEBREAK -] - -def makedict(list): - d = {} - i = 0 - for item in list: - d[item] = i - i = i + 1 - return d - -OPCODES = makedict(OPCODES) -ATCODES = makedict(ATCODES) -CHCODES = makedict(CHCODES) - -# replacement operations for "ignore case" mode -OP_IGNORE = { - GROUPREF: GROUPREF_IGNORE, - IN: IN_IGNORE, - LITERAL: LITERAL_IGNORE, - NOT_LITERAL: NOT_LITERAL_IGNORE -} - -AT_MULTILINE = { - AT_BEGINNING: AT_BEGINNING_LINE, - AT_END: AT_END_LINE -} - -AT_LOCALE = { - AT_BOUNDARY: AT_LOC_BOUNDARY, - AT_NON_BOUNDARY: AT_LOC_NON_BOUNDARY -} - -AT_UNICODE = { - AT_BOUNDARY: AT_UNI_BOUNDARY, - AT_NON_BOUNDARY: AT_UNI_NON_BOUNDARY -} - -CH_LOCALE = { - CATEGORY_DIGIT: CATEGORY_DIGIT, - CATEGORY_NOT_DIGIT: CATEGORY_NOT_DIGIT, - CATEGORY_SPACE: CATEGORY_SPACE, - CATEGORY_NOT_SPACE: CATEGORY_NOT_SPACE, - CATEGORY_WORD: CATEGORY_LOC_WORD, - CATEGORY_NOT_WORD: CATEGORY_LOC_NOT_WORD, - CATEGORY_LINEBREAK: CATEGORY_LINEBREAK, - CATEGORY_NOT_LINEBREAK: CATEGORY_NOT_LINEBREAK -} - -CH_UNICODE = { - CATEGORY_DIGIT: CATEGORY_UNI_DIGIT, - CATEGORY_NOT_DIGIT: CATEGORY_UNI_NOT_DIGIT, - CATEGORY_SPACE: CATEGORY_UNI_SPACE, - CATEGORY_NOT_SPACE: CATEGORY_UNI_NOT_SPACE, - CATEGORY_WORD: CATEGORY_UNI_WORD, - CATEGORY_NOT_WORD: CATEGORY_UNI_NOT_WORD, - CATEGORY_LINEBREAK: CATEGORY_UNI_LINEBREAK, - CATEGORY_NOT_LINEBREAK: CATEGORY_UNI_NOT_LINEBREAK -} - -# flags -SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) -SRE_FLAG_IGNORECASE = 2 # case insensitive -SRE_FLAG_LOCALE = 4 # honour system locale -SRE_FLAG_MULTILINE = 8 # treat target as multiline string -SRE_FLAG_DOTALL = 16 # treat target as a single string -SRE_FLAG_UNICODE = 32 # use unicode locale -SRE_FLAG_VERBOSE = 64 # ignore whitespace and comments -SRE_FLAG_DEBUG = 128 # debugging - -# flags for INFO primitive -SRE_INFO_PREFIX = 1 # has prefix -SRE_INFO_LITERAL = 2 # entire pattern is literal (given by prefix) -SRE_INFO_CHARSET = 4 # pattern starts with character from given set - -if __name__ == "__main__": - def dump(f, d, prefix): - items = d.items() - items.sort(key=lambda a: a[1]) - for k, v in items: - f.write("#define %s_%s %s\n" % (prefix, k.upper(), v)) - f = open("sre_constants.h", "w") - f.write("""\ -/* - * Secret Labs' Regular Expression Engine - * - * regular expression matching engine - * - * NOTE: This file is generated by sre_constants.py. If you need - * to change anything in here, edit sre_constants.py and run it. - * - * Copyright (c) 1997-2001 by Secret Labs AB. All rights reserved. - * - * See the _sre.c file for information on usage and redistribution. - */ - -""") - - f.write("#define SRE_MAGIC %d\n" % MAGIC) - - dump(f, OPCODES, "SRE_OP") - dump(f, ATCODES, "SRE") - dump(f, CHCODES, "SRE") - - f.write("#define SRE_FLAG_TEMPLATE %d\n" % SRE_FLAG_TEMPLATE) - f.write("#define SRE_FLAG_IGNORECASE %d\n" % SRE_FLAG_IGNORECASE) - f.write("#define SRE_FLAG_LOCALE %d\n" % SRE_FLAG_LOCALE) - f.write("#define SRE_FLAG_MULTILINE %d\n" % SRE_FLAG_MULTILINE) - f.write("#define SRE_FLAG_DOTALL %d\n" % SRE_FLAG_DOTALL) - f.write("#define SRE_FLAG_UNICODE %d\n" % SRE_FLAG_UNICODE) - f.write("#define SRE_FLAG_VERBOSE %d\n" % SRE_FLAG_VERBOSE) - - f.write("#define SRE_INFO_PREFIX %d\n" % SRE_INFO_PREFIX) - f.write("#define SRE_INFO_LITERAL %d\n" % SRE_INFO_LITERAL) - f.write("#define SRE_INFO_CHARSET %d\n" % SRE_INFO_CHARSET) - - f.close() - print "done" Added: pypy/branch/pypy-sre/pypy/lib/_sre.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-sre/pypy/lib/_sre.py Fri Jul 29 15:23:07 2005 @@ -0,0 +1,1192 @@ +""" +A pure Python reimplementation of the _sre module from CPython 2.4 +Copyright 2005 Nik Haldimann, licensed under the MIT license + +This code is based on material licensed under CNRI's Python 1.6 license and +copyrighted by: Copyright (c) 1997-2001 by Secret Labs AB +""" + +import array, operator, sys +import sre_constants +from sre_constants import ATCODES, OPCODES, CHCODES, MAXREPEAT + + +# Identifying as _sre from Python 2.3 or 2.4 +if sys.version_info[:2] == (2, 4): + MAGIC = 20031017 +else: + MAGIC = 20030419 + +# In _sre.c this is bytesize of the code word type of the C implementation. +# There it's 2 for normal Python builds and more for wide unicode builds (large +# enough to hold a 32-bit UCS-4 encoded character). Since here in pure Python +# we only see re bytecodes as Python longs, we shouldn't have to care about the +# codesize. But sre_compile will compile some stuff differently depending on the +# codesize (e.g., charsets). +if sys.maxunicode == 65535: + CODESIZE = 2 +else: + CODESIZE = 4 + +copyright = "_sre.py 2.4a Copyright 2005 by Nik Haldimann" + + +def getcodesize(): + return CODESIZE + +def compile(pattern, flags, code, groups=0, groupindex={}, indexgroup=[None]): + """Compiles (or rather just converts) a pattern descriptor to a SRE_Pattern + object. Actual compilation to opcodes happens in sre_compile.""" + return SRE_Pattern(pattern, flags, code, groups, groupindex, indexgroup) + +def getlower(char_ord, flags): + if (char_ord < 128) or (flags & sre_constants.SRE_FLAG_UNICODE) \ + or (flags & sre_constants.SRE_FLAG_LOCALE and char_ord < 256): + return ord(unichr(char_ord).lower()) + else: + return char_ord + + +class SRE_Pattern(object): + + def __init__(self, pattern, flags, code, groups=0, groupindex={}, indexgroup=[None]): + self.pattern = pattern + self.flags = flags + self.groups = groups + self.groupindex = groupindex # Maps group names to group indices + self._indexgroup = indexgroup # Maps indices to group names + self._code = code + + def match(self, string, pos=0, endpos=sys.maxint): + """If zero or more characters at the beginning of string match this + regular expression, return a corresponding MatchObject instance. Return + None if the string does not match the pattern.""" + state = _State(string, pos, endpos, self.flags) + if state.match(self._code): + return SRE_Match(self, state) + else: + return None + + def search(self, string, pos=0, endpos=sys.maxint): + """Scan through string looking for a location where this regular + expression produces a match, and return a corresponding MatchObject + instance. Return None if no position in the string matches the + pattern.""" + state = _State(string, pos, endpos, self.flags) + if state.search(self._code): + return SRE_Match(self, state) + else: + return None + + def findall(self, string, pos=0, endpos=sys.maxint): + """Return a list of all non-overlapping matches of pattern in string.""" + matchlist = [] + state = _State(string, pos, endpos, self.flags) + while state.start <= state.end: + state.reset() + state.string_position = state.start + if not state.search(self._code): + break + match = SRE_Match(self, state) + if self.groups == 0 or self.groups == 1: + item = match.group(self.groups) + else: + item = match.groups("") + matchlist.append(item) + if state.string_position == state.start: + state.start += 1 + else: + state.start = state.string_position + return matchlist + + def _subx(self, template, string, count=0, subn=False): + filter = template + if not callable(template) and "\\" in template: + # handle non-literal strings ; hand it over to the template compiler + import sre + filter = sre._subx(self, template) + state = _State(string, 0, sys.maxint, self.flags) + sublist = [] + + n = last_pos = 0 + while not count or n < count: + state.reset() + state.string_position = state.start + if not state.search(self._code): + break + if last_pos < state.start: + sublist.append(string[last_pos:state.start]) + if not (last_pos == state.start and + last_pos == state.string_position and n > 0): + # the above ignores empty matches on latest position + if callable(filter): + sublist.append(filter(SRE_Match(self, state))) + else: + sublist.append(filter) + last_pos = state.string_position + n += 1 + if state.string_position == state.start: + state.start += 1 + else: + state.start = state.string_position + + if last_pos < state.end: + sublist.append(string[last_pos:state.end]) + item = "".join(sublist) + if subn: + return item, n + else: + return item + + def sub(self, repl, string, count=0): + """Return the string obtained by replacing the leftmost non-overlapping + occurrences of pattern in string by the replacement repl.""" + return self._subx(repl, string, count, False) + + def subn(self, repl, string, count=0): + """Return the tuple (new_string, number_of_subs_made) found by replacing + the leftmost non-overlapping occurrences of pattern with the replacement + repl.""" + return self._subx(repl, string, count, True) + + def split(self, string, maxsplit=0): + """Split string by the occurrences of pattern.""" + splitlist = [] + state = _State(string, 0, sys.maxint, self.flags) + n = 0 + last = state.start + while not maxsplit or n < maxsplit: + state.reset() + state.string_position = state.start + if not state.search(self._code): + break + if state.start == state.string_position: # zero-width match + if last == state.end: # or end of string + break + state.start += 1 + continue + splitlist.append(string[last:state.start]) + # add groups (if any) + if self.groups: + match = SRE_Match(self, state) + splitlist.extend(list(match.groups(None))) + n += 1 + last = state.start = state.string_position + splitlist.append(string[last:state.end]) + return splitlist + + def finditer(self, string, pos=0, endpos=sys.maxint): + """Return a list of all non-overlapping matches of pattern in string.""" + scanner = self.scanner(string, pos, endpos) + return iter(scanner.search, None) + + def scanner(self, string, start=0, end=sys.maxint): + return SRE_Scanner(self, string, start, end) + + def __copy__(self): + raise TypeError, "cannot copy this pattern object" + + def __deepcopy__(self): + raise TypeError, "cannot copy this pattern object" + + +class SRE_Scanner(object): + """Undocumented scanner interface of sre.""" + + def __init__(self, pattern, string, start, end): + self.pattern = pattern + self._state = _State(string, start, end, self.pattern.flags) + + def _match_search(self, matcher): + state = self._state + state.reset() + state.string_position = state.start + match = None + if matcher(self.pattern._code): + match = SRE_Match(self.pattern, state) + if match is None or state.string_position == state.start: + state.start += 1 + else: + state.start = state.string_position + return match + + def match(self): + return self._match_search(self._state.match) + + def search(self): + return self._match_search(self._state.search) + + +class SRE_Match(object): + + def __init__(self, pattern, state): + self.re = pattern + self.string = state.string + self.pos = state.pos + self.endpos = state.end + self.lastindex = state.lastindex + if self.lastindex < 0: + self.lastindex = None + self.regs = self._create_regs(state) + if pattern._indexgroup and 0 <= self.lastindex < len(pattern._indexgroup): + # The above upper-bound check should not be necessary, as the re + # compiler is supposed to always provide an _indexgroup list long + # enough. But the re.Scanner class seems to screw up something + # there, test_scanner in test_re won't work without upper-bound + # checking. XXX investigate this and report bug to CPython. + self.lastgroup = pattern._indexgroup[self.lastindex] + else: + self.lastgroup = None + + def _create_regs(self, state): + """Creates a tuple of index pairs representing matched groups.""" + regs = [(state.start, state.string_position)] + for group in range(self.re.groups): + mark_index = 2 * group + if mark_index + 1 < len(state.marks) \ + and state.marks[mark_index] is not None \ + and state.marks[mark_index + 1] is not None: + regs.append((state.marks[mark_index], state.marks[mark_index + 1])) + else: + regs.append((-1, -1)) + return tuple(regs) + + def _get_index(self, group): + if isinstance(group, int): + if group >= 0 and group <= self.re.groups: + return group + else: + if self.re.groupindex.has_key(group): + return self.re.groupindex[group] + raise IndexError("no such group") + + def _get_slice(self, group, default): + group_indices = self.regs[group] + if group_indices[0] >= 0: + return self.string[group_indices[0]:group_indices[1]] + else: + return default + + def start(self, group=0): + """Returns the indices of the start of the substring matched by group; + group defaults to zero (meaning the whole matched substring). Returns -1 + if group exists but did not contribute to the match.""" + return self.regs[self._get_index(group)][0] + + def end(self, group=0): + """Returns the indices of the end of the substring matched by group; + group defaults to zero (meaning the whole matched substring). Returns -1 + if group exists but did not contribute to the match.""" + return self.regs[self._get_index(group)][1] + + def span(self, group=0): + """Returns the 2-tuple (m.start(group), m.end(group)).""" + return self.start(group), self.end(group) + + def expand(self, template): + """Return the string obtained by doing backslash substitution and + resolving group references on template.""" + import sre + return sre._expand(self.re, self, template) + + def groups(self, default=None): + """Returns a tuple containing all the subgroups of the match. The + default argument is used for groups that did not participate in the + match (defaults to None).""" + groups = [] + for indices in self.regs[1:]: + if indices[0] >= 0: + groups.append(self.string[indices[0]:indices[1]]) + else: + groups.append(default) + return tuple(groups) + + def groupdict(self, default=None): + """Return a dictionary containing all the named subgroups of the match. + The default argument is used for groups that did not participate in the + match (defaults to None).""" + groupdict = {} + for key, value in self.re.groupindex.items(): + groupdict[key] = self._get_slice(value, default) + return groupdict + + def group(self, *args): + """Returns one or more subgroups of the match. Each argument is either a + group index or a group name.""" + if len(args) == 0: + args = (0,) + grouplist = [] + for group in args: + grouplist.append(self._get_slice(self._get_index(group), None)) + if len(grouplist) == 1: + return grouplist[0] + else: + return tuple(grouplist) + + def __copy__(): + raise TypeError, "cannot copy this pattern object" + + def __deepcopy__(): + raise TypeError, "cannot copy this pattern object" + + +class _State(object): + + def __init__(self, string, start, end, flags): + self.string = string + if start < 0: + start = 0 + if end > len(string): + end = len(string) + self.start = start + self.string_position = self.start + self.end = end + self.pos = start + self.flags = flags + self.reset() + + def reset(self): + self.marks = [] + self.lastindex = -1 + self.marks_stack = [] + self.context_stack = [] + self.repeat = None + + def match(self, pattern_codes): + # XXX INFO optimization missing here + dispatcher = _OpcodeDispatcher() + self.context_stack.append(_MatchContext(self, pattern_codes)) + has_matched = None + while len(self.context_stack) > 0: + context = self.context_stack[-1] + has_matched = dispatcher.match(context) + if has_matched is not None: # don't pop if context isn't done + self.context_stack.pop() + return has_matched + + def search(self, pattern_codes): + if pattern_codes[0] == OPCODES["info"]: + pattern_codes = pattern_codes[pattern_codes[1] + 1:] + # XXX USE_FAST_SEARCH optimizations missing here + # XXX literal and charset optimizations missing here + string_position = self.start + while string_position <= self.end: + self.reset() + self.start = self.string_position = string_position + if self.match(pattern_codes): + return True + string_position += 1 + return False + + def set_mark(self, mark_nr, position): + if mark_nr & 1: + # This id marks the end of a group. + self.lastindex = mark_nr / 2 + 1 + if mark_nr >= len(self.marks): + self.marks.extend([None] * (mark_nr - len(self.marks) + 1)) + self.marks[mark_nr] = position + + def get_marks(self, group_index): + marks_index = 2 * group_index + if len(self.marks) > marks_index + 1: + return self.marks[marks_index], self.marks[marks_index + 1] + else: + return None, None + + def marks_push(self): + self.marks_stack.append((self.marks[:], self.lastindex)) + + def marks_pop(self): + self.marks, self.lastindex = self.marks_stack.pop() + + def marks_pop_keep(self): + self.marks, self.lastindex = self.marks_stack[-1] + + def marks_pop_discard(self): + self.marks_stack.pop() + + def lower(self, char_ord): + return getlower(char_ord, self.flags) + + +class _MatchContext(object): + + def __init__(self, state, pattern_codes): + self.state = state + self.pattern_codes = pattern_codes + self.string_position = state.string_position + self.code_position = 0 + self.has_matched = None + + def push_new_context(self, pattern_offset): + """Creates a new child context of this context and pushes it on the + stack. pattern_offset is the offset off the current code position to + start interpreting from.""" + child_context = _MatchContext(self.state, + self.pattern_codes[self.code_position + pattern_offset:]) + self.state.context_stack.append(child_context) + return child_context + + def peek_char(self, peek=0): + return self.state.string[self.string_position + peek] + + def skip_char(self, skip_count): + self.string_position += skip_count + + def remaining_chars(self): + return self.state.end - self.string_position + + def peek_code(self, peek=0): + return self.pattern_codes[self.code_position + peek] + + def skip_code(self, skip_count): + self.code_position += skip_count + + def remaining_codes(self): + return len(self.pattern_codes) - self.code_position + + def at_beginning(self): + return self.string_position == 0 + + def at_end(self): + return self.string_position == self.state.end + + def at_linebreak(self): + return not self.at_end() and _is_linebreak(self.peek_char()) + + def at_boundary(self, word_checker): + if self.at_beginning() and self.at_end(): + return False + that = not self.at_beginning() and word_checker(self.peek_char(-1)) + this = not self.at_end() and word_checker(self.peek_char()) + return this != that + + +class _RepeatContext(_MatchContext): + + def __init__(self, context): + _MatchContext.__init__(self, context.state, + context.pattern_codes[context.code_position:]) + self.count = -1 + self.previous = context.state.repeat + self.last_position = None + + +class _Dispatcher(object): + + DISPATCH_TABLE = None + + def dispatch(self, code, context): + method = self.DISPATCH_TABLE.get(code, self.__class__.unknown) + return method(self, context) + + def unknown(self, code, ctx): + raise NotImplementedError() + + def build_dispatch_table(cls, code_dict, method_prefix): + table = {} + for key, value in code_dict.items(): + if hasattr(cls, "%s%s" % (method_prefix, key)): + table[value] = getattr(cls, "%s%s" % (method_prefix, key)) + cls.DISPATCH_TABLE = table + + build_dispatch_table = classmethod(build_dispatch_table) + + +class _OpcodeDispatcher(_Dispatcher): + + def __init__(self): + self.executing_contexts = {} + self.at_dispatcher = _AtcodeDispatcher() + self.ch_dispatcher = _ChcodeDispatcher() + self.set_dispatcher = _CharsetDispatcher() + + def match(self, context): + """Returns True if the current context matches, False if it doesn't and + None if matching is not finished, ie must be resumed after child + contexts have been matched.""" + while context.remaining_codes() > 0 and context.has_matched is None: + opcode = context.peek_code() + if not self.dispatch(opcode, context): + return None + if context.has_matched is None: + context.has_matched = False + return context.has_matched + + def dispatch(self, opcode, context): + """Dispatches a context on a given opcode. Returns True if the context + is done matching, False if it must be resumed when next encountered.""" + if self.executing_contexts.has_key(id(context)): + generator = self.executing_contexts[id(context)] + del self.executing_contexts[id(context)] + has_finished = generator.next() + else: + method = self.DISPATCH_TABLE.get(opcode, _OpcodeDispatcher.unknown) + has_finished = method(self, context) + if hasattr(has_finished, "next"): # avoid using the types module + generator = has_finished + has_finished = generator.next() + if not has_finished: + self.executing_contexts[id(context)] = generator + return has_finished + + def op_success(self, ctx): + # end of pattern + #self._log(ctx, "SUCCESS") + ctx.state.string_position = ctx.string_position + ctx.has_matched = True + return True + + def op_failure(self, ctx): + # immediate failure + #self._log(ctx, "FAILURE") + ctx.has_matched = False + return True + + def general_op_literal(self, ctx, compare, decorate=lambda x: x): + if ctx.at_end() or not compare(decorate(ord(ctx.peek_char())), + decorate(ctx.peek_code(1))): + ctx.has_matched = False + ctx.skip_code(2) + ctx.skip_char(1) + + def op_literal(self, ctx): + # match literal string + # + #self._log(ctx, "LITERAL", ctx.peek_code(1)) + self.general_op_literal(ctx, operator.eq) + return True + + def op_not_literal(self, ctx): + # match anything that is not the given literal character + # + #self._log(ctx, "NOT_LITERAL", ctx.peek_code(1)) + self.general_op_literal(ctx, operator.ne) + return True + + def op_literal_ignore(self, ctx): + # match literal regardless of case + # + #self._log(ctx, "LITERAL_IGNORE", ctx.peek_code(1)) + self.general_op_literal(ctx, operator.eq, ctx.state.lower) + return True + + def op_not_literal_ignore(self, ctx): + # match literal regardless of case + # + #self._log(ctx, "LITERAL_IGNORE", ctx.peek_code(1)) + self.general_op_literal(ctx, operator.ne, ctx.state.lower) + return True + + def op_at(self, ctx): + # match at given position + # + #self._log(ctx, "AT", ctx.peek_code(1)) + if not self.at_dispatcher.dispatch(ctx.peek_code(1), ctx): + ctx.has_matched = False + return True + ctx.skip_code(2) + return True + + def op_category(self, ctx): + # match at given category + # + #self._log(ctx, "CATEGORY", ctx.peek_code(1)) + if ctx.at_end() or not self.ch_dispatcher.dispatch(ctx.peek_code(1), ctx): + ctx.has_matched = False + return True + ctx.skip_code(2) + ctx.skip_char(1) + return True + + def op_any(self, ctx): + # match anything (except a newline) + # + #self._log(ctx, "ANY") + if ctx.at_end() or ctx.at_linebreak(): + ctx.has_matched = False + return True + ctx.skip_code(1) + ctx.skip_char(1) + return True + + def op_any_all(self, ctx): + # match anything + # + #self._log(ctx, "ANY_ALL") + if ctx.at_end(): + ctx.has_matched = False + return True + ctx.skip_code(1) + ctx.skip_char(1) + return True + + def general_op_in(self, ctx, decorate=lambda x: x): + #self._log(ctx, "OP_IN") + if ctx.at_end(): + ctx.has_matched = False + return + skip = ctx.peek_code(1) + ctx.skip_code(2) # set op pointer to the set code + if not self.check_charset(ctx, decorate(ord(ctx.peek_char()))): + ctx.has_matched = False + return + ctx.skip_code(skip - 1) + ctx.skip_char(1) + + def op_in(self, ctx): + # match set member (or non_member) + # + #self._log(ctx, "OP_IN") + self.general_op_in(ctx) + return True + + def op_in_ignore(self, ctx): + # match set member (or non_member), disregarding case of current char + # + #self._log(ctx, "OP_IN_IGNORE") + self.general_op_in(ctx, ctx.state.lower) + return True + + def op_jump(self, ctx): + # jump forward + # + #self._log(ctx, "JUMP", ctx.peek_code(1)) + ctx.skip_code(ctx.peek_code(1) + 1) + return True + + # skip info + # + op_info = op_jump + + def op_mark(self, ctx): + # set mark + # + #self._log(ctx, "OP_MARK", ctx.peek_code(1)) + ctx.state.set_mark(ctx.peek_code(1), ctx.string_position) + ctx.skip_code(2) + return True + + def op_branch(self, ctx): + # alternation + # <0=skip> code ... + #self._log(ctx, "BRANCH") + ctx.state.marks_push() + ctx.skip_code(1) + current_branch_length = ctx.peek_code(0) + while current_branch_length: + # XXX OP_LITERAL and OP_IN optimizations here + ctx.state.string_position = ctx.string_position + child_context = ctx.push_new_context(1) + yield False + if child_context.has_matched: + ctx.has_matched = True + yield True + ctx.state.marks_pop_keep() + ctx.skip_code(current_branch_length) + current_branch_length = ctx.peek_code(0) + ctx.state.marks_pop_discard() + ctx.has_matched = False + yield True + + def op_repeat_one(self, ctx): + # match repeated sequence (maximizing). + # this operator only works if the repeated item is exactly one character + # wide, and we're not already collecting backtracking points. + # <1=min> <2=max> item tail + mincount = ctx.peek_code(2) + maxcount = ctx.peek_code(3) + #self._log(ctx, "REPEAT_ONE", mincount, maxcount) + + if ctx.remaining_chars() < mincount: + ctx.has_matched = False + yield True + ctx.state.string_position = ctx.string_position + count = self.count_repetitions(ctx, maxcount) + ctx.skip_char(count) + if count < mincount: + ctx.has_matched = False + yield True + if ctx.peek_code(ctx.peek_code(1) + 1) == OPCODES["success"]: + # tail is empty. we're finished + ctx.state.string_position = ctx.string_position + ctx.has_matched = True + yield True + + # XXX OP_LITERAL optimization missing here + + # backtracking + ctx.state.marks_push() + while count >= mincount: + ctx.state.string_position = ctx.string_position + child_context = ctx.push_new_context(ctx.peek_code(1) + 1) + yield False + if child_context.has_matched: + ctx.has_matched = True + yield True + ctx.skip_char(-1) + count -= 1 + ctx.state.marks_pop_keep() + + ctx.state.marks_pop_discard() + ctx.has_matched = False + yield True + + def op_min_repeat_one(self, ctx): + # match repeated sequence (minimizing) + # <1=min> <2=max> item tail + mincount = ctx.peek_code(2) + maxcount = ctx.peek_code(3) + #self._log(ctx, "MIN_REPEAT_ONE", mincount, maxcount) + + if ctx.remaining_chars() < mincount: + ctx.has_matched = False + yield True + ctx.state.string_position = ctx.string_position + if mincount == 0: + count = 0 + else: + count = self.count_repetitions(ctx, mincount) + if count < mincount: + ctx.has_matched = False + yield True + ctx.skip_char(count) + if ctx.peek_code(ctx.peek_code(1) + 1) == OPCODES["success"]: + # tail is empty. we're finished + ctx.state.string_position = ctx.string_position + ctx.has_matched = True + yield True + + ctx.state.marks_push() + while maxcount == MAXREPEAT or count <= maxcount: + ctx.state.string_position = ctx.string_position + child_context = ctx.push_new_context(ctx.peek_code(1) + 1) + yield False + if child_context.has_matched: + ctx.has_matched = True + yield True + ctx.state.string_position = ctx.string_position + if self.count_repetitions(ctx, 1) == 0: + break + ctx.skip_char(1) + count += 1 + ctx.state.marks_pop_keep() + + ctx.state.marks_pop_discard() + ctx.has_matched = False + yield True + + def op_repeat(self, ctx): + # create repeat context. all the hard work is done by the UNTIL + # operator (MAX_UNTIL, MIN_UNTIL) + # <1=min> <2=max> item tail + #self._log(ctx, "REPEAT", ctx.peek_code(2), ctx.peek_code(3)) + repeat = _RepeatContext(ctx) + ctx.state.repeat = repeat + ctx.state.string_position = ctx.string_position + child_context = ctx.push_new_context(ctx.peek_code(1) + 1) + yield False + ctx.state.repeat = repeat.previous + ctx.has_matched = child_context.has_matched + yield True + + def op_max_until(self, ctx): + # maximizing repeat + # <1=min> <2=max> item tail + repeat = ctx.state.repeat + if repeat is None: + raise RuntimeError("Internal re error: MAX_UNTIL without REPEAT.") + mincount = repeat.peek_code(2) + maxcount = repeat.peek_code(3) + ctx.state.string_position = ctx.string_position + count = repeat.count + 1 + #self._log(ctx, "MAX_UNTIL", count) + + if count < mincount: + # not enough matches + repeat.count = count + child_context = repeat.push_new_context(4) + yield False + ctx.has_matched = child_context.has_matched + if not ctx.has_matched: + repeat.count = count - 1 + ctx.state.string_position = ctx.string_position + yield True + + if (count < maxcount or maxcount == MAXREPEAT) \ + and ctx.state.string_position != repeat.last_position: + # we may have enough matches, if we can match another item, do so + repeat.count = count + ctx.state.marks_push() + save_last_position = repeat.last_position # zero-width match protection + repeat.last_position = ctx.state.string_position + child_context = repeat.push_new_context(4) + yield False + repeat.last_position = save_last_position + if child_context.has_matched: + ctx.state.marks_pop_discard() + ctx.has_matched = True + yield True + ctx.state.marks_pop() + repeat.count = count - 1 + ctx.state.string_position = ctx.string_position + + # cannot match more repeated items here. make sure the tail matches + ctx.state.repeat = repeat.previous + child_context = ctx.push_new_context(1) + yield False + ctx.has_matched = child_context.has_matched + if not ctx.has_matched: + ctx.state.repeat = repeat + ctx.state.string_position = ctx.string_position + yield True + + def op_min_until(self, ctx): + # minimizing repeat + # <1=min> <2=max> item tail + repeat = ctx.state.repeat + if repeat is None: + raise RuntimeError("Internal re error: MIN_UNTIL without REPEAT.") + mincount = repeat.peek_code(2) + maxcount = repeat.peek_code(3) + ctx.state.string_position = ctx.string_position + count = repeat.count + 1 + #self._log(ctx, "MIN_UNTIL", count) + + if count < mincount: + # not enough matches + repeat.count = count + child_context = repeat.push_new_context(4) + yield False + ctx.has_matched = child_context.has_matched + if not ctx.has_matched: + repeat.count = count - 1 + ctx.state.string_position = ctx.string_position + yield True + + # see if the tail matches + ctx.state.marks_push() + ctx.state.repeat = repeat.previous + child_context = ctx.push_new_context(1) + yield False + if child_context.has_matched: + ctx.has_matched = True + yield True + ctx.state.repeat = repeat + ctx.state.string_position = ctx.string_position + ctx.state.marks_pop() + + # match more until tail matches + if count >= maxcount and maxcount != MAXREPEAT: + ctx.has_matched = False + yield True + repeat.count = count + child_context = repeat.push_new_context(4) + yield False + ctx.has_matched = child_context.has_matched + if not ctx.has_matched: + repeat.count = count - 1 + ctx.state.string_position = ctx.string_position + yield True + + def general_op_groupref(self, ctx, decorate=lambda x: x): + group_start, group_end = ctx.state.get_marks(ctx.peek_code(1)) + if group_start is None or group_end is None or group_end < group_start: + ctx.has_matched = False + return True + while group_start < group_end: + if ctx.at_end() or decorate(ord(ctx.peek_char())) \ + != decorate(ord(ctx.state.string[group_start])): + ctx.has_matched = False + return True + group_start += 1 + ctx.skip_char(1) + ctx.skip_code(2) + return True + + def op_groupref(self, ctx): + # match backreference + # + #self._log(ctx, "GROUPREF", ctx.peek_code(1)) + return self.general_op_groupref(ctx) + + def op_groupref_ignore(self, ctx): + # match backreference case-insensitive + # + #self._log(ctx, "GROUPREF_IGNORE", ctx.peek_code(1)) + return self.general_op_groupref(ctx, ctx.state.lower) + + def op_groupref_exists(self, ctx): + # codeyes codeno ... + #self._log(ctx, "GROUPREF_EXISTS", ctx.peek_code(1)) + group_start, group_end = ctx.state.get_marks(ctx.peek_code(1)) + if group_start is None or group_end is None or group_end < group_start: + ctx.skip_code(ctx.peek_code(2) + 1) + else: + ctx.skip_code(3) + return True + + def op_assert(self, ctx): + # assert subpattern + # + #self._log(ctx, "ASSERT", ctx.peek_code(2)) + ctx.state.string_position = ctx.string_position - ctx.peek_code(2) + if ctx.state.string_position < 0: + ctx.has_matched = False + yield True + child_context = ctx.push_new_context(3) + yield False + if child_context.has_matched: + ctx.skip_code(ctx.peek_code(1) + 1) + else: + ctx.has_matched = False + yield True + + def op_assert_not(self, ctx): + # assert not subpattern + # + #self._log(ctx, "ASSERT_NOT", ctx.peek_code(2)) + ctx.state.string_position = ctx.string_position - ctx.peek_code(2) + if ctx.state.string_position >= 0: + child_context = ctx.push_new_context(3) + yield False + if child_context.has_matched: + ctx.has_matched = False + yield True + ctx.skip_code(ctx.peek_code(1) + 1) + yield True + + def unknown(self, ctx): + #self._log(ctx, "UNKNOWN", ctx.peek_code()) + raise RuntimeError("Internal re error. Unknown opcode: %s" % ctx.peek_code()) + + def check_charset(self, ctx, char): + """Checks whether a character matches set of arbitrary length. Assumes + the code pointer is at the first member of the set.""" + self.set_dispatcher.reset(char) + save_position = ctx.code_position + result = None + while result is None: + result = self.set_dispatcher.dispatch(ctx.peek_code(), ctx) + ctx.code_position = save_position + return result + + def count_repetitions(self, ctx, maxcount): + """Returns the number of repetitions of a single item, starting from the + current string position. The code pointer is expected to point to a + REPEAT_ONE operation (with the repeated 4 ahead).""" + count = 0 + real_maxcount = ctx.state.end - ctx.string_position + if maxcount < real_maxcount and maxcount != MAXREPEAT: + real_maxcount = maxcount + # XXX could special case every single character pattern here, as in C. + # This is a general solution, a bit hackisch, but works and should be + # efficient. + code_position = ctx.code_position + string_position = ctx.string_position + ctx.skip_code(4) + reset_position = ctx.code_position + while count < real_maxcount: + # this works because the single character pattern is followed by + # a success opcode + ctx.code_position = reset_position + self.dispatch(ctx.peek_code(), ctx) + if ctx.has_matched is False: # could be None as well + break + count += 1 + ctx.has_matched = None + ctx.code_position = code_position + ctx.string_position = string_position + return count + + def _log(self, context, opname, *args): + arg_string = ("%s " * len(args)) % args + _log("|%s|%s|%s %s" % (context.pattern_codes, + context.string_position, opname, arg_string)) + +_OpcodeDispatcher.build_dispatch_table(OPCODES, "op_") + + +class _CharsetDispatcher(_Dispatcher): + + def __init__(self): + self.ch_dispatcher = _ChcodeDispatcher() + + def reset(self, char): + self.char = char + self.ok = True + + def set_failure(self, ctx): + return not self.ok + def set_literal(self, ctx): + # + if ctx.peek_code(1) == self.char: + return self.ok + else: + ctx.skip_code(2) + def set_category(self, ctx): + # + if self.ch_dispatcher.dispatch(ctx.peek_code(1), ctx): + return self.ok + else: + ctx.skip_code(2) + def set_charset(self, ctx): + # (16 bits per code word) + char_code = self.char + ctx.skip_code(1) # point to beginning of bitmap + if CODESIZE == 2: + if char_code < 256 and ctx.peek_code(char_code >> 4) \ + & (1 << (char_code & 15)): + return self.ok + ctx.skip_code(16) # skip bitmap + else: + if char_code < 256 and ctx.peek_code(char_code >> 5) \ + & (1 << (char_code & 31)): + return self.ok + ctx.skip_code(8) # skip bitmap + def set_range(self, ctx): + # + if ctx.peek_code(1) <= self.char <= ctx.peek_code(2): + return self.ok + ctx.skip_code(3) + def set_negate(self, ctx): + self.ok = not self.ok + ctx.skip_code(1) + def set_bigcharset(self, ctx): + # <256 blockindices> + char_code = self.char + count = ctx.peek_code(1) + ctx.skip_code(2) + if char_code < 65536: + block_index = char_code >> 8 + # NB: there are CODESIZE block indices per bytecode + a = array.array("B") + a.fromstring(array.array(CODESIZE == 2 and "H" or "I", + [ctx.peek_code(block_index / CODESIZE)]).tostring()) + block = a[block_index % CODESIZE] + ctx.skip_code(256 / CODESIZE) # skip block indices + block_value = ctx.peek_code(block * (32 / CODESIZE) + + ((char_code & 255) >> (CODESIZE == 2 and 4 or 5))) + if block_value & (1 << (char_code & ((8 * CODESIZE) - 1))): + return self.ok + else: + ctx.skip_code(256 / CODESIZE) # skip block indices + ctx.skip_code(count * (32 / CODESIZE)) # skip blocks + def unknown(self, ctx): + return False + + +_CharsetDispatcher.build_dispatch_table(OPCODES, "set_") + + +class _AtcodeDispatcher(_Dispatcher): + + def at_beginning(self, ctx): + return ctx.at_beginning() + at_beginning_string = at_beginning + def at_beginning_line(self, ctx): + return ctx.at_beginning() or _is_linebreak(ctx.peek_char(-1)) + def at_end(self, ctx): + return (ctx.remaining_chars() == 1 and ctx.at_linebreak()) or ctx.at_end() + def at_end_line(self, ctx): + return ctx.at_linebreak() or ctx.at_end() + def at_end_string(self, ctx): + return ctx.at_end() + def at_boundary(self, ctx): + return ctx.at_boundary(_is_word) + def at_non_boundary(self, ctx): + return not ctx.at_boundary(_is_word) + def at_loc_boundary(self, ctx): + return ctx.at_boundary(_is_loc_word) + def at_loc_non_boundary(self, ctx): + return not ctx.at_boundary(_is_loc_word) + def at_uni_boundary(self, ctx): + return ctx.at_boundary(_is_uni_word) + def at_uni_non_boundary(self, ctx): + return not ctx.at_boundary(_is_uni_word) + def unknown(self, ctx): + return False + +_AtcodeDispatcher.build_dispatch_table(ATCODES, "") + + +class _ChcodeDispatcher(_Dispatcher): + + def category_digit(self, ctx): + return _is_digit(ctx.peek_char()) + def category_not_digit(self, ctx): + return not _is_digit(ctx.peek_char()) + def category_space(self, ctx): + return _is_space(ctx.peek_char()) + def category_not_space(self, ctx): + return not _is_space(ctx.peek_char()) + def category_word(self, ctx): + return _is_word(ctx.peek_char()) + def category_not_word(self, ctx): + return not _is_word(ctx.peek_char()) + def category_linebreak(self, ctx): + return _is_linebreak(ctx.peek_char()) + def category_not_linebreak(self, ctx): + return not _is_linebreak(ctx.peek_char()) + def category_loc_word(self, ctx): + return _is_loc_word(ctx.peek_char()) + def category_loc_not_word(self, ctx): + return not _is_loc_word(ctx.peek_char()) + def category_uni_digit(self, ctx): + return ctx.peek_char().isdigit() + def category_uni_not_digit(self, ctx): + return not ctx.peek_char().isdigit() + def category_uni_space(self, ctx): + return ctx.peek_char().isspace() + def category_uni_not_space(self, ctx): + return not ctx.peek_char().isspace() + def category_uni_word(self, ctx): + return _is_uni_word(ctx.peek_char()) + def category_uni_not_word(self, ctx): + return not _is_uni_word(ctx.peek_char()) + def category_uni_linebreak(self, ctx): + return ord(ctx.peek_char()) in _uni_linebreaks + def category_uni_not_linebreak(self, ctx): + return ord(ctx.peek_char()) not in _uni_linebreaks + def unknown(self, ctx): + return False + +_ChcodeDispatcher.build_dispatch_table(CHCODES, "") + + +_ascii_char_info = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 2, +2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, +0, 0, 16, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0 ] + +def _is_digit(char): + code = ord(char) + return code < 128 and _ascii_char_info[code] & 1 + +def _is_space(char): + code = ord(char) + return code < 128 and _ascii_char_info[code] & 2 + +def _is_word(char): + # NB: non-ASCII chars aren't words according to _sre.c + code = ord(char) + return code < 128 and _ascii_char_info[code] & 16 + +def _is_loc_word(char): + return (not (ord(char) & ~255) and char.isalnum()) or char == '_' + +def _is_uni_word(char): + return char.isalnum() or char == '_' + +def _is_linebreak(char): + return char == "\n" + +# Static list of all unicode codepoints reported by Py_UNICODE_ISLINEBREAK. +_uni_linebreaks = [10, 13, 28, 29, 30, 133, 8232, 8233] + +def _log(message): + if 0: + print message Added: pypy/branch/pypy-sre/pypy/lib/_sre_support.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-sre/pypy/lib/_sre_support.py Fri Jul 29 15:23:07 2005 @@ -0,0 +1,52 @@ +"""Utilities for use with the pure Python _sre module.""" +import imp, os.path, sys +try: + set +except NameError: + from sets import Set as set + +from sre_constants import OPCODES +OPCODES = dict([(value, key) for key, value in OPCODES.items()]) +WIDE_OPS = set(["info", "in", "in_ignore", "branch", "repeat_one", + "min_repeat_one", "repeat", "assert", "assert_not"]) +UNARY_OPS = set(["success", "any", "any_all", "failure", "max_until", + "min_until"]) + +def import_sre_py(): + """This forces the _sre.py to be imported as the _sre modules, also on + CPython systems with an existing _sre extension module. This must be called + before importing the re module. It's assumed that _sre.py is in the same + directory as _sre_support.py.""" + module_path = os.path.dirname(__file__) + _sre = imp.load_module("_sre", *imp.find_module("_sre", [module_path])) + sys.modules["_sre"] = _sre + +def opcodes(pattern, flags=0): + """Returns the list of plain numeric bytecodes for a pattern string.""" + import_sre_py() + import re + return re.compile(pattern, flags)._code + +def dis(pattern, flags=0): + """Prints a symbolic representation of the bytecodes for a pattern.""" + dis_opcodes(opcodes(pattern, flags)) + +def dis_opcodes(code): + symbolic_list = [] + i = 0 + while i < len(code): + symbol = OPCODES[code[i]] + if symbol in UNARY_OPS: + symbolic_list.append(symbol) + i += 1 + else: + if symbol in WIDE_OPS: + skip = code[i + 1] + elif symbol == "groupref_exists": + skip = code[i + 2] + else: + skip = 1 + symbolic_list.append("%s %s" % (symbol, code[i + 1:i + 1 + skip])) + i += skip + 1 + + print "\n".join(symbolic_list) From pedronis at codespeak.net Fri Jul 29 15:45:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 15:45:01 +0200 (CEST) Subject: [pypy-svn] r15350 - in pypy/dist/pypy: interpreter interpreter/test translator/goal Message-ID: <20050729134501.1316827B53@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 15:44:57 2005 New Revision: 15350 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/test/test_appinterp.py pypy/dist/pypy/interpreter/test/test_gateway.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: use_geninterp is now an option (can be set as a keyword arg) on the spaces Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Jul 29 15:44:57 2005 @@ -109,6 +109,7 @@ parser="recparser", compiler="pyparse", translating=False, + use_geninterp=True, **kw ): "NOT_RPYTHON: Basic initialization of objects." @@ -123,6 +124,7 @@ self.options.compiler = compiler self.options.usemodules = usemodules self.options.translating = translating + self.options.use_geninterp = use_geninterp self.setoptions(**kw) self.initialize() Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Fri Jul 29 15:44:57 2005 @@ -508,7 +508,6 @@ name at app-level.""" hidden_applevel = True - use_geninterp = True # change this to disable geninterp globally def __init__(self, source, filename = None, modname = '__builtin__'): self.filename = filename @@ -517,7 +516,9 @@ # look at the first three lines for a NOT_RPYTHON tag first = "\n".join(source.split("\n", 3)[:3]) if "NOT_RPYTHON" in first: - self.use_geninterp = False + self.can_use_geninterp = False + else: + self.can_use_geninterp = True def getwdict(self, space): return space.fromcache(ApplevelCache).getorbuild(self) @@ -562,7 +563,7 @@ def build(self, app): "NOT_RPYTHON. Called indirectly by Applevel.getwdict()." - if app.use_geninterp: + if self.space.options.use_geninterp and app.can_use_geninterp: return PyPyCacheDir.build_applevelinterp_dict(app, self.space) else: return build_applevel_dict(app, self.space) @@ -731,13 +732,11 @@ def getwdict(self, space): # no cache return build_applevel_dict(self, space) -if ApplevelClass.use_geninterp: - class applevelinterp_temp(ApplevelClass): - hidden_applevel = False - def getwdict(self, space): # no cache - return PyPyCacheDir.build_applevelinterp_dict(self, space) -else: - applevelinterp_temp = applevel_temp + +class applevelinterp_temp(ApplevelClass): + hidden_applevel = False + def getwdict(self, space): # no cache + return PyPyCacheDir.build_applevelinterp_dict(self, space) # app2interp_temp is used for testing mainly def app2interp_temp(func, applevel_temp=applevel_temp): Modified: pypy/dist/pypy/interpreter/test/test_appinterp.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_appinterp.py (original) +++ pypy/dist/pypy/interpreter/test/test_appinterp.py Fri Jul 29 15:44:57 2005 @@ -1,6 +1,6 @@ import py -from pypy.interpreter.gateway import appdef, ApplevelClass +from pypy.interpreter.gateway import appdef, ApplevelClass, applevel_temp, applevelinterp_temp def test_execwith_novars(space): val = space.appexec([], """ @@ -70,29 +70,27 @@ w_result = app(space) assert space.eq_w(w_result, space.wrap(42)) -def test_applevel_functions(space, use_geninterp=False): - app = ApplevelClass(''' +def test_applevel_functions(space, applevel_temp = applevel_temp): + app = applevel_temp(''' def f(x, y): return x-y def g(x, y): return f(y, x) ''') - app.use_geninterp &= use_geninterp g = app.interphook('g') w_res = g(space, space.wrap(10), space.wrap(1)) assert space.eq_w(w_res, space.wrap(-9)) def test_applevelinterp_functions(space): - test_applevel_functions(space, use_geninterp=True) + test_applevel_functions(space, applevel_temp = applevelinterp_temp) -def test_applevel_class(space, use_geninterp=False): - app = ApplevelClass(''' +def test_applevel_class(space, applevel_temp = applevel_temp): + app = applevel_temp(''' class C: clsattr = 42 def __init__(self, x=13): self.attr = x ''') - app.use_geninterp &= use_geninterp C = app.interphook('C') c = C(space, space.wrap(17)) w_attr = space.getattr(c, space.wrap('clsattr')) @@ -101,7 +99,7 @@ assert space.eq_w(w_clsattr, space.wrap(17)) def test_applevelinterp_class(space): - test_applevel_class(space, use_geninterp=True) + test_applevel_class(space, applevel_temp = applevelinterp_temp) def app_test_something_at_app_level(): x = 2 Modified: pypy/dist/pypy/interpreter/test/test_gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_gateway.py (original) +++ pypy/dist/pypy/interpreter/test/test_gateway.py Fri Jul 29 15:44:57 2005 @@ -76,6 +76,13 @@ return a+b g3 = gateway.app2interp_temp(app_g3) assert self.space.eq_w(g3(self.space, w('foo'), w('bar')), w('foobar')) + + def test_app2interp1(self): + w = self.space.wrap + def noapp_g3(a, b): + return a+b + g3 = gateway.app2interp_temp(noapp_g3, gateway.applevel_temp) + assert self.space.eq_w(g3(self.space, w('foo'), w('bar')), w('foobar')) def test_app2interp2(self): """same but using transformed code""" Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jul 29 15:44:57 2005 @@ -37,11 +37,10 @@ # disable geninterp for now -- we have faaar toooo much interp-level code # for the poor translator already # XXX why can't I enable this? crashes the annotator! - gateway.ApplevelClass.use_geninterp = False - space = StdObjSpace(nofaking=True, compiler="pyparseapp", - translating=True) + translating=True, + use_geninterp=False) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From cfbolz at codespeak.net Fri Jul 29 15:50:02 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 15:50:02 +0200 (CEST) Subject: [pypy-svn] r15351 - pypy/dist/pypy/rpython Message-ID: <20050729135002.C451027B50@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 15:50:02 2005 New Revision: 15351 Modified: pypy/dist/pypy/rpython/rtyper.py Log: we need to use another variable here, because otherwise you still have the new block in the next loop. Then llexitcase does not get attached to the next link, which is bad. Still the same error :-( Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jul 29 15:50:02 2005 @@ -321,11 +321,11 @@ # cannot insert conversion operations around a single # link, unless it is the only exit of this block. # create a new block along the link... - block = insert_empty_block(self.annotator.translator, - link, + newblock = insert_empty_block(self.annotator.translator, + link, # ...and store the conversions there. newops=newops) - link = block.exits[0] + link = newblock.exits[0] for i, new_a1 in newlinkargs.items(): link.args[i] = new_a1 From arigo at codespeak.net Fri Jul 29 16:12:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 16:12:53 +0200 (CEST) Subject: [pypy-svn] r15352 - pypy/dist/pypy/rpython Message-ID: <20050729141253.18DE527B53@code1.codespeak.net> Author: arigo Date: Fri Jul 29 16:12:51 2005 New Revision: 15352 Modified: pypy/dist/pypy/rpython/exceptiondata.py Log: Only put standard exceptions in the pyexcclass2exc() table. Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Fri Jul 29 16:12:51 2005 @@ -72,7 +72,7 @@ if (clsdef and clsdef.cls is not Exception and issubclass(clsdef.cls, Exception)): cls = clsdef.cls - if not clsdef.attrs: + if cls.__module__ == 'exceptions' and not clsdef.attrs: r_inst = rclass.getinstancerepr(rtyper, clsdef) r_inst.setup() example = malloc(r_inst.lowleveltype.TO, immortal=True) From hpk at codespeak.net Fri Jul 29 16:37:10 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 29 Jul 2005 16:37:10 +0200 (CEST) Subject: [pypy-svn] r15353 - in pypy/dist/pypy: interpreter translator/goal Message-ID: <20050729143710.39F3627B64@code1.codespeak.net> Author: hpk Date: Fri Jul 29 16:37:09 2005 New Revision: 15353 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: adapt option name to other option's style Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Jul 29 16:37:09 2005 @@ -109,7 +109,7 @@ parser="recparser", compiler="pyparse", translating=False, - use_geninterp=True, + geninterp=True, **kw ): "NOT_RPYTHON: Basic initialization of objects." @@ -124,7 +124,7 @@ self.options.compiler = compiler self.options.usemodules = usemodules self.options.translating = translating - self.options.use_geninterp = use_geninterp + self.options.geninterp = geninterp self.setoptions(**kw) self.initialize() Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Fri Jul 29 16:37:09 2005 @@ -563,7 +563,7 @@ def build(self, app): "NOT_RPYTHON. Called indirectly by Applevel.getwdict()." - if self.space.options.use_geninterp and app.can_use_geninterp: + if self.space.options.geninterp and app.can_use_geninterp: return PyPyCacheDir.build_applevelinterp_dict(app, self.space) else: return build_applevel_dict(app, self.space) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jul 29 16:37:09 2005 @@ -40,7 +40,7 @@ space = StdObjSpace(nofaking=True, compiler="pyparseapp", translating=True, - use_geninterp=False) + geninterp=False) # manually imports app_main.py filename = os.path.join(this_dir, 'app_main.py') From ericvrp at codespeak.net Fri Jul 29 16:56:15 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 16:56:15 +0200 (CEST) Subject: [pypy-svn] r15354 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050729145615.5F08327B53@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 16:56:14 2005 New Revision: 15354 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/structnode.py Log: refactor to get more readable llvm code Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Fri Jul 29 16:56:14 2005 @@ -3,13 +3,12 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2 import varsize -import itertools +import itertools log = log.structnode -nextnum = itertools.count().next +nextnum = itertools.count().next class ArrayTypeNode(LLVMNode): - _issetup = False def __init__(self, db, array): assert isinstance(array, lltype.Array) @@ -23,7 +22,7 @@ # for the array type (see writeimpl) c = nextnum() self.ref = "%%arraytype.%s.%s" % (c, self.arraytype) - self.constructor_ref = "%%new.array.%s" % c + self.constructor_ref = "%%new.array.%s" % c self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -32,7 +31,6 @@ def setup(self): self.db.prepare_repr_arg_type(self.arraytype) - self._issetup = True # ______________________________________________________________________ # entry points from genllvm @@ -57,13 +55,12 @@ a struct, pointer to struct/array """ - _issetup = True def __init__(self, db, value): assert isinstance(lltype.typeOf(value), lltype.Array) self.db = db self.value = value self.arraytype = lltype.typeOf(value).OF - self.ref = "%%arrayinstance.%s" % (nextnum(),) + self.ref = self.make_ref('%arrayinstance', '') def __str__(self): return "" % (self.ref,) @@ -78,7 +75,6 @@ self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), self.ref, typeval) - self._issetup = True def get_typerepr(self): items = self.value.items Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfuncnode.py (original) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Fri Jul 29 16:56:14 2005 @@ -4,7 +4,6 @@ log = log.extfuncnode class ExternalFuncNode(LLVMNode): - used_external_functions = {} def __init__(self, db, value): @@ -12,9 +11,6 @@ self.value = value self.ref = "%" + value._callable.__name__ - def setup(self): - self._issetup = True - def getdecl(self): T = self.value._TYPE args = [self.db.repr_arg_type(a) for a in T.ARGS] Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Fri Jul 29 16:56:14 2005 @@ -7,7 +7,6 @@ from pypy.translator.llvm2.node import LLVMNode, ConstantLLVMNode from pypy.translator.llvm2.opwriter import OpWriter from pypy.translator.llvm2.log import log -nextnum = py.std.itertools.count().next log = log.funcnode class FuncTypeNode(LLVMNode): @@ -17,7 +16,7 @@ self.type_ = type_ # XXX Make simplier for now, it is far too hard to read otherwise #self.ref = 'ft.%s.%s' % (type_, nextnum()) - self.ref = '%%functiontype.%s' % (nextnum(),) + self.ref = self.make_ref('%functiontype', '') def __str__(self): return "" % self.ref @@ -32,8 +31,6 @@ codewriter.funcdef(self.ref, returntype, inputargtypes) class FuncNode(ConstantLLVMNode): - _issetup = False - def __init__(self, db, value): self.db = db self.value = value @@ -57,7 +54,6 @@ self.db.prepare_arg(op.result) assert self.graph, "cannot traverse" traverse(visit, self.graph) - self._issetup = True # ______________________________________________________________________ # main entry points from genllvm @@ -65,7 +61,6 @@ codewriter.declare(self.getdecl()) def writeimpl(self, codewriter): - assert self._issetup graph = self.graph log.writeimpl(graph.name) codewriter.openfunc(self.getdecl()) @@ -89,7 +84,6 @@ # writing helpers for entry points def getdecl(self): - assert self._issetup startblock = self.graph.startblock returnblock = self.graph.returnblock inputargs = self.db.repr_arg_multi(startblock.inputargs) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Fri Jul 29 16:56:14 2005 @@ -16,6 +16,7 @@ #from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.module.extfunction import extdeclarations, \ extfunctions, gc_boehm, gc_disabled, dependencies +from pypy.translator.llvm2.node import LLVMNode from pypy.translator.translator import Translator @@ -24,6 +25,7 @@ class GenLLVM(object): def __init__(self, translator, embedexterns=True): + LLVMNode.nodename_count = {} #reset counters self.db = Database(translator) self.translator = translator self.embedexterns = embedexterns Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Fri Jul 29 16:56:14 2005 @@ -1,4 +1,18 @@ class LLVMNode(object): + nodename_count = {} + + def make_name(self, name): + if name in self.nodename_count: + postfix = '.%d' % self.nodename_count[name] + self.nodename_count[name] += 1 + else: + postfix = '' + self.nodename_count[name] = 1 + return name + postfix + + def make_ref(self, prefix, name): + return self.make_name(prefix + name) + def ref(): def _get_ref(self): return self._ref @@ -25,7 +39,6 @@ return property(_get_ref, _set_ref) constructor_ref = constructor_ref() - def setup(self): pass Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Fri Jul 29 16:56:14 2005 @@ -223,6 +223,29 @@ #self.codewriter.cast(tmpvar2, tmptype1, tmpvar1, tmptype2) #self.codewriter.switch(tmptype2, tmpvar2, exc_error_label, value_label) + #XXX get helper function name + exceptiondata = self.db._translator.rtyper.getexceptiondata() + + #functions + ll_exception_match = exceptiondata.ll_exception_match.__name__ + #yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) + #yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) + #yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) + #yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) + + #datatypes + lltype_of_exception_type = 'structtype.' + exceptiondata.lltype_of_exception_type.TO.__name__ + lltype_of_exception_value = 'structtype.' + exceptiondata.lltype_of_exception_value.TO.__name__ + #yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) + #yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) + + self.codewriter.newline() + self.codewriter.comment('HERE') + self.codewriter.comment(ll_exception_match) #ll_issubclass__object_vtablePtr_object_vtablePtr + self.codewriter.comment(lltype_of_exception_type) # + self.codewriter.comment(lltype_of_exception_value) # + self.codewriter.newline() + self.codewriter.switch(tmptype1, tmpvar1, exc_error_label, value_label) self.codewriter.label(exc_error_label) self.codewriter.comment('dead code ahead') Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Fri Jul 29 16:56:14 2005 @@ -4,20 +4,17 @@ from pypy.translator.llvm2 import varsize from pypy.rpython import lltype -import itertools -nextnum = itertools.count().next - log = log.structnode class StructTypeNode(LLVMNode): - _issetup = False - def __init__(self, db, struct): assert isinstance(struct, lltype.Struct) self.db = db self.struct = struct - self.name = "%s.%s" % (self.struct._name , nextnum()) - self.ref = "%%structtype.%s" % (self.name) + prefix = '%structtype.' + name = self.struct._name + self.ref = self.make_ref(prefix, name) + self.name = self.ref[len(prefix):] def __str__(self): return "" %(self.ref,) @@ -26,13 +23,11 @@ # Recurse for field in self.struct._flds.values(): self.db.prepare_repr_arg_type(field) - self._issetup = True # ______________________________________________________________________ # main entry points from genllvm def writedatatypedecl(self, codewriter): - assert self._issetup fields = [getattr(self.struct, name) for name in self.struct._names_without_voids()] codewriter.structdef(self.ref, @@ -42,7 +37,7 @@ def __init__(self, db, struct): super(StructVarsizeTypeNode, self).__init__(db, struct) - self.constructor_ref = "%%newvarsizestruct.%s" % (self.name) + self.constructor_ref = "%%new.varsizestruct.%s" % (self.name) self.constructor_decl = "%s * %s(int %%len)" % \ (self.ref, self.constructor_ref) @@ -83,13 +78,11 @@ a struct, pointer to struct/array """ - _issetup = False - def __init__(self, db, value): self.db = db self.value = value self.structtype = self.value._TYPE - self.ref = "%%structinstance.%s" % (nextnum(),) + self.ref = self.make_ref('%structinstance', '') def __str__(self): return "" % (self.ref,) @@ -111,8 +104,6 @@ value = getattr(self.value, name) self.db.prepare_constant(T, value) - self._issetup = True - def get_typerepr(self): return self.db.repr_arg_type(self.structtype) From arigo at codespeak.net Fri Jul 29 17:04:00 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 17:04:00 +0200 (CEST) Subject: [pypy-svn] r15355 - pypy/dist/pypy/translator/c Message-ID: <20050729150400.30A9627B53@code1.codespeak.net> Author: arigo Date: Fri Jul 29 17:03:58 2005 New Revision: 15355 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: Oups. Enumerated an exitcase as a dependency even if it wasn't actually used (because overridden by an llexitcase). Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Fri Jul 29 17:03:58 2005 @@ -36,9 +36,10 @@ for link in block.exits: mix.extend(link.getextravars()) mix.extend(link.args) - mix.append(Constant(link.exitcase)) if hasattr(link, 'llexitcase'): self.more_ll_values.append(link.llexitcase) + else: + mix.append(Constant(link.exitcase)) traverse(visit, graph) resultvar = graph.getreturnvar() From cfbolz at codespeak.net Fri Jul 29 17:10:52 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 17:10:52 +0200 (CEST) Subject: [pypy-svn] r15356 - in pypy/dist/pypy/rpython: . test Message-ID: <20050729151052.9A97127B53@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 17:10:50 2005 New Revision: 15356 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: added missing invert operations plus test Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jul 29 17:10:50 2005 @@ -321,6 +321,16 @@ assert type(c) is float return math.fmod(b,c) + def op_int_invert(self, a): + assert type(a) is int + return ~a + + def op_uint_invert(self, a): + assert type(a) is r_uint + return ~a + + + # operations on pyobjects! for opname in opimpls.keys(): exec py.code.Source(""" Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jul 29 17:10:50 2005 @@ -8,6 +8,7 @@ from pypy.rpython.rint import signed_repr from pypy.rpython import rstr from pypy.annotation.model import lltype_to_annotation +from pypy.rpython.rarithmetic import r_uint # switch on logging of interp to show more info on failing tests @@ -86,6 +87,13 @@ res = interpret(number_ops, [3]) assert res == 4 +def test_invert(): + def f(x): + return ~x + res = interpret(f, [3]) + assert res == ~3 + assert interpret(f, [r_uint(3)]) == ~r_uint(3) + def test_float_ops(): res = interpret(number_ops, [3.5]) assert res == 4.5 From arigo at codespeak.net Fri Jul 29 17:18:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 17:18:21 +0200 (CEST) Subject: [pypy-svn] r15357 - pypy/dist/pypy/interpreter Message-ID: <20050729151821.15C7627B53@code1.codespeak.net> Author: arigo Date: Fri Jul 29 17:18:19 2005 New Revision: 15357 Modified: pypy/dist/pypy/interpreter/miscutils.py Log: Explicitly check for this IndexError, because some callers expect it. Modified: pypy/dist/pypy/interpreter/miscutils.py ============================================================================== --- pypy/dist/pypy/interpreter/miscutils.py (original) +++ pypy/dist/pypy/interpreter/miscutils.py Fri Jul 29 17:18:19 2005 @@ -34,6 +34,8 @@ and so on. It must not be negative.""" if position < 0: raise ValueError, 'negative stack position' + if position >= len(self.items): + raise IndexError, 'not enough entries in stack' return self.items[~position] def depth(self): From cfbolz at codespeak.net Fri Jul 29 17:37:05 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 17:37:05 +0200 (CEST) Subject: [pypy-svn] r15358 - in pypy/dist/pypy: module/posix translator/c translator/c/src translator/c/test Message-ID: <20050729153705.E424527B53@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 17:37:02 2005 New Revision: 15358 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added some more constants to our posix module added external function implementation for os.lseek tests as well Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Fri Jul 29 17:37:02 2005 @@ -35,7 +35,7 @@ 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_LARGEFILE', 'O_NDELAY', 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_RDONLY', 'O_RDWR', 'O_RSYNC', 'O_SYNC', 'O_TRUNC', 'O_WRONLY', 'R_OK', 'TMP_MAX', - 'W_OK', 'X_OK']: + 'WCONTINUED', 'WNOHANG', 'WUNTRACED', 'W_OK', 'X_OK']: try: Module.interpleveldefs[constant] = ("space.wrap(%s)" % (getattr(os, constant), )) Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 17:37:02 2005 @@ -16,6 +16,7 @@ ll_os .ll_os_getcwd: 'LL_os_getcwd', ll_os .ll_os_stat: 'LL_os_stat', ll_os .ll_os_fstat: 'LL_os_fstat', + ll_os .ll_os_lseek: 'LL_os_lseek', ll_time.ll_time_clock: 'LL_time_clock', ll_math.ll_math_frexp: 'LL_math_frexp', ll_math.ll_math_atan2: 'LL_math_atan2', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Fri Jul 29 17:37:02 2005 @@ -132,3 +132,26 @@ return _stat_construct_result_helper(st); } +long LL_os_lseek(long fd, long pos, long how) { +#if defined(MS_WIN64) || defined(MS_WINDOWS) + PY_LONG_LONG res; +#else + off_t res; +#endif +#ifdef SEEK_SET + /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ + switch (how) { + case 0: how = SEEK_SET; break; + case 1: how = SEEK_CUR; break; + case 2: how = SEEK_END; break; + } +#endif /* SEEK_END */ +#if defined(MS_WIN64) || defined(MS_WINDOWS) + res = _lseeki64(fd, pos, how); +#else + res = lseek(fd, pos, how); +#endif + if (res < 0) + RAISE_OSERROR(errno); + return res; +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 17:37:02 2005 @@ -37,7 +37,7 @@ py.test.raises(OSError, f1) assert not os.path.exists(tmpfile) -def test_open_read_write_close(): +def test_open_read_write_seek_close(): filename = str(udir.join('test_open_read_write_close.txt')) def does_stuff(): fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) @@ -45,8 +45,10 @@ assert count == len("hello world\n") os.close(fd) fd = os.open(filename, os.O_RDONLY, 0777) + result = os.lseek(fd, 1, 0) + assert result == 1 data = os.read(fd, 500) - assert data == "hello world\n" + assert data == "ello world\n" os.close(fd) f1 = compile(does_stuff, []) From cfbolz at codespeak.net Fri Jul 29 17:52:12 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 17:52:12 +0200 (CEST) Subject: [pypy-svn] r15359 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050729155212.78C9A27B58@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 17:52:10 2005 New Revision: 15359 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added support for math.hypot Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 17:52:10 2005 @@ -23,6 +23,7 @@ ll_math.ll_math_fmod : 'LL_math_fmod', ll_math.ll_math_ldexp: 'LL_math_ldexp', ll_math.ll_math_modf: 'LL_math_modf', + ll_math.ll_math_hypot: 'LL_math_hypot', } #______________________________________________________ Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Fri Jul 29 17:52:10 2005 @@ -31,6 +31,10 @@ return ldexp(x, (int) y); } +double LL_math_hypot(double x, double y) { + return hypot(x, y); +} + RPyMODF_RESULT* LL_math_modf(double x) { double intpart; Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 17:52:10 2005 @@ -103,6 +103,13 @@ f = compile(fn, [float]) assert f(10.123) == modf(10.123) +def test_math_hypot(): + from math import hypot + def fn(x, y): + return hypot(x, y) + f = compile(fn, [float, float]) + assert f(9812.231, 1234) == hypot(9812.231, 1234) + simple_math_functions = [ 'acos', 'asin', 'atan', 'ceil', 'cos', 'cosh', 'exp', 'fabs', 'floor', 'log', 'log10', 'sin', 'sinh', 'sqrt', 'tan', 'tanh' From cfbolz at codespeak.net Fri Jul 29 18:01:48 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 18:01:48 +0200 (CEST) Subject: [pypy-svn] r15360 - pypy/dist/pypy/translator/goal Message-ID: <20050729160148.9844227B52@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 18:01:46 2005 New Revision: 15360 Added: pypy/dist/pypy/translator/goal/llinterpret.tmp Log: this file contains the incantation needed to run the flowgraph of targetpypymain in llinterp. to use it paste the lines into pdb. Added: pypy/dist/pypy/translator/goal/llinterpret.tmp ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/llinterpret.tmp Fri Jul 29 18:01:46 2005 @@ -0,0 +1,13 @@ + +import code; code.interact(local=locals()) + +import py + +from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython import rstr +if not log: + py.log.setconsumer("llinterp operation", None) + +ll_str = rstr.string_repr.convert_const("app_example.py") +interp = LLInterpreter(t.flowgraphs, t.rtyper) +interp.eval_function(entry_point, [ll_str]) From pedronis at codespeak.net Fri Jul 29 18:07:58 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 18:07:58 +0200 (CEST) Subject: [pypy-svn] r15361 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050729160758.0096B27B58@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 18:07:56 2005 New Revision: 15361 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_time.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: simple-minded time implementation Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 18:07:56 2005 @@ -18,6 +18,7 @@ ll_os .ll_os_fstat: 'LL_os_fstat', ll_os .ll_os_lseek: 'LL_os_lseek', ll_time.ll_time_clock: 'LL_time_clock', + ll_time.ll_time_time: 'LL_time_time', ll_math.ll_math_frexp: 'LL_math_frexp', ll_math.ll_math_atan2: 'LL_math_atan2', ll_math.ll_math_fmod : 'LL_math_fmod', Modified: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_time.h (original) +++ pypy/dist/pypy/translator/c/src/ll_time.h Fri Jul 29 18:07:56 2005 @@ -1,6 +1,7 @@ /************************************************************/ /*** C header subsection: time module ***/ +#include #include @@ -48,3 +49,17 @@ return ((double)clock()) / CLOCKS_PER_SEC; } #endif /* MS_WINDOWS */ + + +double LL_time_time(void) /* xxx had support for better resolutions */ +{ + return ll_floattime(); +} + +static double +ll_floattime(void) +{ + time_t secs; + time(&secs); + return (double)secs; +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 18:07:56 2005 @@ -153,3 +153,12 @@ f = compile(fn, []) assert f() == False +def test_time_time(): + import time + def fn(): + return time.time() + f = compile(fn, []) + t0 = time.time() + res = fn() + t1 = time.time() + assert t0 <= res <= t1 From cfbolz at codespeak.net Fri Jul 29 18:13:29 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 18:13:29 +0200 (CEST) Subject: [pypy-svn] r15362 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050729161329.6C6F127B58@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 18:13:26 2005 New Revision: 15362 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added c implementation of isatty Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 18:13:26 2005 @@ -17,6 +17,7 @@ ll_os .ll_os_stat: 'LL_os_stat', ll_os .ll_os_fstat: 'LL_os_fstat', ll_os .ll_os_lseek: 'LL_os_lseek', + ll_os .ll_os_isatty: 'LL_os_isatty', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_time: 'LL_time_time', ll_math.ll_math_frexp: 'LL_math_frexp', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Fri Jul 29 18:13:26 2005 @@ -155,3 +155,8 @@ RAISE_OSERROR(errno); return res; } + +long LL_os_isatty(long fd) { + return (int)isatty((int)fd); +} + Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 18:13:26 2005 @@ -82,6 +82,14 @@ assert result[1] == os.stat(filename)[1] assert result[2] == os.stat(filename)[2] +def test_os_isatty(): + def call_isatty(fd): + return os.isatty(fd) + f = compile(call_isatty, [int]) + assert f(0) == os.isatty(0) + assert f(1) == os.isatty(1) + assert f(2) == os.isatty(2) + def test_getcwd(): def does_stuff(): return os.getcwd() From arigo at codespeak.net Fri Jul 29 18:23:12 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 18:23:12 +0200 (CEST) Subject: [pypy-svn] r15363 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050729162312.96F5327B58@code1.codespeak.net> Author: arigo Date: Fri Jul 29 18:23:09 2005 New Revision: 15363 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_time.h pypy/dist/pypy/translator/c/test/test_extfunc.py pypy/dist/pypy/translator/c/test/test_genc.py Log: * time.sleep() in genc. * enable_fast_compilation() for faster testing in genc. * support old versions of gcc in buildpyxmodule. * a new test that checks that all suggested_primitive functions from the rtyper are really implemented in genc. (os.ftruncate to be done in the next few minutes) Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 18:23:09 2005 @@ -19,7 +19,8 @@ ll_os .ll_os_lseek: 'LL_os_lseek', ll_os .ll_os_isatty: 'LL_os_isatty', ll_time.ll_time_clock: 'LL_time_clock', - ll_time.ll_time_time: 'LL_time_time', + ll_time.ll_time_sleep: 'LL_time_sleep', + ll_time.ll_time_time: 'LL_time_time', ll_math.ll_math_frexp: 'LL_math_frexp', ll_math.ll_math_atan2: 'LL_math_atan2', ll_math.ll_math_fmod : 'LL_math_fmod', Modified: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_time.h (original) +++ pypy/dist/pypy/translator/c/src/ll_time.h Fri Jul 29 18:23:09 2005 @@ -51,11 +51,54 @@ #endif /* MS_WINDOWS */ -double LL_time_time(void) /* xxx had support for better resolutions */ +void LL_time_sleep(double secs) { - return ll_floattime(); +#if defined(MS_WINDOWS) + double millisecs = secs * 1000.0; + unsigned long ul_millis; + + if (millisecs > (double)ULONG_MAX) { + RaiseSimpleException(Exc_OverflowError, + "sleep length is too large"); + return; + } + ul_millis = (unsigned long)millisecs; + if (ul_millis == 0) + Sleep(ul_millis); + else { + DWORD rc; + ResetEvent(hInterruptEvent); + rc = WaitForSingleObject(hInterruptEvent, ul_millis); + if (rc == WAIT_OBJECT_0) { + /* Yield to make sure real Python signal + * handler called. + */ + Sleep(1); + RaiseSimpleException(Exc_IOError, "interrupted"); + return; + } + } +#else + struct timeval t; + double frac; + frac = fmod(secs, 1.0); + secs = floor(secs); + t.tv_sec = (long)secs; + t.tv_usec = (long)(frac*1000000.0); + if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) { +#ifdef EINTR + if (errno != EINTR) { +#else + if (1) { +#endif + RaiseSimpleException(Exc_IOError, "select() failed"); + return; + } + } +#endif } + static double ll_floattime(void) { @@ -63,3 +106,8 @@ time(&secs); return (double)secs; } + +double LL_time_time(void) /* xxx had support for better resolutions */ +{ + return ll_floattime(); +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 18:23:09 2005 @@ -3,6 +3,17 @@ import os, time from pypy.tool.udir import udir from pypy.translator.c.test.test_genc import compile +from pypy.translator.c.extfunc import EXTERNALS + +def test_all_suggested_primitives(): + for modulename in ['ll_math', 'll_os', 'll_os_path', 'll_time']: + mod = __import__('pypy.rpython.module.%s' % modulename, + None, None, ['__doc__']) + for func in mod.__dict__.values(): + if getattr(func, 'suggested_primitive', False): + yield suggested_primitive_implemented, func +def suggested_primitive_implemented(func): + assert func in EXTERNALS, "missing C implementation for %r" % (func,) def test_time_clock(): @@ -15,6 +26,16 @@ t2 = time.clock() assert t0 <= t1 <= t2 +def test_time_sleep(): + def does_nothing(): + time.sleep(0.19) + f1 = compile(does_nothing, []) + t0 = time.time() + f1() + t1 = time.time() + assert t0 <= t1 + assert t1 - t0 >= 0.15 + def test_os_open(): tmpfile = str(udir.join('test_os_open.txt')) 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 Fri Jul 29 18:23:09 2005 @@ -8,6 +8,7 @@ from pypy.objspace.flow.model import Block, Link, FunctionGraph from pypy.tool.udir import udir from pypy.translator.tool.buildpyxmodule import make_module_from_c +from pypy.translator.tool.buildpyxmodule import enable_fast_compilation from pypy.translator.gensupp import uniquemodulename # XXX this tries to make compiling faster for full-scale testing @@ -17,6 +18,7 @@ def compile_db(db): + enable_fast_compilation() # for testing modulename = uniquemodulename('testing') targetdir = udir.join(modulename).ensure(dir=1) gen_source(db, modulename, str(targetdir), defines={'COUNT_OP_MALLOCS': 1}) From arigo at codespeak.net Fri Jul 29 18:27:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 18:27:37 +0200 (CEST) Subject: [pypy-svn] r15364 - in pypy/dist/pypy: rpython translator/tool Message-ID: <20050729162737.C6AC827B5D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 18:27:35 2005 New Revision: 15364 Modified: pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/translator/tool/buildpyxmodule.py Log: Oups, forgot to check this in. Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Fri Jul 29 18:27:35 2005 @@ -10,7 +10,7 @@ # the exceptions that can be implicitely raised by some operations standardexceptions = [TypeError, OverflowError, ValueError, - ZeroDivisionError, MemoryError] + ZeroDivisionError, MemoryError, IOError] def __init__(self, rtyper): self.make_standard_exceptions(rtyper) Modified: pypy/dist/pypy/translator/tool/buildpyxmodule.py ============================================================================== --- pypy/dist/pypy/translator/tool/buildpyxmodule.py (original) +++ pypy/dist/pypy/translator/tool/buildpyxmodule.py Fri Jul 29 18:27:35 2005 @@ -77,7 +77,17 @@ # ignore unwanted features like config files. extra_compile_args = [] if get_default_compiler() == 'unix': - extra_compile_args.extend(["-Wno-unused-label", + old_version = False + try: + g = os.popen('gcc --version', 'r') + verinfo = g.read() + g.close() + except (OSError, IOError): + pass + else: + old_version = verinfo.startswith('2') + if not old_version: + extra_compile_args.extend(["-Wno-unused-label", "-Wno-unused-variable"]) attrs = { 'name': "testmodule", From cfbolz at codespeak.net Fri Jul 29 18:30:26 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 18:30:26 +0200 (CEST) Subject: [pypy-svn] r15365 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050729163026.295D027B58@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 18:30:24 2005 New Revision: 15365 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: added os.ftruncate to the c backend Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Jul 29 18:30:24 2005 @@ -18,6 +18,7 @@ ll_os .ll_os_fstat: 'LL_os_fstat', ll_os .ll_os_lseek: 'LL_os_lseek', ll_os .ll_os_isatty: 'LL_os_isatty', + ll_os .ll_os_ftruncate:'LL_os_ftruncate', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', ll_time.ll_time_time: 'LL_time_time', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Fri Jul 29 18:30:24 2005 @@ -160,3 +160,10 @@ return (int)isatty((int)fd); } +void LL_os_ftruncate(long fd, long length) { /*XXX add longfile support */ + int res; + res = ftruncate((int)fd, (off_t)length); + if (res < 0) { + RAISE_OSERROR(errno); + } +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Jul 29 18:30:24 2005 @@ -77,6 +77,22 @@ assert open(filename, 'r').read() == "hello world\n" os.unlink(filename) +def test_ftruncate(): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + os.write(fd, "hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDWR, 0777) + os.ftruncate(fd, 5) + data = os.read(fd, 500) + assert data == "hello" + os.close(fd) + does_stuff() + f1 = compile(does_stuff, []) + f1() + os.unlink(filename) + def test_os_stat(): filename = str(py.magic.autopath()) def call_stat(): From pedronis at codespeak.net Fri Jul 29 18:30:52 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 29 Jul 2005 18:30:52 +0200 (CEST) Subject: [pypy-svn] r15366 - pypy/dist/pypy/translator/c/src Message-ID: <20050729163052.C6C3727B58@code1.codespeak.net> Author: pedronis Date: Fri Jul 29 18:30:51 2005 New Revision: 15366 Modified: pypy/dist/pypy/translator/c/src/ll_time.h Log: more precise time Modified: pypy/dist/pypy/translator/c/src/ll_time.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_time.h (original) +++ pypy/dist/pypy/translator/c/src/ll_time.h Fri Jul 29 18:30:51 2005 @@ -99,12 +99,47 @@ } +#ifdef HAVE_FTIME +#include +#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) +extern int ftime(struct timeb *); +#endif /* MS_WINDOWS */ +#endif /* HAVE_FTIME */ + static double ll_floattime(void) { - time_t secs; - time(&secs); - return (double)secs; + /* There are three ways to get the time: + (1) gettimeofday() -- resolution in microseconds + (2) ftime() -- resolution in milliseconds + (3) time() -- resolution in seconds + In all cases the return value is a float in seconds. + Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may + fail, so we fall back on ftime() or time(). + Note: clock resolution does not imply clock accuracy! */ +#ifdef HAVE_GETTIMEOFDAY + { + struct timeval t; +#ifdef GETTIMEOFDAY_NO_TZ + if (gettimeofday(&t) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#else /* !GETTIMEOFDAY_NO_TZ */ + if (gettimeofday(&t, (struct timezone *)NULL) == 0) + return (double)t.tv_sec + t.tv_usec*0.000001; +#endif /* !GETTIMEOFDAY_NO_TZ */ + } +#endif /* !HAVE_GETTIMEOFDAY */ + { +#if defined(HAVE_FTIME) + struct timeb t; + ftime(&t); + return (double)t.time + (double)t.millitm * (double)0.001; +#else /* !HAVE_FTIME */ + time_t secs; + time(&secs); + return (double)secs; +#endif /* !HAVE_FTIME */ + } } double LL_time_time(void) /* xxx had support for better resolutions */ From arigo at codespeak.net Fri Jul 29 19:16:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 19:16:19 +0200 (CEST) Subject: [pypy-svn] r15367 - pypy/dist/pypy/translator/c Message-ID: <20050729171619.7C20827B58@code1.codespeak.net> Author: arigo Date: Fri Jul 29 19:16:18 2005 New Revision: 15367 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: Another special case to avoid nested /* */ comments. Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Fri Jul 29 19:16:18 2005 @@ -85,7 +85,11 @@ else: return v.name elif isinstance(v, Constant): - return self.db.get(llvalue_from_constant(v)) + value = llvalue_from_constant(v) + if value is None and not special_case_void: + return 'nothing' + else: + return self.db.get(value) else: raise TypeError, "expr(%r)" % (v,) From nik at codespeak.net Fri Jul 29 19:42:29 2005 From: nik at codespeak.net (nik at codespeak.net) Date: Fri, 29 Jul 2005 19:42:29 +0200 (CEST) Subject: [pypy-svn] r15368 - in pypy/dist/pypy/module/_codecs: . test Message-ID: <20050729174229.3CB8F27B58@code1.codespeak.net> Author: nik Date: Fri Jul 29 19:42:27 2005 New Revision: 15368 Added: pypy/dist/pypy/module/_codecs/test/ pypy/dist/pypy/module/_codecs/test/__init__.py pypy/dist/pypy/module/_codecs/test/autopath.py pypy/dist/pypy/module/_codecs/test/test_codecs.py Modified: pypy/dist/pypy/module/_codecs/app_codecs.py Log: fixed unicode_internal encoding to behave more like CPython. needed for array. Modified: pypy/dist/pypy/module/_codecs/app_codecs.py ============================================================================== --- pypy/dist/pypy/module/_codecs/app_codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Fri Jul 29 19:42:27 2005 @@ -220,7 +220,10 @@ res = ''.join(res) return res, len(res) -unicode_bytes = (len(hex(sys.maxunicode))-1)/2 +if sys.maxunicode == 65535: + unicode_bytes = 2 +else: + unicode_bytes = 4 def unicode_internal_encode( obj,errors='strict'): """None @@ -229,9 +232,13 @@ p = [] t = [ord(x) for x in obj] for i in t: + bytes = [] for j in xrange(unicode_bytes): - p += chr(i%256) + bytes += chr(i%256) i >>= 8 + if sys.byteorder == "big": + bytes.reverse() + p += bytes res = ''.join(p) return res, len(res) else: @@ -246,10 +253,20 @@ else: p=[] i=0 + if sys.byteorder == "big": + start = unicode_bytes - 1 + stop = -1 + step = -1 + else: + start = 0 + stop = unicode_bytes + step = 1 while i < len(unistr)-unicode_bytes+1: t = 0 - for j in range(unicode_bytes): - t += ord(unistr[i+j])<<(j*8) + h = 0 + for j in range(start, stop, step): + t += ord(unistr[i+j])<<(h*8) + h += 1 i += unicode_bytes p += unichr(t) res = u''.join(p) Added: pypy/dist/pypy/module/_codecs/test/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_codecs/test/__init__.py Fri Jul 29 19:42:27 2005 @@ -0,0 +1 @@ +# empty \ No newline at end of file Added: pypy/dist/pypy/module/_codecs/test/autopath.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_codecs/test/autopath.py Fri Jul 29 19:42:27 2005 @@ -0,0 +1,120 @@ +""" +self cloning, automatic path configuration + +copy this into any subdirectory of pypy from which scripts need +to be run, typically all of the test subdirs. +The idea is that any such script simply issues + + import autopath + +and this will make sure that the parent directory containing "pypy" +is in sys.path. + +If you modify the master "autopath.py" version (in pypy/tool/autopath.py) +you can directly run it which will copy itself on all autopath.py files +it finds under the pypy root directory. + +This module always provides these attributes: + + pypydir pypy root directory path + this_dir directory where this autopath.py resides + +""" + + +def __dirinfo(part): + """ return (partdir, this_dir) and insert parent of partdir + into sys.path. If the parent directories don't have the part + an EnvironmentError is raised.""" + + import sys, os + try: + head = this_dir = os.path.realpath(os.path.dirname(__file__)) + except NameError: + head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0])) + + while head: + partdir = head + head, tail = os.path.split(head) + if tail == part: + break + else: + raise EnvironmentError, "'%s' missing in '%r'" % (partdir, this_dir) + + checkpaths = sys.path[:] + pypy_root = os.path.join(head, '') + + while checkpaths: + orig = checkpaths.pop() + fullorig = os.path.join(os.path.realpath(orig), '') + if fullorig.startswith(pypy_root): + if os.path.exists(os.path.join(fullorig, '__init__.py')): + sys.path.remove(orig) + try: + sys.path.remove(head) + except ValueError: + pass + sys.path.insert(0, head) + + munged = {} + for name, mod in sys.modules.items(): + fn = getattr(mod, '__file__', None) + if '.' in name or not isinstance(fn, str): + continue + newname = os.path.splitext(os.path.basename(fn))[0] + if not newname.startswith(part + '.'): + continue + path = os.path.join(os.path.dirname(os.path.realpath(fn)), '') + if path.startswith(pypy_root) and newname != part: + modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep) + if newname != '__init__': + modpaths.append(newname) + modpath = '.'.join(modpaths) + if modpath not in sys.modules: + munged[modpath] = mod + + for name, mod in munged.iteritems(): + if name not in sys.modules: + sys.modules[name] = mod + if '.' in name: + prename = name[:name.rfind('.')] + postname = name[len(prename)+1:] + if prename not in sys.modules: + __import__(prename) + if not hasattr(sys.modules[prename], postname): + setattr(sys.modules[prename], postname, mod) + + return partdir, this_dir + +def __clone(): + """ clone master version of autopath.py into all subdirs """ + from os.path import join, walk + if not this_dir.endswith(join('pypy','tool')): + raise EnvironmentError("can only clone master version " + "'%s'" % join(pypydir, 'tool',_myname)) + + + def sync_walker(arg, dirname, fnames): + if _myname in fnames: + fn = join(dirname, _myname) + f = open(fn, 'rwb+') + try: + if f.read() == arg: + print "checkok", fn + else: + print "syncing", fn + f = open(fn, 'w') + f.write(arg) + finally: + f.close() + s = open(join(pypydir, 'tool', _myname), 'rb').read() + walk(pypydir, sync_walker, s) + +_myname = 'autopath.py' + +# set guaranteed attributes + +pypydir, this_dir = __dirinfo('pypy') + +if __name__ == '__main__': + __clone() Added: pypy/dist/pypy/module/_codecs/test/test_codecs.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_codecs/test/test_codecs.py Fri Jul 29 19:42:27 2005 @@ -0,0 +1,37 @@ +import autopath + +class AppTestCodecs: + + def test_unicode_internal_encode(self): + import sys + enc = u"a".encode("unicode_internal") + if sys.maxunicode == 65535: # UCS2 build + if sys.byteorder == "big": + assert enc == "\x00a" + else: + assert enc == "a\x00" + else: # UCS4 build + enc2 = u"\U00010098".encode("unicode_internal") + if sys.byteorder == "big": + assert enc == "\x00\x00\x00a" + assert enc2 == "\x00\x01\x00\x98" + else: + assert enc == "a\x00\x00\x00" + assert enc2 == "\x98\x00\x01\x00" + + def test_unicode_internal_decode(self): + import sys + if sys.maxunicode == 65535: # UCS2 build + if sys.byteorder == "big": + bytes = "\x00a" + else: + bytes = "a\x00" + else: # UCS4 build + if sys.byteorder == "big": + bytes = "\x00\x00\x00a" + bytes2 = "\x00\x01\x00\x98" + else: + bytes = "a\x00\x00\x00" + bytes2 = "\x98\x00\x01\x00" + assert bytes2.decode("unicode_internal") == u"\U00010098" + assert bytes.decode("unicode_internal") == u"a" From arigo at codespeak.net Fri Jul 29 20:24:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 20:24:25 +0200 (CEST) Subject: [pypy-svn] r15370 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050729182425.20C8827B5D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 20:24:22 2005 New Revision: 15370 Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_database.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Reordering of the StructDefNode.setup() and ArrayDefNode.setup(). This ensures that the C source code has the definitions in the correct order, but it's a bit fragile and head-against-wall-banging kind of ordering issues. Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Fri Jul 29 20:24:22 2005 @@ -16,7 +16,6 @@ def __init__(self, translator=None): self.translator = translator self.structdefnodes = {} - self.structdeflist = [] self.containernodes = {} self.containerlist = [] self.externalfuncs = {} @@ -40,7 +39,6 @@ raise Exception("don't know about %r" % (T,)) self.structdefnodes[key] = node node.setup() - self.structdeflist.append(node) return node def gettype(self, T, varlength=1, who_asks=None, argnames=[]): @@ -160,3 +158,17 @@ return exceptiondata.lltype_of_exception_value else: return Ptr(PyObject) + + def getstructdeflist(self): + # return the StructDefNodes sorted according to dependencies + result = [] + seen = {} + def produce(node): + if node not in seen: + for othernode in node.dependencies: + produce(othernode) + result.append(node) + seen[node] = True + for node in self.structdefnodes.values(): + produce(node) + return result Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Fri Jul 29 20:24:22 2005 @@ -55,11 +55,12 @@ # # All declarations # + structdeflist = database.getstructdeflist() print >> f print >> f, '/***********************************************************/' print >> f, '/*** Structure definitions ***/' print >> f - for node in database.structdeflist: + for node in structdeflist: for line in node.definition(phase=1): print >> f, line print >> f @@ -82,7 +83,7 @@ print >> f, '#include "src/g_include.h"' print >> f blank = False - for node in database.structdeflist: + for node in structdeflist: for line in node.definition(phase=2): print >> f, line blank = True @@ -138,7 +139,7 @@ print >> f, '/*** Debugging info ***/' print >> f print >> f, 'static int debuginfo_offsets[] = {' - for node in database.structdeflist: + for node in database.structdefnodes.values(): for expr in symboltable.generate_type_info(database, node): print >> f, '\t%s,' % expr print >> f, '\t0 };' Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Fri Jul 29 20:24:22 2005 @@ -30,11 +30,6 @@ self.STRUCT = STRUCT self.LLTYPE = STRUCT self.varlength = varlength - - def setup(self): - db = self.db - STRUCT = self.STRUCT - varlength = self.varlength if varlength == 1: basename = STRUCT._name with_number = True @@ -44,15 +39,7 @@ with_number = False self.name = db.namespace.uniquename(basename, with_number=with_number) self.dependencies = {} - self.fields = [] self.prefix = somelettersfrom(STRUCT._name) + '_' - for name in STRUCT._names: - T = self.c_struct_field_type(name) - if name == STRUCT._arrayfld: - typename = db.gettype(T, varlength=varlength, who_asks=self) - else: - typename = db.gettype(T, who_asks=self) - self.fields.append((self.c_struct_field_name(name), typename)) # look up the reference counter field if needs_refcount(STRUCT): @@ -61,14 +48,29 @@ # refcount in the first field T = self.c_struct_field_type(STRUCT._names[0]) assert isinstance(T, GC_CONTAINER) - firstfieldname, firstfieldtype = self.fields[0] firstdefnode = db.gettypedefnode(T) + firstfieldname = self.c_struct_field_name(STRUCT._names[0]) self.refcount = '%s.%s' % (firstfieldname, firstdefnode.refcount) # check here that there is enough run-time type information to # handle this case getRuntimeTypeInfo(STRUCT) getRuntimeTypeInfo(T) + def setup(self): + # this computes self.fields + self.fields = [] + db = self.db + STRUCT = self.STRUCT + varlength = self.varlength + for name in STRUCT._names: + T = self.c_struct_field_type(name) + if name == STRUCT._arrayfld: + typename = db.gettype(T, varlength=self.varlength, + who_asks=self) + else: + typename = db.gettype(T, who_asks=self) + self.fields.append((self.c_struct_field_name(name), typename)) + # do we need deallocator(s)? if self.refcount and varlength == 1: self.deallocator = db.namespace.uniquename('dealloc_'+self.name) @@ -173,16 +175,11 @@ self.db = db self.ARRAY = ARRAY self.LLTYPE = ARRAY - self.varlength = varlength - self.original_varlength = varlength + original_varlength = varlength if ARRAY is STR.chars: - self.varlength += 1 # for the NULL char at the end of the string - - def setup(self): - db = self.db - ARRAY = self.ARRAY - varlength = self.varlength - if self.original_varlength == 1: + varlength += 1 # for the NULL char at the end of the string + self.varlength = varlength + if original_varlength == 1: basename = 'array' with_number = True else: @@ -191,12 +188,17 @@ with_number = False self.name = db.namespace.uniquename(basename, with_number=with_number) self.dependencies = {} - self.itemtypename = db.gettype(ARRAY.OF, who_asks=self) # look up the reference counter field if needs_refcount(ARRAY): self.refcount = 'refcount' + def setup(self): + db = self.db + ARRAY = self.ARRAY + varlength = self.varlength + self.itemtypename = db.gettype(ARRAY.OF, who_asks=self) + # is a specific deallocator needed? if self.refcount and varlength == 1 and list(self.deallocator_lines('')): self.deallocator = db.namespace.uniquename('dealloc_'+self.name) 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 Jul 29 20:24:22 2005 @@ -9,10 +9,11 @@ def dump_on_stdout(database): print '/*********************************/' - for node in database.structdeflist: + structdeflist = database.getstructdeflist() + for node in structdeflist: for line in node.definition(phase=1): print line - for node in database.structdeflist: + for node in structdeflist: for line in node.definition(phase=2): print line print 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 Fri Jul 29 20:24:22 2005 @@ -182,3 +182,20 @@ f1 = compile(fn, [int]) res = f1(1) assert res == 'e' + + +def test_recursive_struct(): + # B has an A as its super field, and A has a pointer to B. + class A: + pass + class B(A): + pass + def fn(i): + a = A() + b = B() + a.b = b + b.i = i + return a.b.i + f1 = compile(fn, [int]) + res = f1(42) + assert res == 42 From ericvrp at codespeak.net Fri Jul 29 20:57:35 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 20:57:35 +0200 (CEST) Subject: [pypy-svn] r15371 - pypy/dist/pypy/translator/c/test Message-ID: <20050729185735.289A727B5D@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 20:57:34 2005 New Revision: 15371 Modified: pypy/dist/pypy/translator/c/test/test_exception.py Log: typo Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Fri Jul 29 20:57:34 2005 @@ -2,9 +2,42 @@ from pypy.translator.translator import Translator +class TestException(Exception): + pass + class MyException(Exception): pass +def test_simple1(): + def raise_(i): + if i == 0: + raise TestException() + elif i == 1: + raise MyException() + 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 + t = Translator(fn) + t.annotate([int]).simplify() + t.specialize() + #t.view() + f = t.ccompile() + assert f(0) == fn(0) + assert f(1) == fn(1) + assert f(2) == fn(2) + def test_simple2(): #taken from ../../llvm2/test/test_exception.py py.test.skip("decided whethe we want to support IndexError on [] at interp-level") def fn(n): From ericvrp at codespeak.net Fri Jul 29 21:05:56 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 29 Jul 2005 21:05:56 +0200 (CEST) Subject: [pypy-svn] r15373 - in pypy/dist/pypy/translator/llvm2: module test Message-ID: <20050729190556.80C6527B58@code1.codespeak.net> Author: ericvrp Date: Fri Jul 29 21:05:55 2005 New Revision: 15373 Modified: pypy/dist/pypy/translator/llvm2/module/ll_os.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: added os.isatty Modified: pypy/dist/pypy/translator/llvm2/module/ll_os.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/module/ll_os.py (original) +++ pypy/dist/pypy/translator/llvm2/module/ll_os.py Fri Jul 29 21:05:55 2005 @@ -6,6 +6,7 @@ declare int %write(int, sbyte*, int) declare int %read(int, sbyte*, int) declare sbyte* %strncpy(sbyte*, sbyte*, int) +declare int %isatty(int) """ extfunctions = {} @@ -59,3 +60,14 @@ } """) + +extfunctions["%ll_os_isatty"] = ((), """ +bool %ll_os_isatty(int %fd) { + %ret = call int %isatty(int %fd) + %ret.bool = cast int %ret to bool + ret bool %ret.bool +} + +""") + + Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Fri Jul 29 21:05:55 2005 @@ -189,4 +189,12 @@ f = compile_function(fn, []) assert f() == False +def test_os_isatty(): + def call_isatty(fd): + return os.isatty(fd) + f = compile_function(call_isatty, [int]) + assert f(0) == os.isatty(0) + assert f(1) == os.isatty(1) + assert f(2) == os.isatty(2) + # end of tests taken from c backend From arigo at codespeak.net Fri Jul 29 21:13:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 21:13:19 +0200 (CEST) Subject: [pypy-svn] r15374 - pypy/dist/pypy/translator/c Message-ID: <20050729191319.C1E2327B5D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 21:13:18 2005 New Revision: 15374 Modified: pypy/dist/pypy/translator/c/genc.py Log: We need to forward-declare all structs, because (argh argh argh) in C a "struct X" that first occurs in a function arguments list will be declared with a scope local to that argument list! Useless. Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Fri Jul 29 21:13:18 2005 @@ -61,6 +61,9 @@ print >> f, '/*** Structure definitions ***/' print >> f for node in structdeflist: + print >> f, 'struct %s;' % node.name + print >> f + for node in structdeflist: for line in node.definition(phase=1): print >> f, line print >> f From cfbolz at codespeak.net Fri Jul 29 21:25:20 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 21:25:20 +0200 (CEST) Subject: [pypy-svn] r15376 - pypy/dist/pypy/translator/goal Message-ID: <20050729192520.0D2BC27B5D@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 21:25:17 2005 New Revision: 15376 Removed: pypy/dist/pypy/translator/goal/llinterpret.tmp Modified: pypy/dist/pypy/translator/goal/targetpypymain.py pypy/dist/pypy/translator/goal/targetrichards.py pypy/dist/pypy/translator/goal/translate_pypy.py Log: (pedronis, cfbolz) added an options to interpret the flow graph with the llinterpreter. Deleted: /pypy/dist/pypy/translator/goal/llinterpret.tmp ============================================================================== --- /pypy/dist/pypy/translator/goal/llinterpret.tmp Fri Jul 29 21:25:17 2005 +++ (empty file) @@ -1,13 +0,0 @@ - -import code; code.interact(local=locals()) - -import py - -from pypy.rpython.llinterp import LLInterpreter -from pypy.rpython import rstr -if not log: - py.log.setconsumer("llinterp operation", None) - -ll_str = rstr.string_repr.convert_const("app_example.py") -interp = LLInterpreter(t.flowgraphs, t.rtyper) -interp.eval_function(entry_point, [ll_str]) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jul 29 21:25:17 2005 @@ -50,6 +50,12 @@ return entry_point, [SomeString()] +def get_llinterp_args(): + from pypy.rpython import rstr + ll_str = rstr.string_repr.convert_const("app_example.py") + return [ll_str] + + # _____ Run translated _____ def run(c_entry_point): argv = [os.path.join(this_dir, 'app_example.py')] Modified: pypy/dist/pypy/translator/goal/targetrichards.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrichards.py (original) +++ pypy/dist/pypy/translator/goal/targetrichards.py Fri Jul 29 21:25:17 2005 @@ -7,6 +7,9 @@ def target(): return entry_point, [] +def get_llinterp_args(): + return [] + # _____ Run translated _____ def run(c_entry_point): print "Translated:" Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jul 29 21:25:17 2005 @@ -33,6 +33,8 @@ -load filename restores the translator from a file. The file type must be either .py or .zip . + -llinterpret + interprets the flow graph after rtyping it """ import autopath, sys, os @@ -283,6 +285,7 @@ '-load': False, '-save': False, '-fork': False, + '-llinterpret': False, } listen_port = None argiter = iter(sys.argv[1:]) @@ -554,7 +557,16 @@ ) if err: raise err[0], err[1], err[2] - if options['-no-c']: + if options['-llinterpret']: + def interpret(): + import py + from pypy.rpython.llinterp import LLInterpreter + py.log.setconsumer("llinterp operation", None) + interp = LLInterpreter(t.flowgraphs, t.rtyper) + interp.eval_function(entry_point, + targetspec_dic['get_llinterp_args']()) + interpret() + elif options['-no-c']: print 'Not generating C code.' elif options['-c']: print 'Generating C code without compiling it...' From cfbolz at codespeak.net Fri Jul 29 21:57:03 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 21:57:03 +0200 (CEST) Subject: [pypy-svn] r15379 - pypy/dist/pypy/rpython Message-ID: <20050729195703.654BD27B5D@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 21:57:01 2005 New Revision: 15379 Modified: pypy/dist/pypy/rpython/llinterp.py Log: (pedronis, cfbolz): llinterpreter now prints a kind of traceback if an uncaught exception occurs. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jul 29 21:57:01 2005 @@ -20,6 +20,7 @@ self.flowgraphs = flowgraphs self.bindings = {} self.typer = typer + self.active_frame = None def getgraph(self, func): return self.flowgraphs[func] @@ -27,7 +28,29 @@ def eval_function(self, func, args=()): graph = self.getgraph(func) llframe = LLFrame(graph, args, self) - return llframe.eval() + try: + return llframe.eval() + except Exception, e: + print "AN ERROR OCCURED:", e + self.print_traceback() + raise + + def print_traceback(self): + frame = self.active_frame + frames = [] + while frame is not None: + frames.append(frame) + frame = frame.f_back + frames.reverse() + for frame in frames: + print frame.graph.name, + print self.typer.annotator.annotated[frame.curr_block].__module__ + for i, operation in enumerate(frame.curr_block.operations): + if i == frame.curr_operation_index: + print "E ", + else: + print " ", + print operation # implementations of ops from flow.operation from pypy.objspace.flow.operation import FunctionByName @@ -36,11 +59,14 @@ class LLFrame(object): - def __init__(self, graph, args, llinterpreter): + def __init__(self, graph, args, llinterpreter, f_back=None): self.graph = graph self.args = args self.llinterpreter = llinterpreter self.bindings = {} + self.f_back = f_back + self.curr_block = None + self.curr_operation_index = 0 # _______________________________________________________ # variable setters/getters helpers @@ -85,6 +111,7 @@ # evaling functions def eval(self): + self.llinterpreter.active_frame = self graph = self.graph log.frame("evaluating", graph.name) nextblock = graph.startblock @@ -93,17 +120,20 @@ self.fillvars(nextblock, args) nextblock, args = self.eval_block(nextblock) if nextblock is None: + self.llinterpreter.active_frame = self.f_back return args def eval_block(self, block): """ return (nextblock, values) tuple. If nextblock is None, values is the concrete return value. """ + self.curr_block = block catch_exception = block.exitswitch == Constant(last_exception) e = None try: - for op in block.operations: + for i, op in enumerate(block.operations): + self.curr_operation_index = i self.eval_operation(op) except LLException, e: if not (catch_exception and op is block.operations[-1]): @@ -209,7 +239,7 @@ except KeyError: assert has_callable, "don't know how to execute %r" % f return self.invoke_callable_with_pyexceptions(f, *args) - frame = self.__class__(graph, args, self.llinterpreter) + frame = self.__class__(graph, args, self.llinterpreter, self) return frame.eval() def op_malloc(self, obj): From cfbolz at codespeak.net Fri Jul 29 21:59:13 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 21:59:13 +0200 (CEST) Subject: [pypy-svn] r15380 - pypy/dist/pypy/translator/goal Message-ID: <20050729195913.E426127B5D@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 21:59:12 2005 New Revision: 15380 Added: pypy/dist/pypy/translator/goal/targetsegfault.py Log: added a segfaulting target to test the llinterpreter traceback. Added: pypy/dist/pypy/translator/goal/targetsegfault.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/targetsegfault.py Fri Jul 29 21:59:12 2005 @@ -0,0 +1,15 @@ +def getitem(list, index): + return list[index] + +def entry_point(i): + return getitem([i, 2, 3, 4], 2) + getitem(None, i) + +def target(): + return entry_point, [int] + +def get_llinterp_args(): + return [1] + +# _____ Run translated _____ +def run(c_entry_point): + c_entry_point(0) From arigo at codespeak.net Fri Jul 29 22:04:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 22:04:46 +0200 (CEST) Subject: [pypy-svn] r15381 - in pypy/dist/pypy/translator/c: src test Message-ID: <20050729200446.7EAF727B58@code1.codespeak.net> Author: arigo Date: Fri Jul 29 22:04:44 2005 New Revision: 15381 Modified: pypy/dist/pypy/translator/c/src/int.h pypy/dist/pypy/translator/c/test/test_typed.py Log: Re-enabled the ValueError-raising version of >> and <<, for translate_pypy. 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 Jul 29 22:04:44 2005 @@ -87,36 +87,19 @@ if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ FAIL_OVF(err, "x<= 0) { OP_INT_RSHIFT(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ - -/* #define OP_INT_LSHIFT(x,y,r,err) \ */ -/* if ((y) < LONG_BIT) \ */ -/* r = (x) << (y); \ */ -/* else r = 0; */ - -/* #define OP_INT_LSHIFT_VAL(x,y,r,err) \ */ -/* if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ - -/* #define OP_INT_LSHIFT_OVF(x,y,r,err) \ */ -/* OP_INT_LSHIFT(x,y,r,err) \ */ -/* if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ */ -/* FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ */ -/* else FAIL_VAL(err, "negative shift count") */ +#define OP_INT_RSHIFT_VAL(x,y,r,err) \ + if ((y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ + else FAIL_VAL(err, "negative shift count") + +#define OP_INT_LSHIFT_VAL(x,y,r,err) \ + if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ + else FAIL_VAL(err, "negative shift count") + +#define OP_INT_LSHIFT_OVF_VAL(x,y,r,err) \ + if ((y) >= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ + else FAIL_VAL(err, "negative shift count") /* floor division */ Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Fri Jul 29 22:04:44 2005 @@ -226,14 +226,14 @@ raises(OverflowError, fn, -1) raises(ZeroDivisionError, fn, 0) -## def test_int_rshift_val(self): -## fn = self.getcompiled(snippet.rshift_func) -## raises(ValueError, fn, -1) - -## def test_int_lshift_ovf_val(self): -## fn = self.getcompiled(snippet.lshift_func) -## raises(ValueError, fn, -1) -## raises(OverflowError, fn, 1) + def test_int_rshift_val(self): + fn = self.getcompiled(snippet.rshift_func) + raises(ValueError, fn, -1) + + def test_int_lshift_ovf_val(self): + fn = self.getcompiled(snippet.lshift_func) + raises(ValueError, fn, -1) + raises(OverflowError, fn, 1) def test_int_unary_ovf(self): fn = self.getcompiled(snippet.unary_func) From cfbolz at codespeak.net Fri Jul 29 22:46:51 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 22:46:51 +0200 (CEST) Subject: [pypy-svn] r15382 - in pypy/dist/pypy/rpython: . test Message-ID: <20050729204651.4E50D27B58@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 22:46:49 2005 New Revision: 15382 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: (samule, cfbolz): fixed is_true for instances, which was always true :-( --> segfaulting targetpypymain. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jul 29 22:46:49 2005 @@ -540,6 +540,10 @@ vinst, vattr, vvalue = hop.inputargs(self, Void, r_value) self.setfield(vinst, attr, vvalue, hop.llops) + def rtype_is_true(self, hop): + vinst, = hop.inputargs(self) + return hop.genop('ptr_nonzero', [vinst], resulttype=Bool) + def ll_str(i, r): instance = cast_pointer(OBJECTPTR, i) from pypy.rpython import rstr @@ -590,7 +594,6 @@ def rtype_ne(rpair, hop): v = rpair.rtype_eq(hop) return hop.genop("bool_not", [v], resulttype=Bool) - # ____________________________________________________________ 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 Jul 29 22:46:49 2005 @@ -237,6 +237,23 @@ res = interpret(f, [3]) assert res == 0x0200 +def test_istrue(): + class A: + pass + def f(i): + if i == 0: + a = A() + else: + a = None + if a: + return 1 + else: + return 2 + res = interpret(f, [0]) + assert res == 1 + res = interpret(f, [1]) + assert res == 2 + def test_ne(): class A: pass class B(A): pass From arigo at codespeak.net Fri Jul 29 22:53:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 22:53:23 +0200 (CEST) Subject: [pypy-svn] r15383 - pypy/dist/pypy/objspace/std Message-ID: <20050729205323.1F4B927B58@code1.codespeak.net> Author: arigo Date: Fri Jul 29 22:53:21 2005 New Revision: 15383 Modified: pypy/dist/pypy/objspace/std/dictobject.py Log: Don't use '%' in W_DictObject. Better use '&' masking, as we know the hash table's length is a power of two. Additionally, genc doesn't know about '/' and '%' on r_uint... Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Fri Jul 29 22:53:21 2005 @@ -65,7 +65,8 @@ assert isinstance(lookup_hash, r_uint) space = self.space data = self.data - i = lookup_hash % len(data) + mask = len(data) - 1 # len(data) is expected to be a power of 2 + i = lookup_hash & mask entry = data[i] if entry.w_key is None or space.is_w(w_lookup, entry.w_key): @@ -85,7 +86,7 @@ perturb = lookup_hash while 1: i = (i << 2) + i + perturb + 1 - entry = data[i%len(data)] + entry = data[i & mask] if entry.w_key is None: if freeslot: return freeslot From arigo at codespeak.net Fri Jul 29 23:07:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Jul 2005 23:07:13 +0200 (CEST) Subject: [pypy-svn] r15384 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050729210713.4BE1C27B5D@code1.codespeak.net> Author: arigo Date: Fri Jul 29 23:07:10 2005 New Revision: 15384 Modified: pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Support for constant float infinites. Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Fri Jul 29 23:07:10 2005 @@ -15,8 +15,17 @@ assert value >= 0 return '%dUL' % value +def isinf(x): + return x != 0.0 and x / 2 == x + def name_float(value): - return repr(value) + if isinf(value): + if value > 0: + return '1E9999999' + else: + return '-1E9999999' + else: + return repr(value) def name_char(value): assert type(value) is str and len(value) == 1 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 Fri Jul 29 23:07:10 2005 @@ -199,3 +199,13 @@ f1 = compile(fn, [int]) res = f1(42) assert res == 42 + +def test_infinite_float(): + x = 1.0 + while x != x / 2: + x *= 3.1416 + def fn(): + return x + f1 = compile(fn, []) + res = f1() + assert res > 0 and res == res / 2 From hpk at codespeak.net Fri Jul 29 23:14:53 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 29 Jul 2005 23:14:53 +0200 (CEST) Subject: [pypy-svn] r15386 - pypy/extradoc/sprintinfo Message-ID: <20050729211453.993F327B5D@code1.codespeak.net> Author: hpk Date: Fri Jul 29 23:14:52 2005 New Revision: 15386 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: fixed applevel stdout problem (by fixing/refactoring the py lib) Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Fri Jul 29 23:14:52 2005 @@ -57,7 +57,7 @@ Left:: - - bug to be fixed: applevel test stdout is no longer + - DONE bug to be fixed: applevel test stdout is no longer captured. - running translate_pypy! @@ -90,6 +90,6 @@ - christian: rewriting marshal - - armin, holger: applevel stdout + - DONE armin, holger: applevel stdout - armin: write nik mail, fix the entrypoint From cfbolz at codespeak.net Fri Jul 29 23:30:20 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 23:30:20 +0200 (CEST) Subject: [pypy-svn] r15387 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050729213020.76D6827B53@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 23:30:19 2005 New Revision: 15387 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/translator/c/test/test_exception.py Log: (arigo, cfbolz, pedronis): added implicit IndexError handling for lists + test Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Fri Jul 29 23:30:19 2005 @@ -180,26 +180,44 @@ def rtype_getitem((r_lst, r_int), hop): v_lst, v_index = hop.inputargs(r_lst, Signed) - if hop.args_s[1].nonneg: - llfn = ll_getitem_nonneg + if hop.has_implicit_exception(IndexError): + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg_checked + else: + llfn = ll_getitem_checked else: - llfn = ll_getitem + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg + else: + llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) def rtype_setitem((r_lst, r_int), hop): v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr) - if hop.args_s[1].nonneg: - llfn = ll_setitem_nonneg + if hop.has_implicit_exception(IndexError): + if hop.args_s[1].nonneg: + llfn = ll_setitem_nonneg_checked + else: + llfn = ll_setitem_checked else: - llfn = ll_setitem + if hop.args_s[1].nonneg: + llfn = ll_setitem_nonneg + else: + llfn = ll_setitem return hop.gendirectcall(llfn, v_lst, v_index, v_item) def rtype_delitem((r_lst, r_int), hop): v_lst, v_index = hop.inputargs(r_lst, Signed) - if hop.args_s[1].nonneg: - llfn = ll_delitem_nonneg + if hop.has_implicit_exception(IndexError): + if hop.args_s[1].nonneg: + llfn = ll_delitem_nonneg_checked + else: + llfn = ll_delitem_checked else: - llfn = ll_delitem + if hop.args_s[1].nonneg: + llfn = ll_delitem_nonneg + else: + llfn = ll_delitem return hop.gendirectcall(llfn, v_lst, v_index) def rtype_mul((r_lst, r_int), hop): @@ -386,14 +404,46 @@ i += len(l.items) return l.items[i] +def ll_getitem_nonneg_checked(l, i): + if i >= len(l.items): + raise IndexError + else: + return l.items[i] + +def ll_getitem_checked(l, i): + if i < 0: + i += len(l.items) + if i >= len(l.items) or i < 0: + raise IndexError + else: + return l.items[i] + def ll_setitem_nonneg(l, i, newitem): l.items[i] = newitem +def ll_setitem_nonneg_checked(l, i, newitem): + if i >= len(l.items): + raise IndexError + l.items[i] = newitem + def ll_setitem(l, i, newitem): if i < 0: i += len(l.items) l.items[i] = newitem +def ll_setitem_checked(l, i, newitem): + if i < 0: + i += len(l.items) + if i >= len(l.items) or i < 0: + raise IndexError + else: + l.items[i] = newitem + +def ll_delitem_nonneg_checked(l, i): + if i >= len(l.items): + raise IndexError + ll_delitem_nonneg(l, i) + def ll_delitem_nonneg(l, i): newlength = len(l.items) - 1 newitems = malloc(typeOf(l).TO.items.TO, newlength) @@ -411,6 +461,13 @@ i += len(l.items) ll_delitem_nonneg(l, i) +def ll_delitem_checked(l, i): + if i < 0: + i += len(l.items) + if i >= len(l.items) or i < 0: + raise IndexErrror + ll_delitem_nonneg(l, i) + def ll_concat(l1, l2): len1 = len(l1.items) len2 = len(l2.items) Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Fri Jul 29 23:30:19 2005 @@ -38,15 +38,13 @@ assert f(1) == fn(1) assert f(2) == fn(2) -def test_simple2(): #taken from ../../llvm2/test/test_exception.py - py.test.skip("decided whethe we want to support IndexError on [] at interp-level") +def test_implicit_index_error_lists(): def fn(n): - lst = range(10) + lst = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] try: - lst[n] + return lst[n] except: return 2 - return 4 t = Translator(fn) t.annotate([int]).simplify() t.specialize() From cfbolz at codespeak.net Fri Jul 29 23:46:51 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 29 Jul 2005 23:46:51 +0200 (CEST) Subject: [pypy-svn] r15388 - in pypy/dist/pypy/rpython: . test Message-ID: <20050729214651.B38EF27B5D@code1.codespeak.net> Author: cfbolz Date: Fri Jul 29 23:46:49 2005 New Revision: 15388 Modified: pypy/dist/pypy/rpython/rrange.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (pedronis, arigo, cfbolz): added implicit IndexError handling (plus test) to strs. raising a TyperError for range for a situation that basically cannot happen at the moment. Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Fri Jul 29 23:46:49 2005 @@ -34,6 +34,9 @@ class __extend__(pairtype(RangeRepr, IntegerRepr)): def rtype_getitem((r_rng, r_int), hop): + if hop.has_implicit_exception(IndexError): + s = "getitem on range with try, except: block not supported." + raise TyperError, s v_lst, v_index = hop.inputargs(r_rng, Signed) cstep = hop.inputconst(Signed, r_rng.step) if hop.args_s[1].nonneg: Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jul 29 23:46:49 2005 @@ -179,10 +179,16 @@ class __extend__(pairtype(StringRepr, IntegerRepr)): def rtype_getitem(_, hop): v_str, v_index = hop.inputargs(string_repr, Signed) - if hop.args_s[1].nonneg: - llfn = ll_stritem_nonneg + if hop.has_implicit_exception(IndexError): + if hop.args_s[1].nonneg: + llfn = ll_stritem_nonneg_checked + else: + llfn = ll_stritem_checked else: - llfn = ll_stritem + if hop.args_s[1].nonneg: + llfn = ll_stritem_nonneg + else: + llfn = ll_stritem return hop.gendirectcall(llfn, v_str, v_index) def rtype_mod(_, hop): @@ -499,11 +505,23 @@ 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 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 Jul 29 23:46:49 2005 @@ -13,6 +13,23 @@ res = 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): From cfbolz at codespeak.net Sat Jul 30 00:30:14 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 00:30:14 +0200 (CEST) Subject: [pypy-svn] r15389 - in pypy/dist/pypy/rpython: . test Message-ID: <20050729223014.C6E9827B5D@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 00:30:13 2005 New Revision: 15389 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: (arigo, cfbolz): added overflowing operations to the llinterpreter Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Jul 30 00:30:13 2005 @@ -351,16 +351,6 @@ assert type(c) is float return math.fmod(b,c) - def op_int_invert(self, a): - assert type(a) is int - return ~a - - def op_uint_invert(self, a): - assert type(a) is r_uint - return ~a - - - # operations on pyobjects! for opname in opimpls.keys(): exec py.code.Source(""" @@ -415,7 +405,22 @@ func = opimpls[%(opname)r] return %(adjust_result)s(func(x, y)) """ % locals()).compile() - for opname in 'is_true', 'neg': + if typ is int: + opname += '_ovf' + exec py.code.Source(""" + def op_%(opnameprefix)s_%(pureopname)s_ovf(self, x, y): + assert isinstance(x, %(typname)s) + assert isinstance(y, %(typname)s) + func = opimpls[%(opname)r] + try: + return %(adjust_result)s(func(x, y)) + except OverflowError, e: + self.make_llexception(e) + """ % locals()).compile() + funcname = "op_%(opnameprefix)s_%(pureopname)s_ovf" % locals() + setattr(LLFrame, funcname, globals()[funcname]) + + for opname in 'is_true', 'neg', 'abs', 'invert': assert opname in opimpls if typ is int and opname not in ops_returning_a_bool: adjust_result = 'intmask' @@ -427,6 +432,20 @@ func = opimpls[%(opname)r] return %(adjust_result)s(func(x)) """ % locals()).compile() + if typ is int: + opname += '_ovf' + exec py.code.Source(""" + def op_%(opnameprefix)s_%(opname)s_ovf(self, x): + assert isinstance(x, %(typname)s) + func = opimpls[%(opname)r] + try: + return %(adjust_result)s(func(x)) + except OverflowError, e: + self.make_llexception(e) + """ % locals()).compile() + funcname = "op_%(opnameprefix)s_%(opname)s_ovf" % locals() + setattr(LLFrame, funcname, globals()[funcname]) + for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'): assert opname in opimpls 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 Sat Jul 30 00:30:13 2005 @@ -8,7 +8,7 @@ from pypy.rpython.rint import signed_repr from pypy.rpython import rstr from pypy.annotation.model import lltype_to_annotation -from pypy.rpython.rarithmetic import r_uint +from pypy.rpython.rarithmetic import r_uint, ovfcheck # switch on logging of interp to show more info on failing tests @@ -258,6 +258,28 @@ res = interpret(f, [_1L, _2L], someobjects=True) assert res._obj.value == 3L +def test_ovf(): + import sys + def f(x): + try: + return ovfcheck(sys.maxint + x) + except OverflowError: + return 1 + res = interpret(f, [1]) + assert res == 1 + res = interpret(f, [0]) + assert res == sys.maxint + def g(x): + try: + return ovfcheck(abs(x)) + except OverflowError: + return 42 + res = interpret(g, [-sys.maxint - 1]) + assert res == 42 + res = interpret(g, [-15]) + assert res == 15 + + def test_obj_obj_is(): def f(x,y): return x is y From cfbolz at codespeak.net Sat Jul 30 01:08:06 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 01:08:06 +0200 (CEST) Subject: [pypy-svn] r15390 - in pypy/dist/pypy/rpython: . test Message-ID: <20050729230806.050E127B5D@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 01:08:05 2005 New Revision: 15390 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: added abs_int_ovf as well. There's probably more coming... Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Jul 30 01:08:05 2005 @@ -342,6 +342,14 @@ assert type(b) is r_uint return intmask(b) + def op_int_floordiv_ovf_zer(self, a, b): + assert type(a) is int + assert type(b) is int + if b == 0: + self.make_llexception(ZeroDivisionError()) + return self.op_int_floordiv_ovf(a, b) + + def op_float_floor(self, b): assert type(b) is float return math.floor(b) @@ -435,7 +443,7 @@ if typ is int: opname += '_ovf' exec py.code.Source(""" - def op_%(opnameprefix)s_%(opname)s_ovf(self, x): + def op_%(opnameprefix)s_%(opname)s(self, x): assert isinstance(x, %(typname)s) func = opimpls[%(opname)r] try: @@ -443,7 +451,7 @@ except OverflowError, e: self.make_llexception(e) """ % locals()).compile() - funcname = "op_%(opnameprefix)s_%(opname)s_ovf" % locals() + funcname = "op_%(opnameprefix)s_%(opname)s" % locals() setattr(LLFrame, funcname, globals()[funcname]) 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 Sat Jul 30 01:08:05 2005 @@ -278,6 +278,22 @@ assert res == 42 res = interpret(g, [-15]) assert res == 15 + +def test_ovf_zer(): + import sys + def f(x): + try: + return ovfcheck((-sys.maxint - 1) // x) + except OverflowError: + return 1 + except ZeroDivisionError: + return 0 + res = interpret(f, [0]) + assert res == 0 + res = interpret(f, [-1]) + assert res == 1 + res = interpret(f, [30]) + assert res == (-sys.maxint - 1) // 30 def test_obj_obj_is(): From ericvrp at codespeak.net Sat Jul 30 01:24:56 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 30 Jul 2005 01:24:56 +0200 (CEST) Subject: [pypy-svn] r15391 - in pypy/dist/pypy/translator/llvm2: . module test Message-ID: <20050729232456.73ED127B5D@code1.codespeak.net> Author: ericvrp Date: Sat Jul 30 01:24:55 2005 New Revision: 15391 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/module/extfunction.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: exceptions kind-of-work, a bit, maybe Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 30 01:24:55 2005 @@ -108,10 +108,10 @@ names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] - for i, link in enumerate(entrylinks): + for i, link in enumerate(entrylinks): #XXX refactor into a transformation if link.prevblock.exitswitch == Constant(last_exception) and \ link.prevblock.exits[0].target != block: - blocknames[i] += '_exception' + blocknames[i] += '_exception_found_branchto_' + self.block_to_name[block] if type_ != "void": codewriter.phi(arg, type_, names, blocknames) @@ -120,8 +120,8 @@ if len(block.exits) == 1: codewriter.br_uncond(self.block_to_name[block.exits[0].target]) elif len(block.exits) == 2: - switch = self.db.repr_arg(block.exitswitch) - codewriter.br(switch, self.block_to_name[block.exits[0].target], + cond = self.db.repr_arg(block.exitswitch) + codewriter.br(cond, self.block_to_name[block.exits[0].target], self.block_to_name[block.exits[1].target]) def _last_operation(self, block, opname): @@ -175,17 +175,17 @@ inputargs = self.db.repr_arg_multi(block.inputargs) inputargtypes = self.db.repr_arg_type_multi(block.inputargs) - tmptype, tmpvar = 'long', self.db.repr_tmpvar() + tmptype, tmpvar = 'sbyte*', self.db.repr_tmpvar() codewriter.cast(tmpvar, inputargtypes[0], inputargs[0], tmptype) codewriter.store(tmptype, tmpvar, '%last_exception_type') - tmptype, tmpvar = 'long', self.db.repr_tmpvar() + tmptype, tmpvar = 'sbyte*', self.db.repr_tmpvar() codewriter.cast(tmpvar, inputargtypes[1], inputargs[1], tmptype) codewriter.store(tmptype, tmpvar, '%last_exception_value') - #else: - # Reraising last_exception. - # Which is already stored in the global variables. - # So nothing needs to happen here! + else: + codewriter.comment('reraise last exception') + #Reraising last_exception. + #Which is already stored in the global variables. + #So nothing needs to happen here! - codewriter.comment('reraise last exception') codewriter.unwind() Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 30 01:24:55 2005 @@ -39,11 +39,20 @@ if func is None: func = self.translator.entrypoint self.entrypoint = func - + + #make sure exception matching and exception type are available + e = self.translator.rtyper.getexceptiondata() + for ll_helper in (e.ll_exception_match,): + ptr = getfunctionptr(self.translator, ll_helper) + c = inputconst(lltype.typeOf(ptr), ptr) + self.db.prepare_repr_arg(c) + assert c in self.db.obj2node + ptr = getfunctionptr(self.translator, func) c = inputconst(lltype.typeOf(ptr), ptr) self.db.prepare_repr_arg(c) assert c in self.db.obj2node + self.db.setup_all() self.entrynode = self.db.obj2node[c] codewriter = CodeWriter() Modified: pypy/dist/pypy/translator/llvm2/module/extfunction.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/module/extfunction.py (original) +++ pypy/dist/pypy/translator/llvm2/module/extfunction.py Sat Jul 30 01:24:55 2005 @@ -6,8 +6,10 @@ %structtype.rpy_string = type {int, {int, [0 x sbyte]}} ;exception handling globals -%last_exception_type = global long 0 -%last_exception_value = global long 0 +%last_exception_type = global sbyte* null +%last_exception_value = global sbyte* null +;%last_exception_type = global %structtype.object_vtable* null +;%last_exception_value = global %structtype.object* null """ gc_boehm = """declare sbyte* %GC_malloc(uint) Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 01:24:55 2005 @@ -191,9 +191,9 @@ argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) - none_label = self.node.block_to_name[link.target] - exc_label = self.node.block_to_name[self.block] + '_exception' - exc_error_label = exc_label + '_error' + none_label = self.node.block_to_name[link.target] + block_label = self.node.block_to_name[self.block] + exc_label = block_label + '_exception_handling' if returntype != "void": self.codewriter.invoke(targetvar, returntype, functionref, argrefs, @@ -201,56 +201,42 @@ else: self.codewriter.invoke_void(functionref, argrefs, argtypes, none_label, exc_label) - self.codewriter.label(exc_label) - value_label = [] - value = 0 - for link in self.block.exits[1:]: - assert issubclass(link.exitcase, Exception) + e = self.db._translator.rtyper.getexceptiondata() + ll_exception_match = '%' + e.ll_exception_match.__name__ + lltype_of_exception_type = '%structtype.' + e.lltype_of_exception_type.TO.__name__ + '*' - target = self.node.block_to_name[link.target] - value_label.append( (value,target) ) - value += 1 - - #msg = 'XXX Exception target=%s, exitcase=%s, last_exception.concretetype=%s' % \ - # (str(target), str(link.exitcase), link.last_exception.concretetype) - #self.codewriter.comment(msg) - #self.codewriter.comment('TODO: in %s rename %s to %s' % (target, self.node.block_to_name[self.block], exc_label)) + tmptype1, tmpvar1 = 'sbyte*', self.db.repr_tmpvar() + tmptype2, tmpvar2 = lltype_of_exception_type, self.db.repr_tmpvar() - tmptype1, tmpvar1 = 'long' , self.db.repr_tmpvar() + self.codewriter.label(exc_label) self.codewriter.load(tmpvar1, tmptype1, '%last_exception_type') + self.codewriter.cast(tmpvar2, tmptype1, tmpvar1, tmptype2) + self.codewriter.newline() - #tmptype2, tmpvar2 = '%structtype.object_vtable*', self.db.repr_tmpvar() - #self.codewriter.cast(tmpvar2, tmptype1, tmpvar1, tmptype2) - #self.codewriter.switch(tmptype2, tmpvar2, exc_error_label, value_label) - - #XXX get helper function name - exceptiondata = self.db._translator.rtyper.getexceptiondata() - - #functions - ll_exception_match = exceptiondata.ll_exception_match.__name__ - #yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) - #yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) - #yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) - #yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) - - #datatypes - lltype_of_exception_type = 'structtype.' + exceptiondata.lltype_of_exception_type.TO.__name__ - lltype_of_exception_value = 'structtype.' + exceptiondata.lltype_of_exception_value.TO.__name__ - #yield ('RPYTHON_EXCEPTION_VTABLE', exceptiondata.lltype_of_exception_type) - #yield ('RPYTHON_EXCEPTION', exceptiondata.lltype_of_exception_value) + exc_found_labels = [] + for link in self.block.exits[1:]: + assert issubclass(link.exitcase, Exception) - self.codewriter.newline() - self.codewriter.comment('HERE') - self.codewriter.comment(ll_exception_match) #ll_issubclass__object_vtablePtr_object_vtablePtr - self.codewriter.comment(lltype_of_exception_type) # - self.codewriter.comment(lltype_of_exception_value) # - self.codewriter.newline() + etype = self.db.obj2node[link.llexitcase._obj] - self.codewriter.switch(tmptype1, tmpvar1, exc_error_label, value_label) - self.codewriter.label(exc_error_label) - self.codewriter.comment('dead code ahead') - self.codewriter.ret('int', '0') - #self.codewriter.unwind() #this causes llvm to crash?!? + target = self.node.block_to_name[link.target] + exc_found_label = block_label + '_exception_found_branchto_' + target + exc_found_labels.append( (exc_found_label, target) ) + + not_this_exception_label = block_label + '_not_exception_' + etype.ref[1:] + + ll_issubclass_cond = self.db.repr_tmpvar() + self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, + [etype.ref, tmpvar2], [lltype_of_exception_type, lltype_of_exception_type]) + self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) + self.codewriter.label(not_this_exception_label) + + self.codewriter.comment('this code should never be reached!') + self.codewriter.unwind() + #self.codewriter.br_uncond(none_label) + for label, target in exc_found_labels: + self.codewriter.label(label) + self.codewriter.br_uncond(target) def malloc(self, op): targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sat Jul 30 01:24:55 2005 @@ -11,7 +11,7 @@ self.n = n def test_simple1(): - py.test.skip("not working yet") + #py.test.skip("not working yet") def raise_(i): if i: raise TestException() @@ -30,7 +30,7 @@ assert f(1) == fn(1) def test_simple2(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -44,7 +44,7 @@ assert f(10) == fn(10) def test_simple3(): - py.test.skip("not working yet") + #py.test.skip("not working yet") def raise_(i): if i == 0: raise TestException() @@ -71,6 +71,7 @@ assert f(2) == fn(2) def test_pass_exc(): + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -95,7 +96,7 @@ assert f(0) == fn(0) def test_reraise1(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -109,7 +110,7 @@ assert f(10) == fn(10) def test_reraise2(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -123,7 +124,7 @@ assert f(10) == fn(10) def test_simple_exception(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -138,7 +139,7 @@ assert f(i) == fn(i) def test_two_exceptions(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: @@ -155,7 +156,7 @@ assert f(i) == fn(i) def test_catch_base_exception(): - py.test.skip("not working yet") + py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: From hpk at codespeak.net Sat Jul 30 10:41:25 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 10:41:25 +0200 (CEST) Subject: [pypy-svn] r15398 - pypy/extradoc/sprintinfo Message-ID: <20050730084125.E047727B58@code1.codespeak.net> Author: hpk Date: Sat Jul 30 10:41:23 2005 New Revision: 15398 Added: pypy/extradoc/sprintinfo/heidelberg-people.txt (contents, props changed) Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Log: some more info regarding the heidelberg sprint and also a first list of people supposed to come. Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Heidelberg-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Sat Jul 30 10:41:23 2005 @@ -1,14 +1,15 @@ PyPy Sprint in Heidelberg 22nd - 29th August 2005 ================================================== -The next PyPy sprint is scheduled for end of August in -Heidelberg, Germany. Its main focus is to translate the whole -PyPy interpreter to a low level language. To learn more -about the new PyPy Python-in-Python implementation look here: +The next PyPy sprint will take place at the Heidelberg University +in Germany from 22nd August to 29th August (both days included). +Its main focus is translation of the whole PyPy interpreter +to a low level language and reaching 2.4.1 Python compliancy. +To learn more about the new PyPy Python implementation +look here: http://codespeak.net/pypy - Goals and topics of the sprint ------------------------------ @@ -56,7 +57,13 @@ Please subscribe to the `PyPy sprint mailing list`_, introduce yourself and post a note that you want to come. Feel free -to ask any questions there! +to ask any questions there! There also is a separate +`Heidelberg people`_ page tracking who is already thought +to come. If you have commit rights on codespeak then +you can modify yourself a checkout of + + http://codespeak.net/svn/pypy/extradoc/sprintinfo/heidelberg-people.txt +.. _`Heidelberg people`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/heidelberg-people.html .. _`PyPy sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint Added: pypy/extradoc/sprintinfo/heidelberg-people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/heidelberg-people.txt Sat Jul 30 10:41:23 2005 @@ -0,0 +1,28 @@ + +.. _`Heidelberg Sprint`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/Heidelberg-sprint.html + +People coming to the `Heidelberg Sprint`_ +================================================== + +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 +=================== ============== ===================== +Armin Rigo 21st-29th Aug ? +Samuele Pedroni 21st-29th Aug ? +Carl Friedrich Bolz 21st-29th Aug ? +Niklaus Haldimann ? private +Eric van Riet Paap ? probably private +Holger Krekel 21st-29th Aug private +Richard Emslie 21st-29th Aug private +Michael Hudson (?) ? ? +Beatrice Duering ? ? +Jacob Hallen ? ? +Laura Creighton ? ? +Ludovic Aubry ? ? +Anders Chrigstroem ? ? +Christian Tismer 21st-29th ? +=================== ============== ===================== From hpk at codespeak.net Sat Jul 30 10:48:50 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 10:48:50 +0200 (CEST) Subject: [pypy-svn] r15399 - pypy/dist/pypy/documentation/website Message-ID: <20050730084850.C4E9527B64@code1.codespeak.net> Author: hpk Date: Sat Jul 30 10:48:50 2005 New Revision: 15399 Modified: pypy/dist/pypy/documentation/website/news.txt Log: update hildesheim2 news item Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sat Jul 30 10:48:50 2005 @@ -13,16 +13,19 @@ ====================================================== Up until 31st August we are in a PyPy sprint at `Trillke-Gut`_. -Carl has written a `report about day 1`_ and Holger -about `day 2 and day 3`_ including some `pictures from the sprint`_. +Carl has written a `report about day 1`_, Holger +about `day 2 and day 3`_ and Carl again about `day 4 and day 5`_. +We also have some `pictures from the sprint`_. There has been some great progress already in that we now succeed to fully annotate the PyPy code base and have a mode where we don't borrow object implementations from CPython anymore (which of course means that we have some modules missing). -Stay tuned. +Moreover, there are almost no direct annotation and RTyping +problems remaining. Stay tuned. .. _`report about day 1`: http://codespeak.net/pipermail/pypy-dev/2005q3/002217.html .. _`day 2 and day 3`: http://codespeak.net/pipermail/pypy-dev/2005q3/002220.html +.. _`day 4 and day 5`: http://codespeak.net/pipermail/pypy-dev/2005q3/002234.html .. _`pictures from the sprint`: http://codespeak.net/~hpk/hildesheim2-sprint-www/ .. _`Trillke-Gut`: http://www.trillke.net/images/HomePagePictureSmall.jpg From cfbolz at codespeak.net Sat Jul 30 11:18:57 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 11:18:57 +0200 (CEST) Subject: [pypy-svn] r15400 - in pypy/dist/pypy/rpython: . test Message-ID: <20050730091857.2474E27B5D@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 11:18:54 2005 New Revision: 15400 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (arigo, cfbolz): changed slicing so that slice stop bigger that the length of the list/string is possible. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jul 30 11:18:54 2005 @@ -515,6 +515,8 @@ def ll_listslice(l1, slice): start = slice.start stop = slice.stop + if stop > len(l1.items): + stop = len(l1.items) newitems = malloc(typeOf(l1).TO.items.TO, stop - start) j = 0 while start < stop: @@ -548,6 +550,8 @@ def ll_listdelslice(l1, slice): start = slice.start stop = slice.stop + if stop > len(l1.items): + stop = len(l1.items) newlength = len(l1.items) - (stop-start) newitems = malloc(typeOf(l1).TO.items.TO, newlength) j = 0 Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 30 11:18:54 2005 @@ -793,6 +793,8 @@ 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: Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sat Jul 30 11:18:54 2005 @@ -63,7 +63,7 @@ check_list(ll_listslice_startonly(l, 3), [45]) check_list(ll_listslice_startonly(l, 4), []) for start in range(5): - for stop in range(start, 5): + for stop in range(start, 8): s = ll_newslice(start, stop) check_list(ll_listslice(l, s), [42, 43, 44, 45][start:stop]) @@ -74,7 +74,7 @@ ll_listdelslice_startonly(l, 0) check_list(l, []) for start in range(5): - for stop in range(start, 5): + for stop in range(start, 8): l = sample_list() s = ll_newslice(start, stop) ll_listdelslice(l, s) 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 Jul 30 11:18:54 2005 @@ -303,7 +303,8 @@ s = 'hello' s1 = s[:3] s2 = s[3:] - return s1+s2 == s and s2+s1 == 'lohel' + s3 = s[3:10] + return s1+s2 == s and s2+s1 == 'lohel' and s1+s3 == s res = interpret(fn, ()) assert res From ericvrp at codespeak.net Sat Jul 30 11:45:08 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 30 Jul 2005 11:45:08 +0200 (CEST) Subject: [pypy-svn] r15401 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730094508.11A5B27B5D@code1.codespeak.net> Author: ericvrp Date: Sat Jul 30 11:45:07 2005 New Revision: 15401 Modified: pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: fixed: issubclass call parameters in wrong order Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 11:45:07 2005 @@ -227,7 +227,7 @@ ll_issubclass_cond = self.db.repr_tmpvar() self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, - [etype.ref, tmpvar2], [lltype_of_exception_type, lltype_of_exception_type]) + [tmpvar2, etype.ref], [lltype_of_exception_type, lltype_of_exception_type]) self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) self.codewriter.label(not_this_exception_label) Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sat Jul 30 11:45:07 2005 @@ -10,6 +10,13 @@ def __init__(self, n): self.n = n +def getitem(l, i): #LookupError, KeyError + if i < 0: + i = len(l) - i + if i>= len(l): + raise IndexError + return l[i] + def test_simple1(): #py.test.skip("not working yet") def raise_(i): @@ -30,11 +37,12 @@ assert f(1) == fn(1) def test_simple2(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") + py.test.skip('failing') def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except: return 2 return 4 @@ -71,11 +79,12 @@ assert f(2) == fn(2) def test_pass_exc(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") + py.test.skip('failing') def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except: pass return 4 @@ -96,11 +105,12 @@ assert f(0) == fn(0) def test_reraise1(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") + py.test.skip('failing') def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except: raise return 4 @@ -110,11 +120,12 @@ assert f(10) == fn(10) def test_reraise2(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") + py.test.skip('failing') def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except e: raise e return 4 @@ -124,11 +135,11 @@ assert f(10) == fn(10) def test_simple_exception(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except IndexError: return 2 return 4 @@ -139,11 +150,12 @@ assert f(i) == fn(i) def test_two_exceptions(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") + py.test.skip('failing') def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except IndexError: return 2 except KeyError: @@ -156,11 +168,11 @@ assert f(i) == fn(i) def test_catch_base_exception(): - py.test.skip("not working yet, lst[n] raises no exceptions") + #py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) try: - lst[n] + getitem(lst,n) except LookupError: return 2 return 4 From hpk at codespeak.net Sat Jul 30 12:38:52 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 12:38:52 +0200 (CEST) Subject: [pypy-svn] r15402 - pypy/extradoc/sprintinfo Message-ID: <20050730103852.4CE9127B68@code1.codespeak.net> Author: hpk Date: Sat Jul 30 12:38:51 2005 New Revision: 15402 Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt pypy/extradoc/sprintinfo/hildesheim2-done.txt pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: some today sprint-planning and people update Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/heidelberg-people.txt (original) +++ pypy/extradoc/sprintinfo/heidelberg-people.txt Sat Jul 30 12:38:51 2005 @@ -12,17 +12,17 @@ Name Arrive/Depart Accomodation =================== ============== ===================== Armin Rigo 21st-29th Aug ? -Samuele Pedroni 21st-29th Aug ? +Samuele Pedroni ?21st-29th Aug ? Carl Friedrich Bolz 21st-29th Aug ? Niklaus Haldimann ? private Eric van Riet Paap ? probably private Holger Krekel 21st-29th Aug private -Richard Emslie 21st-29th Aug private +Richard Emslie 22nd-29th Aug private Michael Hudson (?) ? ? Beatrice Duering ? ? Jacob Hallen ? ? Laura Creighton ? ? Ludovic Aubry ? ? Anders Chrigstroem ? ? -Christian Tismer 21st-29th ? +Christian Tismer ? ? =================== ============== ===================== Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-done.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-done.txt Sat Jul 30 12:38:51 2005 @@ -125,3 +125,25 @@ - DONE extend the testing framework to allow to specify a space with options for a test. Related to the latter. +Remaining problem about pyc files:: + + DONE (could be better) The inconsistency problems are more or less solved now, + but PYC file support is disabled at the moment because + it is just too slow in general. + + Bootstrapping is right but messy. Christian will rewrite + marshal at interp-level at some point. + + We won't use PYC file support for translate_pypy anyway. + We will construct and initialize the object space just like now, + and then import at app-level the 'compiler' package, and finally + patch the executioncontext.compiler to use this 'compiler' + package. The resulting object space is what translate_pypy is + seeing. + + Ultimately the compiler and marshal should both be at + interp-level anyway. + + - DONE bug to be fixed: applevel test stdout is no longer + captured. + Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Sat Jul 30 12:38:51 2005 @@ -35,47 +35,71 @@ Current Main task: RTYPER issues ----------------------------------- -Remaining problem about pyc files:: - - The inconsistency problems are more or less solved now, - but PYC file support is disabled at the moment because - it is just too slow in general. - - Bootstrapping is right but messy. Christian will rewrite - marshal at interp-level at some point. - - We won't use PYC file support for translate_pypy anyway. - We will construct and initialize the object space just like now, - and then import at app-level the 'compiler' package, and finally - patch the executioncontext.compiler to use this 'compiler' - package. The resulting object space is what translate_pypy is - seeing. - - Ultimately the compiler and marshal should both be at - interp-level anyway. - - Left:: - - DONE bug to be fixed: applevel test stdout is no longer - captured. - - running translate_pypy! - - finish and polish and test our own posix module + - (Armin, Holger) add a compiling option to the C backend that allows to + generate a standalone binary (as opposed to a Python extension module) - - try to plug in niklaus' sre implementation + - (Armin, Holger) likely we have a possibly deep exception handling problem: + implicitely exceptions are attached to the last (high level) + operation in a block but when the RTyper converts this operation + into possibly many low-level operations then it's unlikely + that we can preserve the implicit assumption that only + the last (low-level) operation possibly raises an exception. + + solution: unknown at this point. + + maybe describe a few scenarios regarding exception handling + describing the interactions/processing of exceptions in + flowobjspace/annotation/rtyping + + - (Holger, X) try to extend test framework a bit to make applevel + tests allow to use 'self.somevalue' coming from interplevel 'self.w_somevalue'. + - (Holger, X) finish and polish and test our own posix module + + - (Carl, Samuele) finish/send out the Heidelberg sprint announcement + goals: do the 0.7 release! + (0.7 is meant as a first self-contained pypy release + with quite some c-extension modules missing (everything + below 1.0 is implicitly alpha'ed or XXXed or both) + + - translation efforts + - work on 2.4.1 compliancy (let's have a lib-python/ISSUE.txt well + before the sprint and let's try to count by failing tests not + failing test files) + - rewriting c-extension modules/integrating existing rewrites + - all kinds of small release issues + - possibly some more LLVM efforts + + - (Armin ...) integrate Niklaus's applevel _sre module as a mixed module + (so that you can switch it in via usemodules=_sre). This may + also ease moving gradually to an interplevel implementation. + + pypy/module/_sre/ + full_sre_project/ # with manifest and so on + conftest.py # don't recurse into full_sre_project (unless the unittests + are converted to py.test) + __init__.py: (appleveldefs -> full_sre_projec/...) + Armin is going to ask niklaus about his plans and + suggest something along these lines. - - write an answer eMail/FAQ entry + - (tracker ->) write a FAQ entry about "what and why is rpython?") - - finally start with garbage collection (CF) + - (Carl, Samuele) finally start with garbage collection (CF) - investigate the possibility of translating the interactive part of PyPy or alternatively (probably preferably) running it completely at applevel - - working on LLVM (need to contact Eric on LLVM) - - - rewriting the marshal module on interplevel + - (Richard, with Armin's throwing-examples help) let llvm support + varsize structs and possibly refactor/cleanup a bit the current + code (richard already contacted Eric and also worked a bit on improving + PBC support for llvm) + + - (Christian, Samuele) rewriting the marshal module on interplevel (mostly + done but there are difficult dependencies on the applevel _codecs.py + and some builtins (like frozenset) that live at applevel) Pairing From hpk at codespeak.net Sat Jul 30 12:42:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 12:42:43 +0200 (CEST) Subject: [pypy-svn] r15403 - pypy/extradoc/sprintinfo Message-ID: <20050730104243.A8C2C27B68@code1.codespeak.net> Author: hpk Date: Sat Jul 30 12:42:43 2005 New Revision: 15403 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: pairing info is actually inlined Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Sat Jul 30 12:42:43 2005 @@ -102,18 +102,3 @@ and some builtins (like frozenset) that live at applevel) -Pairing -------- - -basically everyone should keep an eye on targetpypymain, in the meantime -working on a subtask.. - - - samuele, carl friedrich: garbage collection - - - richard: plugin in sre - - - christian: rewriting marshal - - - DONE armin, holger: applevel stdout - - - armin: write nik mail, fix the entrypoint From cfbolz at codespeak.net Sat Jul 30 12:53:00 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 12:53:00 +0200 (CEST) Subject: [pypy-svn] r15404 - pypy/extradoc/sprintinfo Message-ID: <20050730105300.A303527B68@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 12:52:59 2005 New Revision: 15404 Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Log: finialized sprint announcement Modified: pypy/extradoc/sprintinfo/Heidelberg-sprint.txt ============================================================================== --- pypy/extradoc/sprintinfo/Heidelberg-sprint.txt (original) +++ pypy/extradoc/sprintinfo/Heidelberg-sprint.txt Sat Jul 30 12:52:59 2005 @@ -10,11 +10,24 @@ http://codespeak.net/pypy + Goals and topics of the sprint ------------------------------ -XXX The focus will probably be translation issues, -possibly including garbage collection and threading (?). +One of the main goals of the sprint is going to be a 0.7 release of PyPy. The +0.7 is meant to be the first self-contained PyPy version but still alpha with +some C-extension modules missing and not meant for production use. + +Therefore the topics of the sprint will be: + + - translation efforts: it's not completely clear now what related task will + be left at that time + - work on 2.4.1 compliancy: there are some failing compliancy tests on + which we plan to work + - rewriting c-extension modules/integrating existing rewrites + - all kinds of small release issues + - possibly some more LLVM efforts + Location & Accomodation ------------------------ @@ -28,8 +41,7 @@ unfortunately rather expensive. It should be no problem to reach the sprint venue from anywhere in Heidelberg. As an alternative you could also take a `hotel in Mannheim`_ which you can reach in 15 min from Heidelberg with the -train. If there is enough interest Carl could try to rent a room in a living -group (WG). +train. .. _`See here`: http://www.physi.uni-heidelberg.de/physi/front/anfahrt.en.php .. _hotels: http://www.cvb-heidelberg.de/index_eng.html @@ -49,7 +61,8 @@ The Heidelberg Altstadt can be reached in approximately 10 min from the sprint venue. There you will find all kinds of restaurants and fast food places. -You need a wireless network card to access the network. +You will probably need a wireless network card to access the network although we +could set up a WLAN to cable bridge if necessary. Registration etc.pp. From hpk at codespeak.net Sat Jul 30 12:54:45 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 12:54:45 +0200 (CEST) Subject: [pypy-svn] r15405 - in pypy/dist/pypy: module/__builtin__/test module/__builtin__/test/impsubdir/compiled module/_codecs/test module/posix/test translator/goal translator/llvm2/module Message-ID: <20050730105445.911C127B64@code1.codespeak.net> Author: hpk Date: Sat Jul 30 12:54:42 2005 New Revision: 15405 Modified: pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/ (props changed) pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/__init__.py (props changed) pypy/dist/pypy/module/__builtin__/test/impsubdir/compiled/x.py (props changed) pypy/dist/pypy/module/__builtin__/test/test_buffer.py (props changed) pypy/dist/pypy/module/_codecs/test/ (props changed) pypy/dist/pypy/module/_codecs/test/__init__.py (props changed) pypy/dist/pypy/module/_codecs/test/autopath.py (props changed) pypy/dist/pypy/module/_codecs/test/test_codecs.py (props changed) pypy/dist/pypy/module/posix/test/test_posix2.py (props changed) pypy/dist/pypy/translator/goal/targetsegfault.py (props changed) pypy/dist/pypy/translator/llvm2/module/ll_math.py (props changed) pypy/dist/pypy/translator/llvm2/module/ll_os.py (props changed) pypy/dist/pypy/translator/llvm2/module/ll_os_path.py (props changed) pypy/dist/pypy/translator/llvm2/module/ll_time.py (props changed) pypy/dist/pypy/translator/llvm2/module/support.py (props changed) Log: FIXEOL From cfbolz at codespeak.net Sat Jul 30 12:55:15 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 12:55:15 +0200 (CEST) Subject: [pypy-svn] r15406 - pypy/dist/pypy/documentation/website Message-ID: <20050730105515.74E5F27B64@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 12:55:14 2005 New Revision: 15406 Modified: pypy/dist/pypy/documentation/website/news.txt Log: added news item about the upcoming Heidelberg sprint Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sat Jul 30 12:55:14 2005 @@ -9,6 +9,20 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: ../architecture.html#mission-statement +Heidelberg sprint planning +=========================== + +The next PyPy sprint will take place at the Heidelberg University +in Germany from 22nd August to 29th August (both days included). +Its main focus is translation of the whole PyPy interpreter +to a low level language and reaching 2.4.1 Python compliancy. +To learn more see the `Heidelberg sprint announcement`_ or look at +the list of people_ that are expected to come + +.. _people: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/heidelberg-people.html +.. _`Heidelberg sprint announcement`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/Heidelberg-sprint.html + + PyPy Hildesheim2 sprint ongoing ... ====================================================== From cfbolz at codespeak.net Sat Jul 30 12:59:44 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 12:59:44 +0200 (CEST) Subject: [pypy-svn] r15407 - pypy/dist/pypy/documentation/website Message-ID: <20050730105944.AC25C27B64@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 12:59:43 2005 New Revision: 15407 Modified: pypy/dist/pypy/documentation/website/news.txt Log: fixed the news item. Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sat Jul 30 12:59:43 2005 @@ -15,9 +15,10 @@ The next PyPy sprint will take place at the Heidelberg University in Germany from 22nd August to 29th August (both days included). Its main focus is translation of the whole PyPy interpreter -to a low level language and reaching 2.4.1 Python compliancy. +to a low level language and reaching 2.4.1 Python compliancy. +The goal of the sprint is to release a first self-contained PyPy-0.7 version. To learn more see the `Heidelberg sprint announcement`_ or look at -the list of people_ that are expected to come +the list of people_ that are expected to come. .. _people: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/heidelberg-people.html .. _`Heidelberg sprint announcement`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/Heidelberg-sprint.html From cfbolz at codespeak.net Sat Jul 30 13:04:00 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 13:04:00 +0200 (CEST) Subject: [pypy-svn] r15408 - pypy/extradoc/sprintinfo Message-ID: <20050730110400.1998927B68@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 13:03:59 2005 New Revision: 15408 Added: pypy/extradoc/sprintinfo/conftest.py - copied unchanged from r15387, pypy/dist/pypy/documentation/conftest.py Log: added rest-checking conftest file to the sprintinfo dir. From cfbolz at codespeak.net Sat Jul 30 13:27:51 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 13:27:51 +0200 (CEST) Subject: [pypy-svn] r15409 - pypy/extradoc/sprintinfo Message-ID: <20050730112751.6894527B75@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 13:27:50 2005 New Revision: 15409 Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt Log: niklaus mailed me that he planned to come for the whole time. Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/heidelberg-people.txt (original) +++ pypy/extradoc/sprintinfo/heidelberg-people.txt Sat Jul 30 13:27:50 2005 @@ -14,7 +14,7 @@ Armin Rigo 21st-29th Aug ? Samuele Pedroni ?21st-29th Aug ? Carl Friedrich Bolz 21st-29th Aug ? -Niklaus Haldimann ? private +Niklaus Haldimann 21st-29th Aug private Eric van Riet Paap ? probably private Holger Krekel 21st-29th Aug private Richard Emslie 22nd-29th Aug private From hpk at codespeak.net Sat Jul 30 13:36:55 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 13:36:55 +0200 (CEST) Subject: [pypy-svn] r15410 - in pypy/dist/pypy: . tool/test Message-ID: <20050730113655.64C8827B61@code1.codespeak.net> Author: hpk Date: Sat Jul 30 13:36:54 2005 New Revision: 15410 Modified: pypy/dist/pypy/conftest.py pypy/dist/pypy/tool/test/test_pytestsupport.py Log: (hpk,arigo) added support for sending values from setup_* functions in applevelclass-tests to the actual applevel test methods. See the added test for an example. Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Sat Jul 30 13:36:54 2005 @@ -156,11 +156,23 @@ self.execute_appex(space, func, space) class AppTestMethod(PyPyTestFunction): + + def setup(self): + super(AppTestMethod, self).setup() + instance = self.parent.obj + w_instance = self.parent.w_instance + space = instance.space + for name in dir(instance): + if name.startswith('w_'): + space.setattr(w_instance, space.wrap(name[2:]), + getattr(instance, name)) + def execute(self, target, *args): assert not args space = target.im_self.space func = app2interp_temp(target.im_func) - self.execute_appex(space, func, space, space.w_None) + w_instance = self.parent.w_instance + self.execute_appex(space, func, space, w_instance) class IntClassCollector(py.test.collect.Class): Function = IntTestFunction @@ -173,6 +185,23 @@ class AppClassInstance(py.test.collect.Instance): Function = AppTestMethod + def setup(self): + super(AppClassInstance, self).setup() + instance = self.obj + space = instance.space + w_class = self.parent.w_class + self.w_instance = space.call_function(w_class) + class AppClassCollector(IntClassCollector): Instance = AppClassInstance + def setup(self): + super(AppClassCollector, self).setup() + cls = self.obj + space = cls.space + clsname = cls.__name__ + w_class = space.call_function(space.w_type, + space.wrap(clsname), + space.newtuple([]), + space.newdict([])) + self.w_class = w_class Modified: pypy/dist/pypy/tool/test/test_pytestsupport.py ============================================================================== --- pypy/dist/pypy/tool/test/test_pytestsupport.py (original) +++ pypy/dist/pypy/tool/test/test_pytestsupport.py Sat Jul 30 13:36:54 2005 @@ -68,4 +68,18 @@ pass assert not appex.errisinstance(A) - + +class AppTestWithWrappedInterplevelAttributes: + def setup_class(cls): + space = cls.space + cls.w_some1 = space.wrap(42) + + def setup_method(self, meth): + self.w_some2 = self.space.wrap(23) + + def test_values_arrive(self): + assert self.some1 == 42 + assert self.some2 == 23 + + def test_values_arrive2(self): + assert self.some1 == 42 From hpk at codespeak.net Sat Jul 30 13:42:27 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 13:42:27 +0200 (CEST) Subject: [pypy-svn] r15411 - pypy/dist/pypy/module/posix/test Message-ID: <20050730114227.CF54427B61@code1.codespeak.net> Author: hpk Date: Sat Jul 30 13:42:27 2005 New Revision: 15411 Modified: pypy/dist/pypy/module/posix/test/test_posix2.py Log: refactor the test after the new interp/app test interactions possibility Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Sat Jul 30 13:42:27 2005 @@ -9,15 +9,15 @@ class AppTestPosix: def setup_class(cls): cls.space = space + cls.w_posix = space.appexec([], "(): import posix ; return posix") + cls.w_path = space.wrap(str(path)) def test_posix_is_pypy_s(self): - import posix - assert posix.__file__ + assert self.posix.__file__ -def test_some_posix_basic_operation(): - w_path = space.wrap(str(path)) - space.appexec([w_path], """(path): - import posix + def test_some_posix_basic_operation(self): + path = self.path + posix = self.posix fd = posix.open(path, posix.O_RDONLY, 0777) fd2 = posix.dup(fd) assert not posix.isatty(fd2) @@ -30,4 +30,3 @@ assert stat # XXX posix.close(fd2) posix.close(fd) - """) From cfbolz at codespeak.net Sat Jul 30 13:49:38 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 13:49:38 +0200 (CEST) Subject: [pypy-svn] r15412 - pypy/extradoc/sprintinfo Message-ID: <20050730114938.9583427B6A@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 13:49:37 2005 New Revision: 15412 Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: added issues to tracker. Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Sat Jul 30 13:49:37 2005 @@ -27,11 +27,6 @@ Misc -------- -* -> TRACKER: (mostly done?) add missing docstrings on - app-level built-in types and functions, etc. (Laura): there - now is a program that generates the docstrings into the - appropriate places but it needs prettification. (christian) - Current Main task: RTYPER issues ----------------------------------- @@ -85,8 +80,6 @@ Armin is going to ask niklaus about his plans and suggest something along these lines. - - (tracker ->) write a FAQ entry about "what and why is rpython?") - - (Carl, Samuele) finally start with garbage collection (CF) - investigate the possibility of translating the interactive part of PyPy From arigo at codespeak.net Sat Jul 30 14:04:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Jul 2005 14:04:42 +0200 (CEST) Subject: [pypy-svn] r15413 - in pypy/dist/pypy/translator/c: src test Message-ID: <20050730120442.2624F27B64@code1.codespeak.net> Author: arigo Date: Sat Jul 30 14:04:40 2005 New Revision: 15413 Modified: pypy/dist/pypy/translator/c/src/int.h pypy/dist/pypy/translator/c/test/test_typed.py Log: Well, we really need / and % on r_uint. 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 Sat Jul 30 14:04:40 2005 @@ -105,7 +105,7 @@ /* floor division */ #define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); -#define OP_UINT_FLOORDIV(x,y,r,err) & Is_Unsigned_Division_Really_Useful; +#define OP_UINT_FLOORDIV(x,y,r,err) r = (x) / (y); #define OP_INT_FLOORDIV_OVF(x,y,r,err) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -115,7 +115,9 @@ #define OP_INT_FLOORDIV_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ else FAIL_ZER(err, "integer division") -#define OP_UINT_FLOORDIV_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; +#define OP_UINT_FLOORDIV_ZER(x,y,r,err) \ + if ((y)) { OP_UINT_FLOORDIV(x,y,r,err) } \ + else FAIL_ZER(err, "unsigned integer division") #define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ @@ -124,7 +126,7 @@ /* modulus */ #define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); -#define OP_UINT_MOD(x,y,r,err) & Is_Unsigned_Division_Really_Useful; +#define OP_UINT_MOD(x,y,r,err) r = (x) % (y); #define OP_INT_MOD_OVF(x,y,r,err) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -134,7 +136,9 @@ #define OP_INT_MOD_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") -#define OP_UINT_MOD_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; +#define OP_UINT_MOD_ZER(x,y,r,err) \ + if ((y)) { OP_UINT_MOD(x,y,r,err) } \ + else FAIL_ZER(err, "unsigned integer modulo") #define OP_INT_MOD_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sat Jul 30 14:04:40 2005 @@ -4,6 +4,7 @@ from pypy.translator.translator import Translator from pypy.translator.test import snippet from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.rpython.rarithmetic import r_uint from pypy.translator.c.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase @@ -294,3 +295,13 @@ f = self.getcompiled(fn) assert f(1.0) == fn(1.0) + def test_uint_arith(self): + def fn(i=r_uint): + try: + return ~(i*(i+1))/(i-1) + except ZeroDivisionError: + return r_uint(91872331) + f = self.getcompiled(fn) + for value in range(15): + i = r_uint(value) + assert f(i) == fn(i) From arigo at codespeak.net Sat Jul 30 14:23:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Jul 2005 14:23:32 +0200 (CEST) Subject: [pypy-svn] r15414 - pypy/dist/pypy/translator/c Message-ID: <20050730122332.9C83D27B6A@code1.codespeak.net> Author: arigo Date: Sat Jul 30 14:23:31 2005 New Revision: 15414 Modified: pypy/dist/pypy/translator/c/node.py Log: Forgot to forward-declare the deallocator for ArrayNodeDef. Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sat Jul 30 14:23:31 2005 @@ -217,6 +217,9 @@ line = '/* %s */' % line yield '\t' + line yield '};' + if self.deallocator: + yield 'void %s(struct %s *a);' % (self.deallocator, self.name) + elif phase == 2 and self.deallocator: yield 'void %s(struct %s *a) {' % (self.deallocator, self.name) for line in self.deallocator_lines('a->'): From hpk at codespeak.net Sat Jul 30 14:40:20 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 14:40:20 +0200 (CEST) Subject: [pypy-svn] r15415 - in pypy/dist/pypy/translator: . c c/test goal llvm2 pyrex/test test tool Message-ID: <20050730124020.0DDC427B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 14:40:15 2005 New Revision: 15415 Added: pypy/dist/pypy/translator/tool/cbuild.py - copied unchanged from r15414, pypy/dist/pypy/translator/tool/buildpyxmodule.py Removed: pypy/dist/pypy/translator/tool/buildpyxmodule.py Modified: pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/test/test_annotated.py pypy/dist/pypy/translator/c/test/test_backendoptimized.py pypy/dist/pypy/translator/c/test/test_genc.py pypy/dist/pypy/translator/c/test/test_lltyped.py pypy/dist/pypy/translator/c/test/test_notype.py pypy/dist/pypy/translator/c/test/test_operation.py pypy/dist/pypy/translator/c/test/test_typed.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/llvm2/build_llvm_module.py pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py pypy/dist/pypy/translator/test/test_geninterp.py pypy/dist/pypy/translator/tool/benchmark.py pypy/dist/pypy/translator/translator.py Log: (hpk,arigo) rename buildpyxmodule to cbuild finally Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sat Jul 30 14:40:15 2005 @@ -4,7 +4,7 @@ from pypy.translator.c.database import LowLevelDatabase from pypy.translator.c.extfunc import pre_include_code_lines from pypy.translator.gensupp import uniquemodulename -from pypy.translator.tool.buildpyxmodule import make_module_from_c +from pypy.translator.tool.cbuild import make_module_from_c from pypy.rpython.lltype import pyobjectptr from pypy.tool.udir import udir Modified: pypy/dist/pypy/translator/c/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/c/test/test_annotated.py Sat Jul 30 14:40:15 2005 @@ -1,12 +1,12 @@ import autopath -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator from pypy.translator.test import snippet # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() class TestAnnotatedTestCase: Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_backendoptimized.py (original) +++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Sat Jul 30 14:40:15 2005 @@ -1,5 +1,5 @@ import autopath -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator from pypy.translator import backendoptimization Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Sat Jul 30 14:40:15 2005 @@ -7,14 +7,14 @@ from pypy.objspace.flow.model import Constant, Variable, SpaceOperation from pypy.objspace.flow.model import Block, Link, FunctionGraph from pypy.tool.udir import udir -from pypy.translator.tool.buildpyxmodule import make_module_from_c -from pypy.translator.tool.buildpyxmodule import enable_fast_compilation +from pypy.translator.tool.cbuild import make_module_from_c +from pypy.translator.tool.cbuild import enable_fast_compilation from pypy.translator.gensupp import uniquemodulename # XXX this tries to make compiling faster for full-scale testing # XXX tcc leaves some errors undetected! Bad! -#from pypy.translator.tool import buildpyxmodule -#buildpyxmodule.enable_fast_compilation() +#from pypy.translator.tool import cbuild +#cbuild.enable_fast_compilation() def compile_db(db): Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Sat Jul 30 14:40:15 2005 @@ -1,5 +1,5 @@ from pypy.rpython.lltype import * -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator from pypy.objspace.flow import FlowObjSpace Modified: pypy/dist/pypy/translator/c/test/test_notype.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_notype.py (original) +++ pypy/dist/pypy/translator/c/test/test_notype.py Sat Jul 30 14:40:15 2005 @@ -1,13 +1,13 @@ import autopath -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator from pypy.objspace.flow import FlowObjSpace from pypy.translator.test import snippet # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() class TestNoTypeCGenTestCase: def setup_class(cls): Modified: pypy/dist/pypy/translator/c/test/test_operation.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_operation.py (original) +++ pypy/dist/pypy/translator/c/test/test_operation.py Sat Jul 30 14:40:15 2005 @@ -2,12 +2,12 @@ from pypy.objspace.flow.model import * from pypy.objspace.flow.operation import FunctionByName from pypy.objspace.flow import FlowObjSpace -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() TESTCASES = [ Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sat Jul 30 14:40:15 2005 @@ -3,7 +3,7 @@ from py.test import raises from pypy.translator.translator import Translator from pypy.translator.test import snippet -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.rpython.rarithmetic import r_uint from pypy.translator.c.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sat Jul 30 14:40:15 2005 @@ -81,8 +81,8 @@ from pypy.rpython.error import TyperError # XXX this tries to make compiling faster -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() annmodel.DEBUG = False Modified: pypy/dist/pypy/translator/llvm2/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sat Jul 30 14:40:15 2005 @@ -8,7 +8,7 @@ from py import path import py -from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile +from pypy.translator.tool.cbuild import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture from pypy.translator.llvm2.genllvm import use_boehm_gc Modified: pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py (original) +++ pypy/dist/pypy/translator/pyrex/test/test_pyrextrans.py Sat Jul 30 14:40:15 2005 @@ -3,8 +3,8 @@ from pypy.tool.udir import udir from pypy.translator.pyrex.genpyrex import GenPyrex from pypy.objspace.flow.model import * -from pypy.translator.tool.buildpyxmodule import build_cfunc -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import build_cfunc +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.translator import Translator from pypy.objspace.flow import FlowObjSpace @@ -14,8 +14,8 @@ from pypy.translator.test import snippet # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() class TestNoTypePyrexGenTestCase: Modified: pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py (original) +++ pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py Sat Jul 30 14:40:15 2005 @@ -6,12 +6,12 @@ from pypy.translator.pyrex.genpyrex import GenPyrex from pypy.objspace.flow.model import * -from pypy.translator.tool.buildpyxmodule import make_module_from_pyxstring +from pypy.translator.tool.cbuild import make_module_from_pyxstring #from pypy.translator.test.make_dot import make_ps # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +from pypy.translator.tool import cbuild +cbuild.enable_fast_compilation() class TestSourceGenTestCase: Modified: pypy/dist/pypy/translator/test/test_geninterp.py ============================================================================== --- pypy/dist/pypy/translator/test/test_geninterp.py (original) +++ pypy/dist/pypy/translator/test/test_geninterp.py Sat Jul 30 14:40:15 2005 @@ -27,8 +27,8 @@ import py from pypy.tool.udir import udir from pypy.objspace.flow.model import * -from pypy.translator.tool.buildpyxmodule import make_module_from_c -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.tool.cbuild import make_module_from_c +from pypy.translator.tool.cbuild import skip_missing_compiler from pypy.translator.geninterplevel import translate_as_module from pypy.translator.test import snippet from pypy.interpreter.error import OperationError Modified: pypy/dist/pypy/translator/tool/benchmark.py ============================================================================== --- pypy/dist/pypy/translator/tool/benchmark.py (original) +++ pypy/dist/pypy/translator/tool/benchmark.py Sat Jul 30 14:40:15 2005 @@ -1,7 +1,7 @@ import autopath from pypy.tool import testit from pypy.tool.udir import udir -from pypy.translator.tool.buildpyxmodule import build_cfunc +from pypy.translator.tool.cbuild import build_cfunc from pypy.translator.test.test_cltrans import global_cl, make_cl_func def benchmark(func): Deleted: /pypy/dist/pypy/translator/tool/buildpyxmodule.py ============================================================================== --- /pypy/dist/pypy/translator/tool/buildpyxmodule.py Sat Jul 30 14:40:15 2005 +++ (empty file) @@ -1,222 +0,0 @@ -import autopath - -import py - -import os, sys, inspect, re -from pypy.translator.tool import stdoutcapture - -debug = 0 - -def make_module_from_pyxstring(name, dirpath, string): - dirpath = py.path.local(dirpath) - pyxfile = dirpath.join('%s.pyx' % name) - i = 0 - while pyxfile.check(): - pyxfile = pyxfile.new(basename='%s%d.pyx' % (name, i)) - i+=1 - pyxfile.write(string) - if debug: print "made pyxfile", pyxfile - cfile = make_c_from_pyxfile(pyxfile) - module = make_module_from_c(cfile) - #print "made module", module - return module - -def compiler_command(): - # e.g. for tcc, you might set this to - # "tcc -shared -o %s.so %s.c" - return os.getenv('PYPY_CC') - -def enable_fast_compilation(): - from distutils import sysconfig - gcv = sysconfig.get_config_vars() - opt = gcv.get('OPT') # not always existent - if opt: - opt = re.sub('-O\d+', '-O0', opt) - else: - opt = '-O0' - gcv['OPT'] = opt - -def make_module_from_c(cfile, include_dirs=None): - #try: - # from distutils.log import set_threshold - # set_threshold(10000) - #except ImportError: - # print "ERROR IMPORTING" - # pass - if include_dirs is None: - include_dirs = [] - - dirpath = cfile.dirpath() - lastdir = py.path.local() - os.chdir(str(dirpath)) - try: - modname = cfile.purebasename - if debug: print "modname", modname - c = stdoutcapture.Capture(mixed_out_err = True) - try: - try: - if compiler_command(): - # GCC-ish options only - from distutils import sysconfig - gcv = sysconfig.get_config_vars() - cmd = compiler_command().replace('%s', - str(dirpath.join(modname))) - for dir in [gcv['INCLUDEPY']] + list(include_dirs): - cmd += ' -I%s' % dir - os.system(cmd) - else: - from distutils.dist import Distribution - from distutils.extension import Extension - from distutils.ccompiler import get_default_compiler - saved_environ = os.environ.items() - try: - # distutils.core.setup() is really meant for end-user - # interactive usage, because it eats most exceptions and - # turn them into SystemExits. Instead, we directly - # instantiate a Distribution, which also allows us to - # ignore unwanted features like config files. - extra_compile_args = [] - if get_default_compiler() == 'unix': - old_version = False - try: - g = os.popen('gcc --version', 'r') - verinfo = g.read() - g.close() - except (OSError, IOError): - pass - else: - old_version = verinfo.startswith('2') - if not old_version: - extra_compile_args.extend(["-Wno-unused-label", - "-Wno-unused-variable"]) - attrs = { - 'name': "testmodule", - 'ext_modules': [ - Extension(modname, [str(cfile)], - include_dirs=include_dirs, - extra_compile_args=extra_compile_args) - ], - 'script_name': 'setup.py', - 'script_args': ['-q', 'build_ext', '--inplace'], - } - dist = Distribution(attrs) - if not dist.parse_command_line(): - raise ValueError, "distutils cmdline parse error" - dist.run_commands() - finally: - for key, value in saved_environ: - if os.environ.get(key) != value: - os.environ[key] = value - finally: - foutput, foutput = c.done() - data = foutput.read() - if data: - fdump = open("%s.errors" % modname, "w") - fdump.write(data) - fdump.close() - # XXX do we need to do some check on fout/ferr? - # XXX not a nice way to import a module - if debug: print "inserting path to sys.path", dirpath - sys.path.insert(0, '.') - if debug: print "import %(modname)s as testmodule" % locals() - exec "import %(modname)s as testmodule" % locals() - sys.path.pop(0) - except: - print data - raise - finally: - os.chdir(str(lastdir)) - #if not debug: - #dirpath.rmtree() - return testmodule - -def make_c_from_pyxfile(pyxfile): - from pypy.translator.pyrex import genpyrex - pyrexdir = os.path.dirname(genpyrex.__file__) - if pyrexdir not in sys.path: - sys.path.insert(0, pyrexdir) - from Pyrex.Compiler.Main import CompilationOptions, Context, PyrexError - try: - options = CompilationOptions(show_version = 0, - use_listing_file = 0, - c_only = 1, - output_file = None) - context = Context(options.include_path) - result = context.compile(str(pyxfile), options) - if result.num_errors > 0: - raise ValueError, "failure %s" % result - except PyrexError, e: - print >>sys.stderr, e - cfile = pyxfile.new(ext='.c') - return cfile - -def skip_missing_compiler(fn, *args, **kwds): - from distutils.errors import DistutilsPlatformError - try: - return fn(*args, **kwds) - except DistutilsPlatformError, e: - py.test.skip('DistutilsPlatformError: %s' % (e,)) - -def build_cfunc(func, simplify=1, dot=1, inputargtypes=None): - """ return a pyrex-generated cfunction from the given func. - - simplify is true -> perform simplifications on the flowgraph. - dot is true -> generate a dot-configuration file and postscript. - inputargtypes is a list (allowed to be empty) -> - then annotation will be performed before generating - dot/pyrex/c code. - - """ - try: func = func.im_func - except AttributeError: pass - - # build the flow graph - from pypy.objspace.flow import Space - from pypy.tool.udir import udir - space = Space() - name = func.func_name - funcgraph = space.build_flow(func) - - if not inputargtypes: - source = inspect.getsource(func) - base = udir.join(name).new(ext='.py').write(source) - - if dot: - from pypy.translator.tool.make_dot import FlowGraphDotGen - dotgen = FlowGraphDotGen(name) - dotgen.emit_subgraph(name, funcgraph) - - # apply transformations - if simplify: - from pypy.translator.simplify import simplify_graph - simplify_graph(funcgraph) - name += '_s' - - # get the pyrex generator - from pypy.translator.pyrex.genpyrex import GenPyrex - genpyrex = GenPyrex(funcgraph) - - # generate pyrex (without type inference) - - # apply type inference - if inputargtypes is not None: - genpyrex.annotate(inputargtypes) - name += '_t' - #a = Annotator(self.functiongraph) - #a.build_types(input_arg_types) - #a.simplify() - - pyxstring = genpyrex.emitcode() - #funcgraph.source = inspect.getsource(func) - else: - pyxstring = genpyrex.emitcode() - - pyxheader = genpyrex.globaldeclarations() - mod = make_module_from_pyxstring(name, udir, pyxheader + '\n' + pyxstring) - - if dot: - if name != func.func_name: # if some transformations have been done - dotgen.emit_subgraph(name, funcgraph) - dotgen.generate() - - return getattr(mod, func.func_name) Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Sat Jul 30 14:40:15 2005 @@ -9,8 +9,8 @@ from pypy.objspace.flow.model import * from pypy.translator.simplify import simplify_graph from pypy.translator.gensupp import uniquemodulename -from pypy.translator.tool.buildpyxmodule import make_module_from_pyxstring -from pypy.translator.tool.buildpyxmodule import make_module_from_c +from pypy.translator.tool.cbuild import make_module_from_pyxstring +from pypy.translator.tool.cbuild import make_module_from_c from pypy.objspace.flow import FlowObjSpace From hpk at codespeak.net Sat Jul 30 15:05:34 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 15:05:34 +0200 (CEST) Subject: [pypy-svn] r15416 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20050730130534.38C9927B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 15:05:33 2005 New Revision: 15416 Added: pypy/dist/pypy/translator/tool/test/ (props changed) pypy/dist/pypy/translator/tool/test/__init__.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: (hpk,arigo) implemented build_executable and a simple test for that Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat Jul 30 15:05:33 2005 @@ -218,5 +218,34 @@ if name != func.func_name: # if some transformations have been done dotgen.emit_subgraph(name, funcgraph) dotgen.generate() - return getattr(mod, func.func_name) + + +def build_executable(cfilenames, outputfilename=None, include_dirs=None): + from distutils.ccompiler import new_compiler + if outputfilename is None: + if sys.platform == 'win32': + ext = '.exe' + else: + ext = '' + outputfilename = py.path.local(cfilenames[0]).new(ext=ext) + else: + outputfilename = py.path.local(outputfilename) + + compiler = new_compiler() + objects = [] + for cfile in cfilenames: + cfile = py.path.local(cfile) + old = cfile.dirpath().chdir() + try: + res = compiler.compile([cfile.basename], + include_dirs=include_dirs) + assert len(res) == 1 + cobjfile = py.path.local(res[0]) + assert cobjfile.check() + objects.append(str(cobjfile)) + finally: + old.chdir() + compiler.link_executable(objects, str(outputfilename)) + return str(outputfilename) + Added: pypy/dist/pypy/translator/tool/test/__init__.py ============================================================================== Added: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat Jul 30 15:05:33 2005 @@ -0,0 +1,20 @@ +import py + +from pypy.tool.udir import udir +from pypy.translator.tool.cbuild import build_executable + +def test_simple_executable(): + print udir + testpath = udir.join('testbuildexec') + t = testpath.ensure("test.c") + t.write(r""" + #include + int main() { + printf("hello world\n"); + return 0; + } + """) + testexec = build_executable([t]) + out = py.process.cmdexec(testexec) + assert out.startswith('hello world') + From rxe at codespeak.net Sat Jul 30 15:15:02 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 15:15:02 +0200 (CEST) Subject: [pypy-svn] r15417 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730131502.3AACD27B75@code1.codespeak.net> Author: rxe Date: Sat Jul 30 15:14:55 2005 New Revision: 15417 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/node.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_exception.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py pypy/dist/pypy/translator/llvm2/test/test_lltype.py Log: arigo's test_aliasing() was added which started a revamping of pbcs with the knowledge of rpython.lltype.parentlink(). database/node/funcnode/arraynode/structnode - large revamping of pbcs handling. all tests pass but some weirdness with extfuncs and exceptions which will investigate into after lunch. add some tests to find out seg faulting in test_class.py also added some debugging option to aid finding out where segfaults happen while running llvm compiled code. Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sat Jul 30 15:14:55 2005 @@ -69,35 +69,66 @@ for item in self.value.items: self.db.prepare_constant(self.arraytype, item) - # set castref (note we must ensure that types are "setup" before we can - # get typeval) - typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) - self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), - self.ref, - typeval) + p, c = lltype.parentlink(self.value) + p, c = lltype.parentlink(self.value) + if p is not None: + self.db.prepare_constant(lltype.typeOf(p), p) - def get_typerepr(self): + def get_length(self): + items = self.value.items + return len(items) + + def get_arrayvalues(self): items = self.value.items - arraylen = len(items) + return [self.db.repr_constant(v)[1] for v in items] + + def get_typerepr(self): typeval = self.db.repr_arg_type(self.arraytype) - return "{ int, [%s x %s] }" % (arraylen, typeval) + return "{ int, [%s x %s] }" % (self.get_length(), typeval) - def castfrom(self): - return "%s*" % self.get_typerepr() + def get_ref(self): + """ Returns a reference as used for operations in blocks. """ + typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) + ref = "cast (%s* %s to %s*)" % (self.get_typerepr(), + self.ref, + typeval) + + p, c = lltype.parentlink(self.value) + if p is not None: + assert False, "XXX TODO" + return ref + + def get_pbcref(self, toptr): + """ Returns a reference as a pointer used per pbc. """ + ref = self.ref + p, c = lltype.parentlink(self.value) + if p is not None: + assert False, "XXX TODO" + + fromptr = "%s*" % self.get_typerepr() + refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref) + ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) + return ref + + def get_childref(self, index): + return "getelementptr(%s* %s, int 0, uint 1, int %s)" %( + self.get_typerepr(), + self.ref, + index) def constantvalue(self): """ Returns the constant representation for this node. """ - items = self.value.items - arraylen = len(items) + arraylen = self.get_length() + arrayvalues = self.get_arrayvalues() typeval = self.db.repr_arg_type(self.arraytype) - arrayvalues = [self.db.repr_constant(v)[1] for v in items] value = "int %s, [%s x %s] [ %s ]" % (arraylen, arraylen, typeval, ", ".join(arrayvalues)) s = "%s {%s}" % (self.get_typerepr(), value) + #XXXX ???????? #XXX this does not work for arrays inlined in struct. How else to do this? #if typeval == 'sbyte': #give more feedback for strings # limited_printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-.' @@ -114,4 +145,16 @@ # entry points from genllvm def writeglobalconstants(self, codewriter): - codewriter.globalinstance(self.ref, self.constantvalue()) + p, c = lltype.parentlink(self.value) + if p is None: + codewriter.globalinstance(self.ref, self.constantvalue()) + +class StrArrayNode(ConstantLLVMNode): + + def get_length(self): + # For null character + return super(StrArrayNode, self).get_length() + 1 + + def get_arrayvalues(self): + items = self.value.items + [chr(0)] + return [self.db.repr_constant(v)[1] for v in items] Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 30 15:14:55 2005 @@ -140,5 +140,11 @@ self.indent("store %(valuetype)s %(valuevar)s, " "%(valuetype)s* %(ptr)s" % locals()) + def debugcomment(self, tempname, len, tmpname): + res = "%s = tail call int (sbyte*, ...)* %%printf(" + res += "sbyte* getelementptr ([%s x sbyte]* %s, int 0, int 0) )" + res = res % (tmpname, len, tmpname) + self.indent(res) + def __str__(self): return "\n".join(self._lines) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jul 30 15:14:55 2005 @@ -50,6 +50,9 @@ def __delitem__(self, key): key = self._get(key) del self._dict[key] + def get(self, key): + key = self._get(key) + return self._dict.get(key) def values(self): return self._dict.values() def items(self): @@ -73,6 +76,37 @@ self._pendingsetup = [] self._tmpcount = 1 + # debug operation comments + self._opcomments = {} + + #_______for debugging llvm code_________________________ + + def add_op2comment(self, lenofopstr, op): + """ internal method for adding comments on each operation """ + tmpname = self.repr_tmpvar() + ".comment" + self._opcomments[op] = (lenofopstr, tmpname) + return tmpname + + def get_op2comment(self, op): + """ internal method for adding comments on each operation """ + return self._opcomments.get(op, None) + + #_______debugggin_______________________________________ + + def dump_pbcs(self): + + for k, v in self.obj2node.items(): + + if (isinstance(k, lltype.LowLevelType) or + isinstance(k, Constant)): + continue + + assert isinstance(lltype.typeOf(k), lltype.ContainerType) + print "dump_pbcs", v, "---->", k + + + #_______create node_____________________________________ + def create_constant_node(self, type_, value): node = None if isinstance(type_, lltype.FuncType): @@ -125,7 +159,14 @@ assert isinstance(ct, lltype.Ptr), "Preparation of non primitive and non pointer" value = const_or_var.value._obj - if value: #XXX for test/test_dict_creation (how to handle this better?) + # Only prepare root values at this point + if isinstance(ct, lltype.Array) or isinstance(ct, lltype.Struct): + p, c = lltype.parentlink(value) + if p is None: + log.prepare_repr_arg("XXX skipping preparing non root", value) + return + + if value is not None: self.addpending(const_or_var, self.create_constant_node(ct.TO, value)) else: log.prepare(const_or_var, type(const_or_var)) @@ -168,39 +209,36 @@ self.prepare_repr_arg_type(const_or_var.concretetype) self.prepare_repr_arg(const_or_var) - def prepare_constant(self, type_, value): + def prepare_constant(self, type_, value): if isinstance(type_, lltype.Primitive): - log.prepare_constant(value, "(is primitive)") + #log.prepare_constant(value, "(is primitive)") return - elif isinstance(type_, lltype.Ptr): + + if isinstance(type_, lltype.Ptr): + type_ = type_.TO value = value._obj - # we can share data via pointers & dont need a node for nulls - if value in self.obj2node or value is None: + log.prepare_constant("preparing ptr", value) + + # we dont need a node for nulls + if value is None: return - self.addpending(value, - self.create_constant_node(type_, value)) + # we can share data via pointers + if value not in self.obj2node: + self.addpending(value, self.create_constant_node(type_, value)) + # Always add type (it is safe) + self.prepare_repr_arg_type(type_) + def setup_all(self): # Constants setup need to be done after the rest - pendingconstants = [] while self._pendingsetup: node = self._pendingsetup.pop() - if isinstance(node, (StructNode, ArrayNode)): - pendingconstants.append(node) - continue log.settingup(node) node.setup() - self._pendingsetup = pendingconstants - while self._pendingsetup: - node = self._pendingsetup.pop() - assert isinstance(node, ConstantLLVMNode) - log.settingup_constant(node) - node.setup() - def getnodes(self): return self.obj2node.values() @@ -212,18 +250,16 @@ if isinstance(arg.concretetype, lltype.Primitive): return primitive_to_str(arg.concretetype, arg.value) else: - try: - node = self.obj2node[arg] - except KeyError: - #XXX related to llvm2/test/test_genllvm/test_dict_creation - #XXX "v962 = same_as((<* None>))" - #XXX this <* None> gets propagated to the next block and fails at the phi node! - #XXX Need better way to test for this only! + node = self.obj2node.get(arg) + if node is None: return 'null' - if hasattr(node, "castref"): - return node.castref else: - return node.ref + return node.get_ref() + + # XXX ??? dont understand rxe ??? + #XXX related to llvm2/test/test_genllvm/test_dict_creation + #XXX "v962 = same_as((<* None>))" + #XXX this <* None> gets propagated to the next block and fails at the phi node! else: assert isinstance(arg, Variable) return "%" + str(arg) @@ -259,18 +295,14 @@ elif isinstance(type_, lltype.Ptr): toptr = self.repr_arg_type(type_) + value = value._obj # special case, null pointer - if value._obj is None: + if value is None: return None, "%s null" % (toptr,) - node = self.obj2node[value._obj] - ref = node.ref - - fromptr = node.castfrom() - if fromptr: - refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref) - ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) + node = self.obj2node[value] + ref = node.get_pbcref(toptr) return node, "%s %s" % (toptr, ref) elif isinstance(type_, lltype.Array) or isinstance(type_, lltype.Struct): Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 30 15:14:55 2005 @@ -14,8 +14,6 @@ self.db = db assert isinstance(type_, lltype.FuncType) self.type_ = type_ - # XXX Make simplier for now, it is far too hard to read otherwise - #self.ref = 'ft.%s.%s' % (type_, nextnum()) self.ref = self.make_ref('%functiontype', '') def __str__(self): @@ -80,6 +78,17 @@ self.write_block(codewriter, block) codewriter.closefunc() + def writecomments(self, codewriter): + """ write operations strings for debugging purposes. """ + blocks = [x for x in flatten(self.graph) if isinstance(x, Block)] + for block in blocks: + for op in block.operations: + strop = str(op) + l = (len(strop) + 2) # new line & null + tempname = self.db.add_op2comment(l, op) + typeandata = '[%s x sbyte] c"%s\\0A\\00"' % (l, strop) + codewriter.globalinstance(tempname, typeandata) + # ______________________________________________________________________ # writing helpers for entry points @@ -135,7 +144,16 @@ opwriter = OpWriter(self.db, codewriter, self, block) last_direct_call_index = self._last_operation(block, 'direct_call') for op_index, op in enumerate(block.operations): + + # print out debug string codewriter.comment(str(op)) + info = self.db.get_op2comment(op) + if info is not None: + lenofopstr, opstrname = info + codewriter.debugcomment(self.db.repr_tmpvar(), + lenofopstr, + opstrname) + if op_index == last_direct_call_index and block.exitswitch == Constant(last_exception): op.opname = 'direct_invoke' opwriter.write_operation(op) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 30 15:14:55 2005 @@ -24,7 +24,7 @@ class GenLLVM(object): - def __init__(self, translator, embedexterns=True): + def __init__(self, translator, debug=False, embedexterns=True): LLVMNode.nodename_count = {} #reset counters self.db = Database(translator) self.translator = translator @@ -35,6 +35,9 @@ translator.checkgraphs() ExternalFuncNode.used_external_functions = {} + # For debug we create comments of every operation that may be executed + self.debug = debug + def compile(self, func=None): if func is None: func = self.translator.entrypoint @@ -54,6 +57,9 @@ assert c in self.db.obj2node self.db.setup_all() + self.db.dump_pbcs() + #assert False + self.entrynode = self.db.obj2node[c] codewriter = CodeWriter() comment = codewriter.comment @@ -67,10 +73,19 @@ for typ_decl in self.db.getnodes(): typ_decl.writeglobalconstants(codewriter) + if self.debug: + nl(); comment("Comments") ; nl() + for typ_decl in self.db.getnodes(): + typ_decl.writecomments(codewriter) + nl(); comment("Function Prototypes") ; nl() if self.embedexterns: for extdecl in extdeclarations.split('\n'): codewriter.append(extdecl) + + if self.debug: + self._debug_prototype(codewriter) + for typ_decl in self.db.getnodes(): typ_decl.writedecl(codewriter) @@ -113,6 +128,7 @@ function_count[func.func_name] += 1 else: postfix = '' + function_count[func.func_name] = 1 targetdir = udir @@ -126,6 +142,10 @@ write_pyx_wrapper(self.entrynode, pyxsource) return build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) + + def _debug_prototype(self, codewriter): + codewriter.append("declare int %printf(sbyte*, ...)") + def genllvm(translator, embedexterns=True): gen = GenLLVM(translator, embedexterns=embedexterns) Modified: pypy/dist/pypy/translator/llvm2/node.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/node.py (original) +++ pypy/dist/pypy/translator/llvm2/node.py Sat Jul 30 15:14:55 2005 @@ -54,11 +54,17 @@ def writedecl(self, codewriter): """ write function forward declarations. """ + def writecomments(self, codewriter): + """ write operations strings for debugging purposes. """ + # __________________ after "implementation" ____________________ def writeimpl(self, codewriter): """ write function implementations. """ class ConstantLLVMNode(LLVMNode): - def castfrom(self): - return None + def get_ref(self): + return self.ref + + def get_pbcref(self, toptr): + return self.ref Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 15:14:55 2005 @@ -226,8 +226,11 @@ not_this_exception_label = block_label + '_not_exception_' + etype.ref[1:] ll_issubclass_cond = self.db.repr_tmpvar() - self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, - [tmpvar2, etype.ref], [lltype_of_exception_type, lltype_of_exception_type]) + self.codewriter.call(ll_issubclass_cond, + 'bool', + ll_exception_match, + [tmpvar2, self.db.repr_arg_type(type)], + [lltype_of_exception_type, lltype_of_exception_type]) self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) self.codewriter.label(not_this_exception_label) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 30 15:14:55 2005 @@ -103,20 +103,54 @@ assert T is not lltype.Void value = getattr(self.value, name) self.db.prepare_constant(T, value) - + + p, c = lltype.parentlink(self.value) + if p is not None: + self.db.prepare_constant(lltype.typeOf(p), p) + def get_typerepr(self): return self.db.repr_arg_type(self.structtype) + + def get_childref(self, index): + pos = 0 + found = False + for name in self.structtype._names_without_voids(): + if name == index: + found = True + break + pos += 1 + + return "getelementptr(%s* %s, int 0, uint %s)" %( + self.get_typerepr(), + self.get_ref(), + pos) + + def get_ref(self): + """ Returns a reference as used for operations in blocks. """ + p, c = lltype.parentlink(self.value) + if p is None: + ref = self.ref + else: + parent = self.db.obj2node[p] + ref = parent.get_childref(c) + return ref + + def get_pbcref(self, toptr): + """ Returns a reference as used per pbc. """ + return self.get_ref() def constantvalue(self): """ Returns the constant representation for this node. """ values = self._getvalues() return "%s {%s}" % (self.get_typerepr(), ", ".join(values)) - + # ______________________________________________________________________ # main entry points from genllvm def writeglobalconstants(self, codewriter): - codewriter.globalinstance(self.ref, self.constantvalue()) + p, c = lltype.parentlink(self.value) + if p is None: + codewriter.globalinstance(self.ref, self.constantvalue()) class StructVarsizeNode(StructNode): """ A varsize struct constant. Can simply contain @@ -156,13 +190,6 @@ def setup(self): super(StructVarsizeNode, self).setup() - - # set castref (note we must ensure that types are "setup" before we can - # get typeval) - typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) - self.castref = "cast (%s* %s to %s*)" % (self.get_typerepr(), - self.ref, - typeval) def get_typerepr(self): # last type is a special case and need to be worked out recursively @@ -171,7 +198,25 @@ types_repr.append(self._get_lastnode().get_typerepr()) return "{%s}" % ", ".join(types_repr) - - def castfrom(self): - return "%s*" % self.get_typerepr() - + + def get_ref(self): + #XXX Is this right? + ref = super(StructVarsizeNode, self).get_ref() + typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) + ref = "cast (%s* %s to %s*)" % (self.get_typerepr(), + ref, + typeval) + return ref + + def get_pbcref(self, toptr): + """ Returns a reference as used per pbc. """ + ref = self.ref + p, c = lltype.parentlink(self.value) + if p is not None: + assert False, "XXX TODO" + + fromptr = "%s*" % self.get_typerepr() + refptr = "getelementptr (%s %s, int 0)" % (fromptr, ref) + ref = "cast(%s %s to %s)" % (fromptr, refptr, toptr) + return ref + Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jul 30 15:14:55 2005 @@ -212,6 +212,30 @@ c = C(b) return c.a.a + +class AA(object): + x = 8 + def __init__(self): + self.a = 15 + self.b = 16 + def g(self): + return self.a + self.b + +class BB(AA): + x = 3 + def g(self): + return self.a + self.a + +def class_inherit1(): + aa = AA() + bb = BB() + return aa.x + bb.x + +def class_inherit2(): + aa = AA() + bb = BB() + return aa.g() + bb.g() + class D(object): def __init__(self, a, length): self.a = [a] * length Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Sat Jul 30 15:14:55 2005 @@ -24,9 +24,18 @@ f = compile_function(llvmsnippet.class_simple2, [int]) assert f(2) == 10 + def test_inherit1(self): + f = compile_function(llvmsnippet.class_inherit1, []) + assert f() == 11 + + def test_inherit2(self): + py.test.skip("not working yet (segfault)") + f = compile_function(llvmsnippet.class_inherit2, []) + assert f() == 11 + def test_method_of_base_class(self): py.test.skip("not working yet (segfault)") - f = compile_function(llvmsnippet.method_of_base_class, []) + f = compile_function(llvmsnippet.method_of_base_class, [], view=True) assert f() == 14 def test_attribute_from_base_class(self): Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sat Jul 30 15:14:55 2005 @@ -3,6 +3,9 @@ from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.test.snippet import try_raise_choose +def setup_module(module): + py.test.skip("tmp - just to sync up changes") + class TestException(Exception): pass Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Sat Jul 30 15:14:55 2005 @@ -10,6 +10,9 @@ py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) +def setup_module(module): + py.test.skip("tmp - just to sync up changes") + def test_external_function_ll_os_dup(): def fn(): return os.dup(0) Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_lltype.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Sat Jul 30 15:14:55 2005 @@ -104,6 +104,18 @@ f = compile_function(struct_constant, [], embedexterns=False) assert f() == struct_constant() +def test_aliasing(): + B = lltype.Struct('B', ('x', lltype.Signed)) + A = lltype.Array(B) + global_a = lltype.malloc(A, 5, immortal=True) + global_b = global_a[3] + def aliasing(i): + global_b.x = 17 + return global_a[i].x + f = compile_function(aliasing, [int], embedexterns=False) + assert f(2) == 0 + assert f(3) == 17 + def test_array_constant(): A = lltype.GcArray(lltype.Signed) a = lltype.malloc(A, 3) From hpk at codespeak.net Sat Jul 30 15:18:07 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 15:18:07 +0200 (CEST) Subject: [pypy-svn] r15418 - pypy/extradoc/sprintinfo Message-ID: <20050730131807.CE46127B7C@code1.codespeak.net> Author: hpk Date: Sat Jul 30 15:18:07 2005 New Revision: 15418 Modified: pypy/extradoc/sprintinfo/ (props changed) Log: ignore html files in this dir From cfbolz at codespeak.net Sat Jul 30 15:21:25 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 15:21:25 +0200 (CEST) Subject: [pypy-svn] r15419 - in pypy/dist/pypy: annotation documentation rpython/memory rpython/memory/test Message-ID: <20050730132125.65A8527B75@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 15:21:21 2005 New Revision: 15419 Added: pypy/dist/pypy/documentation/gc_planning.txt pypy/dist/pypy/rpython/memory/ pypy/dist/pypy/rpython/memory/__init__.py pypy/dist/pypy/rpython/memory/lladdress.py pypy/dist/pypy/rpython/memory/test/ pypy/dist/pypy/rpython/memory/test/test_address.py Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/model.py Log: (pedronis, cfbolz): garbage collection: - added a bit of planning documentation for GC - added a dummy implementation of the Address class - this class does nothing at the moment but is annotated correctly Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jul 30 15:21:21 2005 @@ -16,6 +16,7 @@ from pypy.rpython.rarithmetic import r_uint from pypy.tool.unionfind import UnionFind from pypy.rpython import lltype +from pypy.rpython.memory import lladdress from pypy.annotation.specialize import decide_callable @@ -330,6 +331,9 @@ result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (x.__module__, x.__name__)) 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 callable(x) or isinstance(x, staticmethod): # XXX # maybe 'x' is a method bound to a not-yet-frozen cache? # fun fun fun. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat Jul 30 15:21:21 2005 @@ -7,7 +7,7 @@ from pypy.tool.ansi_print import ansi_print from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool from pypy.annotation.model import SomeList, SomeString, SomeTuple, SomeSlice -from pypy.annotation.model import SomeUnicodeCodePoint +from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress from pypy.annotation.model import SomeFloat, unionof from pypy.annotation.model import SomePBC, SomeInstance from pypy.annotation.model import annotation_to_lltype @@ -336,9 +336,36 @@ BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info +#_________________________________ +# memory address + +from pypy.rpython.memory import lladdress + +def raw_malloc(s_size): + assert isinstance(s_size, SomeInteger) #XXX add noneg...? + return SomeAddress() + +def raw_free(s_addr): + assert isinstance(s_addr, SomeAddress) + assert not s_addr.is_null + +def raw_memcopy(s_addr1, s_addr2, s_int): + assert isinstance(s_addr1, SomeAddress) + assert isinstance(s_addr2, SomeAddress) + assert isinstance(s_int, SomeInteger) #XXX add noneg...? + +BUILTIN_ANALYZERS[lladdress.raw_malloc] = raw_malloc +BUILTIN_ANALYZERS[lladdress.raw_free] = raw_free +BUILTIN_ANALYZERS[lladdress.raw_memcopy] = raw_memcopy + +#_________________________________ +# external functions + + from pypy.rpython import extfunctable # import annotation information for external functions # from the extfunctable.table into our own annotation specific table for func, extfuncinfo in extfunctable.table.iteritems(): BUILTIN_ANALYZERS[func] = extfuncinfo.annotation + Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jul 30 15:21:21 2005 @@ -440,6 +440,16 @@ return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ +# memory addresses + +class SomeAddress(SomeObject): + def __init__(self, is_null=False): + self.is_null = is_null + + def can_be_none(self): + return False + +# ____________________________________________________________ class UnionError(Exception): """Signals an suspicious attempt at taking the union of Added: pypy/dist/pypy/documentation/gc_planning.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/gc_planning.txt Sat Jul 30 15:21:21 2005 @@ -0,0 +1,57 @@ +plan: +===== + - write a simulator using arrays + - blocks are malloced with their size + - addresses are pointers memory locations: + * they are basically integers + * offsets are just regular integers + * their annotation is SomeAddress + +Address operations: +=================== + +construction / destruction: +---------------------------- + - NULL: global object + - raw_malloc(size) --> address + - raw_free(addr) + - memcopy(addr1, addr2, size) + +memory access: +-------------- + + - reading: addr.signed[offset] + - writing: addr.signed[offset] = value + - datatypes: + * signed, unsigned, char, address + + +open question / whish: +====================== + +it would be cool to do something like:: + + class A(object): + _raw_allocate_ = True + def method(self): + ... + + a = A() + free_non_gc_object(a) + a.method() #-> crash + +it seems possible, will be messy + + +Memory Layout: +============== + +for now we go for the simple solution:: + + +-<-<-< object model sees only this + V + +---------+---------+----------------------------+ + | gc info | type id | object data | + | int | int | whatever | + +---------+---------+----------------------------+ + Added: pypy/dist/pypy/rpython/memory/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/__init__.py Sat Jul 30 15:21:21 2005 @@ -0,0 +1 @@ +# Added: pypy/dist/pypy/rpython/memory/lladdress.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/lladdress.py Sat Jul 30 15:21:21 2005 @@ -0,0 +1,16 @@ + +class Address(object): + pass + +NULL = Address() + +def raw_malloc(size): + pass + +def raw_free(addr): + pass + +def raw_memcopy(addr1, addr2, size): + pass + + Added: pypy/dist/pypy/rpython/memory/test/test_address.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/test/test_address.py Sat Jul 30 15:21:21 2005 @@ -0,0 +1,43 @@ +import py + +from pypy.annotation import model as annmodel +from pypy.translator.annrpython import RPythonAnnotator +from pypy.objspace.flow import FlowObjSpace +from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL, raw_memcopy + +class TestAddressAnnotation(object): + def test_raw_malloc(self): + def f(): + return raw_malloc(100) + a = RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeAddress) + assert not s.is_null + + def test_null(self): + def f(): + return NULL + a = RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeAddress) + assert s.is_null + + def test_raw_free(self): + def f(addr): + raw_free(addr) + a = RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeAddress()]) #does not raise + py.test.raises(AssertionError, + a.build_types, f, [annmodel.SomeAddress(is_null=True)]) + + def test_memcopy(self): + def f(addr1, addr2): + raw_memcopy(addr1, addr2, 100) + a = RPythonAnnotator() + #does not raise: + s = a.build_types(f, [annmodel.SomeAddress(), annmodel.SomeAddress()]) + py.test.raises(AssertionError, a.build_types, f, + [annmodel.SomeAddress(is_null=True), + annmodel.SomeAddress()]) + + From hpk at codespeak.net Sat Jul 30 19:02:50 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 19:02:50 +0200 (CEST) Subject: [pypy-svn] r15424 - pypy/dist/pypy/translator/goal Message-ID: <20050730170250.6B54E27B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 19:02:49 2005 New Revision: 15424 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: (arigo,hpk) added some debugging information to the main entry point also call the entry point as a sanity check before translation. which uncovered an umpff bug in that we call 'space.call(...)' instead of space.call_function. another bug is related to posix which we are going to fix now ... Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sat Jul 30 19:02:49 2005 @@ -6,6 +6,7 @@ from pypy.annotation.model import SomeList, SomeString from pypy.annotation.listdef import ListDef from pypy.interpreter import gateway +from pypy.interpreter.error import OperationError # WARNING: this requires the annotator. # There is no easy way to build all caches manually, @@ -16,16 +17,29 @@ except NameError: this_dir = os.path.dirname(sys.argv[0]) +def debug(msg): + os.write(2, "debug: " + msg + '\n') + # __________ Entry point __________ def entry_point(argvstring): + debug("entry point starting") + debug(argvstring) argv = argvstring.split('\x00') - w_argv = space.newlist([space.wrap(s) for s in argv]) - w_exitcode = space.call(w_entry_point, w_argv) - # try to pull it all in -## from pypy.interpreter import main, interactive, error -## con = interactive.PyPyConsole(space) -## con.interact() + for arg in argv: + debug(" argv -> " + arg) + try: + w_argv = space.newlist([space.wrap(s) for s in argv]) + w_exitcode = space.call_function(w_entry_point, w_argv) + # try to pull it all in + ## from pypy.interpreter import main, interactive, error + ## con = interactive.PyPyConsole(space) + ## con.interact() + except OperationError, e: + debug("OperationError:") + debug(e.w_type.name) + debug(space.str_w(space.str(e.w_value))) + return 1 return space.int_w(w_exitcode) # _____ Define and setup target ___ @@ -48,6 +62,10 @@ space.exec_(open(filename).read(), w_dict, w_dict) w_entry_point = space.getitem(w_dict, space.wrap('entry_point')) + # sanity-check: call the entry point + res = entry_point("app_example.py") + assert res == 0 + return entry_point, [SomeString()] def get_llinterp_args(): From pedronis at codespeak.net Sat Jul 30 19:45:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 30 Jul 2005 19:45:54 +0200 (CEST) Subject: [pypy-svn] r15425 - in pypy/dist/pypy: rpython rpython/module rpython/module/test translator/c translator/c/src translator/c/test Message-ID: <20050730174554.299A727B75@code1.codespeak.net> Author: pedronis Date: Sat Jul 30 19:45:42 2005 New Revision: 15425 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/test/test_ll_os.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: strerror support Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sat Jul 30 19:45:42 2005 @@ -78,6 +78,7 @@ declare(os.ftruncate, noneannotation, 'll_os/ftruncate') declare(os.fstat , statannotation, 'll_os/fstat') declare(os.stat , statannotation, 'll_os/stat') +declare(os.strerror , str , 'll_os/strerror') declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') declare(time.time , float , 'll_time/time') 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 Jul 30 19:45:42 2005 @@ -109,3 +109,7 @@ return ll_stat_result(stat0, stat1, stat2, stat3, stat4, stat5, stat6, stat7, stat8, stat9) ll_os_stat.suggested_primitive = True + +def ll_os_strerror(errnum): + return to_rstr(os.strerror(errnum)) +ll_os_getcwd.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os.py Sat Jul 30 19:45:42 2005 @@ -23,3 +23,7 @@ def test_getcwd(): data = ll_os_getcwd() assert from_rstr(data) == os.getcwd() + +def test_strerror(): + data = ll_os_strerror(2) + assert from_rstr(data) == os.strerror(2) Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Sat Jul 30 19:45:42 2005 @@ -19,6 +19,7 @@ ll_os .ll_os_lseek: 'LL_os_lseek', ll_os .ll_os_isatty: 'LL_os_isatty', ll_os .ll_os_ftruncate:'LL_os_ftruncate', + ll_os .ll_os_strerror: 'LL_os_strerror', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', ll_time.ll_time_time: 'LL_time_time', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Sat Jul 30 19:45:42 2005 @@ -167,3 +167,10 @@ RAISE_OSERROR(errno); } } + +RPyString *LL_os_strerror(int errnum) +{ + char *res; + res = strerror(errnum); + return RPyString_FromString(res); +} Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sat Jul 30 19:45:42 2005 @@ -134,6 +134,13 @@ res = f1() assert res == os.getcwd() +def test_strerror(): + def does_stuff(): + return os.strerror(2) + f1 = compile(does_stuff, []) + res = f1() + assert res == os.strerror(2) + def test_math_frexp(): from math import frexp def fn(x): From hpk at codespeak.net Sat Jul 30 19:48:53 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 19:48:53 +0200 (CEST) Subject: [pypy-svn] r15426 - in pypy/dist/pypy/module/posix: . test Message-ID: <20050730174853.AD1A527B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 19:48:52 2005 New Revision: 15426 Modified: pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix2.py Log: check exception handling (which was completely broken or non-existent for the posix module) Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Sat Jul 30 19:48:52 2005 @@ -1,36 +1,75 @@ from pypy.interpreter.baseobjspace import ObjSpace from pypy.rpython.rarithmetic import intmask +from pypy.interpreter.error import OperationError import os from os import * +def wrap_oserror(space, e): + assert isinstance(e, OSError) + errno = e.errno + msg = os.strerror(errno) + w_error = space.call_function(space.w_OSError, + space.wrap(errno), + space.wrap(msg)) + return OperationError(space.w_OSError, w_error) + def open(space, fname, flag, mode=0777): - fd = os.open(fname, flag, mode) + try: + fd = os.open(fname, flag, mode) + except OSError, e: + raise wrap_oserror(space, e) return space.wrap(fd) open.unwrap_spec = [ObjSpace, str, int, int] def lseek(space, fd, pos, how): - return space.wrap(os.lseek(fd, pos, how)) + try: + pos = os.lseek(fd, pos, how) + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(pos) lseek.unwrap_spec = [ObjSpace, int, int, int] def isatty(space, fd): - return space.wrap(os.isatty(fd)) + try: + res = os.isatty(fd) + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(res) isatty.unwrap_spec = [ObjSpace, int] def read(space, fd, buffersize): - return space.wrap(os.read(fd, buffersize)) + try: + s = os.read(fd, buffersize) + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(s) read.unwrap_spec = [ObjSpace, int, int] def write(space, fd, data): - return space.wrap(os.write(fd, data)) + try: + res = os.write(fd, data) + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(res) write.unwrap_spec = [ObjSpace, int, str] def close(space, fd): - os.close(fd) + try: + os.close(fd) + except OSError, e: + raise wrap_oserror(space, e) close.unwrap_spec = [ObjSpace, int] def ftruncate(space, fd, length): - os.ftruncate(fd, length) + try: + os.ftruncate(fd, length) + except OSError, e: + raise wrap_oserror(space, e) ftruncate.unwrap_spec = [ObjSpace, int, int] def build_stat_result(space, st): @@ -43,17 +82,37 @@ return space.call_function(w_stat_result, w_tuple) def fstat(space, fd): - return build_stat_result(space, os.fstat(fd)) + try: + st = os.fstat(fd) + except OSError, e: + raise wrap_oserror(space, e) + else: + return build_stat_result(space, st) fstat.unwrap_spec = [ObjSpace, int] def stat(space, path): - return build_stat_result(space, os.stat(path)) + try: + st = os.stat(path) + except OSError, e: + raise wrap_oserror(space, e) + else: + return build_stat_result(space, st) stat.unwrap_spec = [ObjSpace, str] def getcwd(space): - return space.wrap(os.getcwd()) + try: + cur = os.getcwd() + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(cur) getcwd.unwrap_spec = [ObjSpace] def dup(space, fd): - return space.wrap(os.dup(fd)) + try: + newfd = os.dup(fd) + except OSError, e: + raise wrap_oserror(space, e) + else: + return space.wrap(newfd) dup.unwrap_spec = [ObjSpace, int] Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Sat Jul 30 19:48:52 2005 @@ -30,3 +30,35 @@ assert stat # XXX posix.close(fd2) posix.close(fd) + + def test_open_exception(self): + posix = self.posix + try: + posix.open('qowieuqwoeiu', 0, 0) + except OSError: + pass + else: + assert 0 + + def test_functions_raise_error(self): + def ex(func, *args): + try: + func(*args) + except OSError: + pass + else: + raise AssertionError("%s(%s) did not raise" %( + func.__name__, + ", ".join([str(x) for x in args]))) + UNUSEDFD = 123123 + ex(self.posix.open, "qweqwe", 0, 0) + ex(self.posix.lseek, UNUSEDFD, 123, 0) + #apparently not posix-required: ex(self.posix.isatty, UNUSEDFD) + ex(self.posix.read, UNUSEDFD, 123) + ex(self.posix.write, UNUSEDFD, "x") + ex(self.posix.close, UNUSEDFD) + #UMPF cpython raises IOError ex(self.posix.ftruncate, UNUSEDFD, 123) + ex(self.posix.fstat, UNUSEDFD) + ex(self.posix.stat, "qweqwehello") + # how can getcwd() raise? + ex(self.posix.dup, UNUSEDFD) From cfbolz at codespeak.net Sat Jul 30 19:55:16 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 19:55:16 +0200 (CEST) Subject: [pypy-svn] r15427 - in pypy/dist/pypy: annotation documentation rpython/memory rpython/memory/test Message-ID: <20050730175516.31EAF27B75@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 19:55:06 2005 New Revision: 15427 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/documentation/gc_planning.txt pypy/dist/pypy/rpython/memory/lladdress.py pypy/dist/pypy/rpython/memory/test/test_address.py Log: (cfbolz, pedronis): added annotation to memory read/write using address.signed[offset] added annotation for address arithmetic and comparisons tests Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sat Jul 30 19:55:06 2005 @@ -10,6 +10,7 @@ from pypy.annotation.model import SomeTuple, SomeImpossibleValue from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator from pypy.annotation.model import SomePBC, SomeSlice, SomeFloat +from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS from pypy.annotation.model import add_knowntypedata, merge_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper @@ -610,3 +611,38 @@ return pair(p2, obj).union() +#_________________________________________ +# memory addresses + +class __extend__(pairtype(SomeAddress, SomeAddress)): + def union((s_addr1, s_addr2)): + return SomeAddress(is_null=s_addr1.is_null and s_addr2.is_null) + +class __extend__(pairtype(SomeTypedAddressAccess, SomeTypedAddressAccess)): + def union((s_taa1, s_taa2)): + assert s_taa1.type == s_taa2.type + return s_taa1 + +class __extend__(pairtype(SomeTypedAddressAccess, SomeInteger)): + def getitem((s_taa, s_int)): + from pypy.annotation.model import lltype_or_address_to_annotation + return lltype_or_address_to_annotation(s_taa.type) + + def setitem((s_taa, s_int), s_value): + from pypy.annotation.model import annotation_to_lltype_or_address + assert annotation_to_lltype_or_address(s_value) is s_taa.type + + +class __extend__(pairtype(SomeAddress, SomeInteger)): + def add((s_addr, s_int)): + return SomeAddress(is_null=False) + + def sub((s_addr, s_int)): + return SomeAddress(is_null=False) + +class __extend__(pairtype(SomeAddress, SomeAddress)): + def sub((s_addr1, s_addr2)): + if s_addr1.is_null and s_addr2.is_null: + return getbookkeeper().immutablevalue(0) + return SomeInteger() + Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat Jul 30 19:55:06 2005 @@ -351,7 +351,9 @@ def raw_memcopy(s_addr1, s_addr2, s_int): assert isinstance(s_addr1, SomeAddress) + assert not s_addr1.is_null assert isinstance(s_addr2, SomeAddress) + assert not s_addr2.is_null assert isinstance(s_int, SomeInteger) #XXX add noneg...? BUILTIN_ANALYZERS[lladdress.raw_malloc] = raw_malloc Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jul 30 19:55:06 2005 @@ -449,6 +449,31 @@ def can_be_none(self): return False + +# The following class is used to annotate the intermediate value that +# appears in expressions of the form: +# addr.signed[offset] and addr.signed[offset] = value + +class SomeTypedAddressAccess(SomeObject): + def __init__(self, type): + self.type = type + + def can_be_none(self): + return False + +def lltype_or_address_to_annotation(T): + from pypy.rpython.memory.lladdress import Address + if T is Address: + return SomeAddress() + return lltype_to_annotation(T) + +def annotation_to_lltype_or_address(s_ann): + from pypy.rpython.memory.lladdress import Address + if isinstance(s_ann, SomeAddress): + return Address + else: + return annotation_to_lltype(s_ann) + # ____________________________________________________________ class UnionError(Exception): Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jul 30 19:55:06 2005 @@ -11,6 +11,7 @@ from pypy.annotation.model import SomeTuple, SomeImpossibleValue from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeFloat from pypy.annotation.model import SomeIterator, SomePBC, new_or_old_class +from pypy.annotation.model import SomeTypedAddressAccess, SomeAddress from pypy.annotation.model import unionof, set, setunion, missing_operation from pypy.annotation.bookkeeper import getbookkeeper, RPythonCallsSpace from pypy.annotation.classdef import isclassdef @@ -493,3 +494,17 @@ def is_true(p): return SomeBool() + + +#_________________________________________ +# memory addresses + +from pypy.rpython.memory import lladdress + +class __extend__(SomeAddress): + def getattr(s_addr, s_attr): + assert s_attr.is_constant() + assert isinstance(s_attr, SomeString) + assert s_attr.const in lladdress.supported_access_types + return SomeTypedAddressAccess( + lladdress.supported_access_types[s_attr.const]) Modified: pypy/dist/pypy/documentation/gc_planning.txt ============================================================================== --- pypy/dist/pypy/documentation/gc_planning.txt (original) +++ pypy/dist/pypy/documentation/gc_planning.txt Sat Jul 30 19:55:06 2005 @@ -23,7 +23,7 @@ - reading: addr.signed[offset] - writing: addr.signed[offset] = value - datatypes: - * signed, unsigned, char, address + * signed, unsigned, char, float(?), address open question / whish: Modified: pypy/dist/pypy/rpython/memory/lladdress.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lladdress.py (original) +++ pypy/dist/pypy/rpython/memory/lladdress.py Sat Jul 30 19:55:06 2005 @@ -1,7 +1,17 @@ +from pypy.rpython import lltype + + class Address(object): pass + +supported_access_types = {"signed": lltype.Signed, + "unsigned": lltype.Unsigned, + "char": lltype.Char, + "address": Address, + } + NULL = Address() def raw_malloc(size): 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 Sat Jul 30 19:55:06 2005 @@ -27,6 +27,7 @@ raw_free(addr) a = RPythonAnnotator() s = a.build_types(f, [annmodel.SomeAddress()]) #does not raise + a = RPythonAnnotator() py.test.raises(AssertionError, a.build_types, f, [annmodel.SomeAddress(is_null=True)]) @@ -36,8 +37,61 @@ a = RPythonAnnotator() #does not raise: s = a.build_types(f, [annmodel.SomeAddress(), annmodel.SomeAddress()]) + a = RPythonAnnotator() py.test.raises(AssertionError, a.build_types, f, [annmodel.SomeAddress(is_null=True), annmodel.SomeAddress()]) - + def test_union(self): + def f(x, y): + if y: + addr = NULL + else: + if x: + addr = NULL + else: + addr = raw_malloc(10) + return addr + a = RPythonAnnotator() + s_true = annmodel.SomeBool() + s_true.const = True + s_false = annmodel.SomeBool() + s_false.const = False + s = a.build_types(f, [bool, bool]) + assert isinstance(s, annmodel.SomeAddress) + assert not s.is_null + a = RPythonAnnotator() + s = a.build_types(f, [s_true, bool]) + assert isinstance(s, annmodel.SomeAddress) + assert s.is_null + a = RPythonAnnotator() + s = a.build_types(f, [s_false, bool]) + assert isinstance(s, annmodel.SomeAddress) + assert not s.is_null + + def test_memory_access(self): + def f(offset, value): + addr = raw_malloc(offset * 2 + 1) + addr.signed[offset] = value + return addr.signed[offset] + a = RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeInteger(), annmodel.SomeInteger()]) + assert isinstance(s, annmodel.SomeInteger) + + def test_address_arithmetic(self): + def f(offset, char): + addr = raw_malloc(offset * 2 + 1) + same_offset = (addr + offset) - addr + addr.char[offset] = char + return (addr + same_offset).char[0] + a = RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeInteger(), annmodel.SomeChar()]) + assert isinstance(s, annmodel.SomeChar) + + def test_address_comparison(self): + def f(offset): + return NULL < NULL + offset + a = RPythonAnnotator() + s = a.build_types(f, [annmodel.SomeInteger()]) + a.translator.view() + assert isinstance(s, annmodel.SomeBool) From hpk at codespeak.net Sat Jul 30 19:57:27 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 19:57:27 +0200 (CEST) Subject: [pypy-svn] r15428 - pypy/dist/pypy/translator/goal Message-ID: <20050730175727.45D8927B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 19:57:26 2005 New Revision: 15428 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: we have to pass a zero-splitted string (the entry_point builds the argv by splitting a string by the 0 terminator) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sat Jul 30 19:57:26 2005 @@ -63,7 +63,7 @@ w_entry_point = space.getitem(w_dict, space.wrap('entry_point')) # sanity-check: call the entry point - res = entry_point("app_example.py") + res = entry_point("pypy\x00app_example.py") assert res == 0 return entry_point, [SomeString()] From hpk at codespeak.net Sat Jul 30 19:59:09 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 19:59:09 +0200 (CEST) Subject: [pypy-svn] r15429 - pypy/dist/pypy/translator/goal Message-ID: <20050730175909.3AA7527B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 19:59:08 2005 New Revision: 15429 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: fix another argv construction to result in two strings Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sat Jul 30 19:59:08 2005 @@ -76,6 +76,6 @@ # _____ Run translated _____ def run(c_entry_point): - argv = [os.path.join(this_dir, 'app_example.py')] + argv = ["pypy", os.path.join(this_dir, 'app_example.py')] exitcode = c_entry_point('\x00'.join(argv)) assert exitcode == 0 From hpk at codespeak.net Sat Jul 30 20:04:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 20:04:43 +0200 (CEST) Subject: [pypy-svn] r15430 - pypy/dist/pypy/translator/goal Message-ID: <20050730180443.445D627B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 20:04:42 2005 New Revision: 15430 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: add memory and memory.lladdress to the list of accepted module names before forking Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sat Jul 30 20:04:42 2005 @@ -128,7 +128,8 @@ def assert_rpython_mostly_not_imported(): prefix = 'pypy.rpython.' - oknames = 'rarithmetic extfunctable lltype objectmodel error'.split() + oknames = ('rarithmetic memory memory.lladdress extfunctable ' + 'lltype objectmodel error'.split()) wrongimports = [] for name, module in sys.modules.items(): if module is not None and name.startswith(prefix): From hpk at codespeak.net Sat Jul 30 20:12:28 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 20:12:28 +0200 (CEST) Subject: [pypy-svn] r15431 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20050730181228.2B08C27B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 20:12:27 2005 New Revision: 15431 Modified: pypy/dist/pypy/rpython/memory/ (props changed) pypy/dist/pypy/rpython/memory/__init__.py (props changed) pypy/dist/pypy/rpython/memory/lladdress.py (props changed) pypy/dist/pypy/rpython/memory/test/ (props changed) pypy/dist/pypy/rpython/memory/test/test_address.py (props changed) Log: fixeol From hpk at codespeak.net Sat Jul 30 20:18:57 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 20:18:57 +0200 (CEST) Subject: [pypy-svn] r15432 - pypy/dist/pypy/translator/goal Message-ID: <20050730181857.2ACEC27B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 20:18:56 2005 New Revision: 15432 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: not confusing annotation with our debugging info (umpf) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sat Jul 30 20:18:56 2005 @@ -37,8 +37,8 @@ ## con.interact() except OperationError, e: debug("OperationError:") - debug(e.w_type.name) - debug(space.str_w(space.str(e.w_value))) + debug(" operror-type: " + w_type.getname(space, '?')) + debug(" operror-value: " + space.str_w(space.str(e.w_value))) return 1 return space.int_w(w_exitcode) From hpk at codespeak.net Sat Jul 30 20:22:27 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 20:22:27 +0200 (CEST) Subject: [pypy-svn] r15433 - pypy/dist/pypy/translator/goal Message-ID: <20050730182227.A40F727B75@code1.codespeak.net> Author: hpk Date: Sat Jul 30 20:22:27 2005 New Revision: 15433 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: :-( Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sat Jul 30 20:22:27 2005 @@ -37,7 +37,7 @@ ## con.interact() except OperationError, e: debug("OperationError:") - debug(" operror-type: " + w_type.getname(space, '?')) + debug(" operror-type: " + e.w_type.getname(space, '?')) debug(" operror-value: " + space.str_w(space.str(e.w_value))) return 1 return space.int_w(w_exitcode) From rxe at codespeak.net Sat Jul 30 20:34:40 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 20:34:40 +0200 (CEST) Subject: [pypy-svn] r15434 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730183440.2A0E127B75@code1.codespeak.net> Author: rxe Date: Sat Jul 30 20:34:35 2005 New Revision: 15434 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_class.py Log: * annotator.simplify() is a nono. Rewriting the remove_void() functionality at code generation as now breaks check_graph() * test_classes() updates. * Some better formatting for struct constants. Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 30 20:34:35 2005 @@ -95,8 +95,12 @@ def getdecl(self): startblock = self.graph.startblock returnblock = self.graph.returnblock - inputargs = self.db.repr_arg_multi(startblock.inputargs) - inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) + # XXX hack as per remove_voids() + startblock_inputargs = [a for a in startblock.inputargs + if a.concretetype is not lltype.Void] + + inputargs = self.db.repr_arg_multi(startblock_inputargs) + inputargtypes = self.db.repr_arg_type_multi(startblock_inputargs) returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) result = "%s %s" % (returntype, self.ref) args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] @@ -122,7 +126,7 @@ link.prevblock.exits[0].target != block: blocknames[i] += '_exception_found_branchto_' + self.block_to_name[block] if type_ != "void": - codewriter.phi(arg, type_, names, blocknames) + codewriter.phi(arg, type_, names, blocknames) def write_block_branches(self, codewriter, block): #assert len(block.exits) <= 2 #more exits are possible (esp. in combination with exceptions) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jul 30 20:34:35 2005 @@ -30,7 +30,7 @@ self.translator = translator self.embedexterns = embedexterns # transformations - remove_void(translator) + #remove_void(translator) #rename_extfunc_calls(translator) translator.checkgraphs() ExternalFuncNode.used_external_functions = {} @@ -163,7 +163,6 @@ t = Translator(function) a = t.annotate(annotate) t.specialize() - a.simplify() if view: t.view() return genllvm(t, embedexterns=embedexterns) Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 20:34:35 2005 @@ -166,12 +166,16 @@ "null") def direct_call(self, op): - assert len(op.args) >= 1 + + op_args = [arg for arg in op.args + if arg.concretetype is not lltype.Void] + + assert len(op_args) >= 1 targetvar = self.db.repr_arg(op.result) returntype = self.db.repr_arg_type(op.result) - functionref = self.db.repr_arg(op.args[0]) - argrefs = self.db.repr_arg_multi(op.args[1:]) - argtypes = self.db.repr_arg_type_multi(op.args[1:]) + functionref = self.db.repr_arg(op_args[0]) + argrefs = self.db.repr_arg_multi(op_args[1:]) + argtypes = self.db.repr_arg_type_multi(op_args[1:]) if returntype != "void": self.codewriter.call(targetvar, returntype, functionref, argrefs, argtypes) @@ -179,7 +183,11 @@ self.codewriter.call_void(functionref, argrefs, argtypes) def direct_invoke(self, op): - assert len(op.args) >= 1 + # XXX hack as per remove_voids() + op_args = [arg for arg in op.args + if arg.concretetype is not Void] + + assert len(op_args) >= 1 assert len(self.block.exits) >= 2 #at least one label and one exception label link = self.block.exits[0] @@ -187,9 +195,9 @@ targetvar = self.db.repr_arg(op.result) returntype = self.db.repr_arg_type(op.result) - functionref = self.db.repr_arg(op.args[0]) - argrefs = self.db.repr_arg_multi(op.args[1:]) - argtypes = self.db.repr_arg_type_multi(op.args[1:]) + functionref = self.db.repr_arg(op_args[0]) + argrefs = self.db.repr_arg_multi(op_args[1:]) + argtypes = self.db.repr_arg_type_multi(op_args[1:]) none_label = self.node.block_to_name[link.target] block_label = self.node.block_to_name[self.block] @@ -229,7 +237,7 @@ self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, - [tmpvar2, self.db.repr_arg_type(type)], + [tmpvar2, type.ref], [lltype_of_exception_type, lltype_of_exception_type]) self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) self.codewriter.label(not_this_exception_label) Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sat Jul 30 20:34:35 2005 @@ -142,7 +142,8 @@ def constantvalue(self): """ Returns the constant representation for this node. """ values = self._getvalues() - return "%s {%s}" % (self.get_typerepr(), ", ".join(values)) + all_values = ",\n ".join(values) + return "%s {\n %s\n }\n\n" % (self.get_typerepr(), all_values) # ______________________________________________________________________ # main entry points from genllvm Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jul 30 20:34:35 2005 @@ -212,7 +212,6 @@ c = C(b) return c.a.a - class AA(object): x = 8 def __init__(self): @@ -234,7 +233,7 @@ def class_inherit2(): aa = AA() bb = BB() - return aa.g() + bb.g() + return aa.g() + bb.g() class D(object): def __init__(self, a, length): @@ -266,6 +265,7 @@ ggg.c.append(x) d = ggg.b[1] ggg.a = x + 36 + d + 3 return previous + d + previous1 def degrading_func(obj): Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Sat Jul 30 20:34:35 2005 @@ -6,6 +6,8 @@ from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.llvm2.test import llvmsnippet +#py.log.setconsumer("genllvm", py.log.STDOUT) + class TestClass(object): def test_classsimple(self): f = compile_function(llvmsnippet.class_simple, []) @@ -29,22 +31,21 @@ assert f() == 11 def test_inherit2(self): - py.test.skip("not working yet (segfault)") + py.test.skip("function redefinition problem") f = compile_function(llvmsnippet.class_inherit2, []) - assert f() == 11 + assert f() == 1 def test_method_of_base_class(self): - py.test.skip("not working yet (segfault)") - f = compile_function(llvmsnippet.method_of_base_class, [], view=True) + py.test.skip("rtyper problem") + f = compile_function(llvmsnippet.method_of_base_class, []) assert f() == 14 def test_attribute_from_base_class(self): - py.test.skip("not working yet (segfault)") f = compile_function(llvmsnippet.attribute_from_base_class, []) assert f() == 4 def test_direct_call_of_virtual_method(self): - py.test.skip("not working yet (segfault)") + py.test.skip("function redefinition problem") f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) assert f() == 14 @@ -63,14 +64,14 @@ assert f(False) == 2 def test_global_instance(self): - py.test.skip("modify global instance not working properly yet") + py.test.skip("function redefinition problems") f = compile_function(llvmsnippet.global_instance, [int]) assert f(-1) == llvmsnippet.global_instance(-1) for i in range(20): assert f(i) == llvmsnippet.global_instance(i) def test_call_degrading_func(self): - py.test.skip("call degrading not working yet") + py.test.skip("rtyper problem") f = compile_function(llvmsnippet.call_degrading_func, [bool]) assert f(True) == llvmsnippet.call_degrading_func(True) #-36 assert f(False) == llvmsnippet.call_degrading_func(False) #14 From ericvrp at codespeak.net Sat Jul 30 21:14:51 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 30 Jul 2005 21:14:51 +0200 (CEST) Subject: [pypy-svn] r15435 - pypy/dist/pypy/documentation Message-ID: <20050730191451.0E69127B6A@code1.codespeak.net> Author: ericvrp Date: Sat Jul 30 21:14:50 2005 New Revision: 15435 Modified: pypy/dist/pypy/documentation/svn-help.txt Log: - Add missing comment about [auto-props]. - Be a little more verbose Modified: pypy/dist/pypy/documentation/svn-help.txt ============================================================================== --- pypy/dist/pypy/documentation/svn-help.txt (original) +++ pypy/dist/pypy/documentation/svn-help.txt Sat Jul 30 21:14:50 2005 @@ -143,10 +143,9 @@ enable-auto-props = yes + [auto-props] *.txt = svn:eol-style=native - -and add a line for .py files. - + *.py = svn:eol-style=native .. _website: http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B259403 From cfbolz at codespeak.net Sat Jul 30 21:20:10 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 21:20:10 +0200 (CEST) Subject: [pypy-svn] r15436 - in pypy/dist/pypy/rpython: . test Message-ID: <20050730192010.0247527B6A@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 21:20:07 2005 New Revision: 15436 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (pedronis, cfbolz): fixed string and list comparisons to make it not segfault if one of the compared elements is None (a Null pointer). Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jul 30 21:20:07 2005 @@ -579,6 +579,10 @@ # Comparison. def ll_listeq(l1, l2, eqfn): + if not l1 and not l2: + return True + if not l1 or not l2: + return False len1 = len(l1.items) len2 = len(l2.items) if len1 != len2: Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jul 30 21:20:07 2005 @@ -568,6 +568,10 @@ 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) @@ -586,6 +590,10 @@ return len1 - len2 def ll_streq(s1, s2): + if not s1 and not s2: + return True + if not s1 or not s2: + return False len1 = len(s1.chars) len2 = len(s2.chars) if len1 != len2: Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sat Jul 30 21:20:07 2005 @@ -253,12 +253,13 @@ def test_list_compare(): def fn(i, j, neg=False): - s1 = [[1, 2, 3], [4, 5, 1]] - s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], [7, 1, 1, 8, 9, 10]] + s1 = [[1, 2, 3], [4, 5, 1], None] + s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], + [7, 1, 1, 8, 9, 10], None] if neg: return s1[i] != s2[i] return s1[i] == s2[j] - for i in range(2): - for j in range(6): + for i in range(3): + for j in range(7): for case in False, True: res = interpret(fn, [i,j,case]) assert res is fn(i, j, case) 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 Jul 30 21:20:07 2005 @@ -124,11 +124,11 @@ def test_str_compare(): def fn(i, j): - s1 = ['one', 'two'] - s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + s1 = ['one', 'two', None] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar', None] return s1[i] == s2[j] - for i in range(2): - for j in range(6): + for i in range(3): + for j in range(7): res = interpret(fn, [i,j]) assert res is fn(i, j) From hpk at codespeak.net Sat Jul 30 21:20:45 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 30 Jul 2005 21:20:45 +0200 (CEST) Subject: [pypy-svn] r15437 - pypy/dist/pypy/translator/pyrex/test Message-ID: <20050730192045.7ADB327B6A@code1.codespeak.net> Author: hpk Date: Sat Jul 30 21:20:44 2005 New Revision: 15437 Modified: pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py Log: get rid of usage of py.test.skip_on_error because it is to be removed from py.test soon Modified: pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py ============================================================================== --- pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py (original) +++ pypy/dist/pypy/translator/pyrex/test/test_sourcegen.py Sat Jul 30 21:20:44 2005 @@ -29,8 +29,7 @@ block.operations.append(op) block.closeblock(Link([result], fun.returnblock)) result = GenPyrex(fun).emitcode() - mod = py.test.skip_on_error( - make_module_from_pyxstring, 'test_source1', udir, result) + mod = make_module_from_pyxstring('test_source1', udir, result) assert mod.f(1) == 2 def test_if(self): @@ -55,8 +54,7 @@ Link([j], fun.returnblock, True)) result = GenPyrex(fun).emitcode() - mod = py.test.skip_on_error( - make_module_from_pyxstring, 'test_source2', udir, result) + mod = make_module_from_pyxstring('test_source2', udir, result) assert mod.f(-1, 42) == 42 assert mod.f(3, 5) == 3 @@ -92,7 +90,6 @@ whileblock.closeblock(Link([i, sum], headerblock)) result = GenPyrex(fun).emitcode() - mod = py.test.skip_on_error( - make_module_from_pyxstring, 'test_source4', udir, result) + mod = make_module_from_pyxstring('test_source4', udir, result) assert mod.f(3) == 6 assert mod.f(-3) == 0 From pedronis at codespeak.net Sat Jul 30 21:36:32 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 30 Jul 2005 21:36:32 +0200 (CEST) Subject: [pypy-svn] r15438 - pypy/dist/pypy/interpreter Message-ID: <20050730193632.5928A27B6A@code1.codespeak.net> Author: pedronis Date: Sat Jul 30 21:36:30 2005 New Revision: 15438 Modified: pypy/dist/pypy/interpreter/argument.py Log: avoid a method demoting warning. Modified: pypy/dist/pypy/interpreter/argument.py ============================================================================== --- pypy/dist/pypy/interpreter/argument.py (original) +++ pypy/dist/pypy/interpreter/argument.py Sat Jul 30 21:36:30 2005 @@ -266,7 +266,9 @@ # class ArgErr(Exception): - pass + + def getmsg(self, args, fnname): + raise NotImplementedError class ArgErrCount(ArgErr): From pedronis at codespeak.net Sat Jul 30 21:37:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 30 Jul 2005 21:37:28 +0200 (CEST) Subject: [pypy-svn] r15439 - pypy/dist/pypy/objspace/std Message-ID: <20050730193728.AABDC27B6A@code1.codespeak.net> Author: pedronis Date: Sat Jul 30 21:37:27 2005 New Revision: 15439 Modified: pypy/dist/pypy/objspace/std/dictobject.py Log: avoid method demoting warning Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Sat Jul 30 21:37:27 2005 @@ -319,6 +319,9 @@ w_self.len = w_dictobject.used w_self.pos = 0 + def return_entry(w_self, entry): + raise NotImplementedError + registerimplementation(W_DictIterObject) class W_DictIter_Keys(W_DictIterObject): From cfbolz at codespeak.net Sat Jul 30 21:37:57 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 30 Jul 2005 21:37:57 +0200 (CEST) Subject: [pypy-svn] r15440 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20050730193757.3C88F27B6A@code1.codespeak.net> Author: cfbolz Date: Sat Jul 30 21:37:53 2005 New Revision: 15440 Added: pypy/dist/pypy/rpython/memory/simulator.py pypy/dist/pypy/rpython/memory/test/test_simulator.py Modified: pypy/dist/pypy/rpython/memory/lladdress.py pypy/dist/pypy/rpython/memory/test/test_address.py Log: started writing the memory simulator. Modified: pypy/dist/pypy/rpython/memory/lladdress.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lladdress.py (original) +++ pypy/dist/pypy/rpython/memory/lladdress.py Sat Jul 30 21:37:53 2005 @@ -1,10 +1,33 @@ from pypy.rpython import lltype - - class Address(object): - pass + 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 + else: + return object.__new__(cls) + + def __init__(self, intaddress=0): + self.intaddress = intaddress + + def __add__(self, offset): + assert isinstance(offset, int) + return Address(self.intaddress + offset) + + def __sub__(self, other): + if isinstance(other, int): + return Address(self.intaddress + offset) + else: + return self.intaddress - other.intaddress + def __cmp__(self, other): + return cmp(self.intaddress, other.intaddress) + +NULL = Address() supported_access_types = {"signed": lltype.Signed, "unsigned": lltype.Unsigned, @@ -12,8 +35,6 @@ "address": Address, } -NULL = Address() - def raw_malloc(size): pass Added: pypy/dist/pypy/rpython/memory/simulator.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/simulator.py Sat Jul 30 21:37:53 2005 @@ -0,0 +1,46 @@ +import array + +# all addresses in the simulator are just ints + +# possible chars in status are: +# 'u': uninitialized +# 'i': initialized + +class MemorySimulatorError(Exception): + pass + +class MemoryBlock(object): + def __init__(self, baseaddress, size): + self.baseaddress = baseaddress + self.size = size + self.memory = array.array("c", "\x00" * size) + self.status = array.array("c", "u" * size) + self.freed = False + + def free(self): + self.freed = True + self.memory = None + self.status = None + + def getbytes(self, offset, size): + assert offset >= 0 + if self.freed: + raise MemorySimulatorError, "trying to access free memory" + if offset + size >= self.size: + raise MemorySimulatorError, "trying to access memory between blocks" + if "u" in self.status[offset: offset+size]: + raise MemorySimulatorError, "trying to access uninitialized memory" + return self.memory[offset:offset+size].tostring() + + def setbytes(self, offset, value): + assert offset >= 0 + if self.freed: + raise MemorySimulatorError, "trying to access free memory" + if offset + len(value) >= self.size: + raise MemorySimulatorError, "trying to access memory between blocks" + a = array.array("c") + a.fromstring(value) + s = array.array("c") + s.fromstring("i" * len(value)) + self.memory[offset:offset + len(value)] = a + self.status[offset:offset + len(value)] = s 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 Sat Jul 30 21:37:53 2005 @@ -3,24 +3,26 @@ from pypy.annotation import model as annmodel from pypy.translator.annrpython import RPythonAnnotator from pypy.objspace.flow import FlowObjSpace -from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL, raw_memcopy +from pypy.rpython.memory.lladdress import Address, NULL +from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy class TestAddressAnnotation(object): - def test_raw_malloc(self): + def test_null(self): def f(): - return raw_malloc(100) + return NULL a = RPythonAnnotator() s = a.build_types(f, []) assert isinstance(s, annmodel.SomeAddress) - assert not s.is_null + assert s.is_null + assert f() is NULL - def test_null(self): + def test_raw_malloc(self): def f(): - return NULL + return raw_malloc(100) a = RPythonAnnotator() s = a.build_types(f, []) assert isinstance(s, annmodel.SomeAddress) - assert s.is_null + assert not s.is_null def test_raw_free(self): def f(addr): @@ -93,5 +95,12 @@ return NULL < NULL + offset a = RPythonAnnotator() s = a.build_types(f, [annmodel.SomeInteger()]) - a.translator.view() assert isinstance(s, annmodel.SomeBool) + assert f(1) + assert not f(0) + assert not f(-1) + +class TestAddressSimulation(object): + def test_null_is_singleton(self): + assert Address() is NULL + assert Address() is Address(0) Added: pypy/dist/pypy/rpython/memory/test/test_simulator.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/test/test_simulator.py Sat Jul 30 21:37:53 2005 @@ -0,0 +1,10 @@ +import py +from pypy.rpython.memory.simulator import MemoryBlock + +class TestMemoryBlock(object): + def test_getsetbyte(self): + block = MemoryBlock(1, 1000) + block.setbytes(1, "hello") + assert block.getbytes(1, 5) == "hello" + + From rxe at codespeak.net Sat Jul 30 21:44:46 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 21:44:46 +0200 (CEST) Subject: [pypy-svn] r15441 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730194446.361B127B6A@code1.codespeak.net> Author: rxe Date: Sat Jul 30 21:44:42 2005 New Revision: 15441 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_class.py pypy/dist/pypy/translator/llvm2/test/test_lltype.py Log: Various fixes to make all tests in test_class work. Passed arigo's test_aliasing2. Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jul 30 21:44:42 2005 @@ -34,7 +34,7 @@ self.append(" %s:" % name) def globalinstance(self, name, typeandata): - self.append("%s = constant %s" % (name, typeandata)) + self.append("%s = global %s" % (name, typeandata)) def structdef(self, name, typereprs): self.append("%s = type { %s }" %(name, ", ".join(typereprs))) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jul 30 21:44:42 2005 @@ -32,7 +32,7 @@ def __init__(self, db, value): self.db = db self.value = value - self.ref = "%" + value._name + self.ref = "%" + value.graph.name self.graph = value.graph remove_same_as(self.graph) remove_double_links(self.db._translator, self.graph) Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jul 30 21:44:42 2005 @@ -188,7 +188,7 @@ a = A() return a.a -class B(object): +class B(A): def __init__(self): self.a = 14 self.b = False @@ -201,7 +201,7 @@ b.change(newa) return b.a -class C(object): +class C(A): def __init__(self, a): self.a = a self.b = 1 @@ -233,7 +233,7 @@ def class_inherit2(): aa = AA() bb = BB() - return aa.g() + bb.g() + return aa.g() - bb.g() class D(object): def __init__(self, a, length): @@ -268,6 +268,20 @@ 36 + d + 3 return previous + d + previous1 +class FFF: pass +fff = FFF() +fff.x = 10 + +def getset(x): + res = fff.x + fff.x = x + return res + +def testgetset(y): + res1 = getset(y) + res2 = getset(y) + return res1 + res2 + def degrading_func(obj): if isinstance(obj, C): return obj.a + obj.b Modified: pypy/dist/pypy/translator/llvm2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_class.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_class.py Sat Jul 30 21:44:42 2005 @@ -31,12 +31,10 @@ assert f() == 11 def test_inherit2(self): - py.test.skip("function redefinition problem") f = compile_function(llvmsnippet.class_inherit2, []) assert f() == 1 def test_method_of_base_class(self): - py.test.skip("rtyper problem") f = compile_function(llvmsnippet.method_of_base_class, []) assert f() == 14 @@ -45,7 +43,6 @@ assert f() == 4 def test_direct_call_of_virtual_method(self): - py.test.skip("function redefinition problem") f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) assert f() == 14 @@ -64,17 +61,21 @@ assert f(False) == 2 def test_global_instance(self): - py.test.skip("function redefinition problems") f = compile_function(llvmsnippet.global_instance, [int]) assert f(-1) == llvmsnippet.global_instance(-1) for i in range(20): - assert f(i) == llvmsnippet.global_instance(i) + x = f(i) + y = llvmsnippet.global_instance(i) + assert x == y + + def test_getset(self): + f = compile_function(llvmsnippet.testgetset, [int]) + assert f(15) == 25 def test_call_degrading_func(self): - py.test.skip("rtyper problem") f = compile_function(llvmsnippet.call_degrading_func, [bool]) - assert f(True) == llvmsnippet.call_degrading_func(True) #-36 - assert f(False) == llvmsnippet.call_degrading_func(False) #14 + assert f(True) == llvmsnippet.call_degrading_func(True) + assert f(False) == llvmsnippet.call_degrading_func(False) def test_circular_classdef(self): f = compile_function(llvmsnippet.circular_classdef, []) Modified: pypy/dist/pypy/translator/llvm2/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_lltype.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_lltype.py Sat Jul 30 21:44:42 2005 @@ -116,6 +116,20 @@ assert f(2) == 0 assert f(3) == 17 +def test_aliasing2(): + B = lltype.Struct('B', ('x', lltype.Signed)) + A = lltype.Array(B) + C = lltype.Struct('C', ('x', lltype.Signed), ('bptr', lltype.Ptr(B))) + global_a = lltype.malloc(A, 5, immortal=True) + global_c = lltype.malloc(C, immortal=True) + global_c.bptr = global_a[3] + def aliasing(i): + global_c.bptr.x = 17 + return global_a[i].x + f = compile_function(aliasing, [int], embedexterns=False) + assert f(2) == 0 + assert f(3) == 17 + def test_array_constant(): A = lltype.GcArray(lltype.Signed) a = lltype.malloc(A, 3) From rxe at codespeak.net Sat Jul 30 21:50:41 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 21:50:41 +0200 (CEST) Subject: [pypy-svn] r15442 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050730195041.DE83327B6A@code1.codespeak.net> Author: rxe Date: Sat Jul 30 21:50:40 2005 New Revision: 15442 Modified: pypy/dist/pypy/translator/llvm2/opwriter.py Log: Double oops. Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 21:50:40 2005 @@ -185,7 +185,7 @@ def direct_invoke(self, op): # XXX hack as per remove_voids() op_args = [arg for arg in op.args - if arg.concretetype is not Void] + if arg.concretetype is not lltype.Void] assert len(op_args) >= 1 assert len(self.block.exits) >= 2 #at least one label and one exception label @@ -237,7 +237,7 @@ self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, - [tmpvar2, type.ref], + [etype.ref, tmpvar2], [lltype_of_exception_type, lltype_of_exception_type]) self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) self.codewriter.label(not_this_exception_label) From arigo at codespeak.net Sat Jul 30 21:58:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Jul 2005 21:58:57 +0200 (CEST) Subject: [pypy-svn] r15443 - pypy/dist/pypy/translator/tool Message-ID: <20050730195857.3154927B6A@code1.codespeak.net> Author: arigo Date: Sat Jul 30 21:58:55 2005 New Revision: 15443 Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: Refactored make_module_from_c() into two independently callable functions. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat Jul 30 21:58:55 2005 @@ -2,7 +2,7 @@ import py -import os, sys, inspect, re +import os, sys, inspect, re, imp from pypy.translator.tool import stdoutcapture debug = 0 @@ -36,7 +36,7 @@ opt = '-O0' gcv['OPT'] = opt -def make_module_from_c(cfile, include_dirs=None): +def compile_c_module(cfile, modname, include_dirs=None): #try: # from distutils.log import set_threshold # set_threshold(10000) @@ -47,10 +47,8 @@ include_dirs = [] dirpath = cfile.dirpath() - lastdir = py.path.local() - os.chdir(str(dirpath)) + lastdir = dirpath.chdir() try: - modname = cfile.purebasename if debug: print "modname", modname c = stdoutcapture.Capture(mixed_out_err = True) try: @@ -116,19 +114,26 @@ fdump.close() # XXX do we need to do some check on fout/ferr? # XXX not a nice way to import a module - if debug: print "inserting path to sys.path", dirpath - sys.path.insert(0, '.') - if debug: print "import %(modname)s as testmodule" % locals() - exec "import %(modname)s as testmodule" % locals() - sys.path.pop(0) except: print data raise finally: - os.chdir(str(lastdir)) - #if not debug: - #dirpath.rmtree() - return testmodule + lastdir.chdir() + +def make_module_from_c(cfile, include_dirs=None): + cfile = py.path.local(cfile) + modname = cfile.purebasename + compile_c_module(cfile, modname, include_dirs) + return import_module_from_directory(cfile.dirpath(), modname) + +def import_module_from_directory(dir, modname): + file, pathname, description = imp.find_module(modname, [str(dir)]) + try: + mod = imp.load_module(modname, file, pathname, description) + finally: + if file: + file.close() + return mod def make_c_from_pyxfile(pyxfile): from pypy.translator.pyrex import genpyrex From rxe at codespeak.net Sat Jul 30 21:59:22 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 21:59:22 +0200 (CEST) Subject: [pypy-svn] r15444 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730195922.837D027B6A@code1.codespeak.net> Author: rxe Date: Sat Jul 30 21:59:20 2005 New Revision: 15444 Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Log: Type for extfuncnode and reenable test_extfunc tests. Modified: pypy/dist/pypy/translator/llvm2/extfuncnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/extfuncnode.py (original) +++ pypy/dist/pypy/translator/llvm2/extfuncnode.py Sat Jul 30 21:59:20 2005 @@ -1,9 +1,9 @@ import py -from pypy.translator.llvm2.node import LLVMNode +from pypy.translator.llvm2.node import ConstantLLVMNode from pypy.translator.llvm2.log import log log = log.extfuncnode -class ExternalFuncNode(LLVMNode): +class ExternalFuncNode(ConstantLLVMNode): used_external_functions = {} def __init__(self, db, value): Modified: pypy/dist/pypy/translator/llvm2/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_extfunc.py Sat Jul 30 21:59:20 2005 @@ -10,9 +10,6 @@ py.log.setconsumer("genllvm", py.log.STDOUT) py.log.setconsumer("genllvm database prepare", None) -def setup_module(module): - py.test.skip("tmp - just to sync up changes") - def test_external_function_ll_os_dup(): def fn(): return os.dup(0) From arigo at codespeak.net Sat Jul 30 22:35:51 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Jul 2005 22:35:51 +0200 (CEST) Subject: [pypy-svn] r15445 - pypy/dist/pypy/translator/c/src Message-ID: <20050730203551.92B1B27B6A@code1.codespeak.net> Author: arigo Date: Sat Jul 30 22:35:50 2005 New Revision: 15445 Modified: pypy/dist/pypy/translator/c/src/int.h Log: Casting from char to int produced negative numbers if the compiler's chars are signed. 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 Sat Jul 30 22:35:50 2005 @@ -156,11 +156,11 @@ #define OP_CAST_BOOL_TO_UINT(x,r,err) r = (unsigned long)(x); #define OP_CAST_UINT_TO_INT(x,r,err) r = (long)(x); #define OP_CAST_INT_TO_UINT(x,r,err) r = (unsigned long)(x); -#define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)((unsigned char)(x)); #define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); #define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ -#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (x); +#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (long)((unsigned long)(x)); /*?*/ #define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (Py_UCS4)(x); /* bool operations */ From rxe at codespeak.net Sat Jul 30 22:38:25 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 30 Jul 2005 22:38:25 +0200 (CEST) Subject: [pypy-svn] r15446 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050730203825.9BD9E27B6A@code1.codespeak.net> Author: rxe Date: Sat Jul 30 22:38:15 2005 New Revision: 15446 Modified: pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Log: setfield should skip voids. enable skipping pbc test. Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sat Jul 30 22:38:15 2005 @@ -301,12 +301,14 @@ struct, structtype = self.db.repr_argwithtype(op.args[0]) fieldnames = list(op.args[0].concretetype.TO._names) index = fieldnames.index(op.args[1].value) - self.codewriter.getelementptr(tmpvar, structtype, struct, - ("uint", index)) valuevar, valuetype = self.db.repr_argwithtype(op.args[2]) - assert valuetype != "void" - self.codewriter.store(valuetype, valuevar, tmpvar) - + if valuetype != "void": + self.codewriter.getelementptr(tmpvar, structtype, struct, + ("uint", index)) + self.codewriter.store(valuetype, valuevar, tmpvar) + else: + self.codewriter.comment("***Skipping operation setfield()***") + def getarrayitem(self, op): array, arraytype = self.db.repr_argwithtype(op.args[0]) index = self.db.repr_arg(op.args[1]) @@ -316,6 +318,8 @@ ("uint", 1), (indextype, index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) + #XXX These should skip too if the case comes up + assert targettype != "void" self.codewriter.load(targetvar, targettype, tmpvar) def getarraysubstruct(self, op): @@ -337,6 +341,8 @@ valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) + #XXX These should skip too if the case comes up + assert valuetype != "void" self.codewriter.store(valuetype, valuevar, tmpvar) def getarraysize(self, op): Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm1.py Sat Jul 30 22:38:15 2005 @@ -89,7 +89,6 @@ assert f(3) == 8 def test_pbc_function2(self): - py.test.skip("pbc circular not working yet") f = compile_function(llvmsnippet.pbc_function2, [int]) assert f(0) == 13 assert f(1) == 15 From pedronis at codespeak.net Sat Jul 30 23:36:35 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 30 Jul 2005 23:36:35 +0200 (CEST) Subject: [pypy-svn] r15447 - in pypy/dist/pypy: interpreter module/time module/time/test Message-ID: <20050730213635.A1EE227B6A@code1.codespeak.net> Author: pedronis Date: Sat Jul 30 23:36:30 2005 New Revision: 15447 Added: pypy/dist/pypy/module/time/ (props changed) pypy/dist/pypy/module/time/__init__.py (contents, props changed) pypy/dist/pypy/module/time/interp_time.py (contents, props changed) pypy/dist/pypy/module/time/test/ (props changed) pypy/dist/pypy/module/time/test/test_time.py (contents, props changed) Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: start of an implementation for time module Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Sat Jul 30 23:36:30 2005 @@ -165,6 +165,7 @@ if self.options.nofaking: l.append('posix') l.append('math') + l.append('time') for name in self.options.usemodules: if name not in l: Added: pypy/dist/pypy/module/time/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/time/__init__.py Sat Jul 30 23:36:30 2005 @@ -0,0 +1,16 @@ +# Package initialisation +from pypy.interpreter.mixedmodule import MixedModule + +import time + +class Module(MixedModule): + """time module""" + + appleveldefs = { + } + + interpleveldefs = { + 'clock' : 'interp_time.clock', + 'time' : 'interp_time.time_', + } + Added: pypy/dist/pypy/module/time/interp_time.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/time/interp_time.py Sat Jul 30 23:36:30 2005 @@ -0,0 +1,7 @@ +import time + +def clock(space): + return space.wrap(time.clock()) + +def time_(space): + return space.wrap(time.time()) Added: pypy/dist/pypy/module/time/test/test_time.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/time/test/test_time.py Sat Jul 30 23:36:30 2005 @@ -0,0 +1,20 @@ +from pypy.objspace.std import StdObjSpace +import time + +def setup_module(mod): + mod.space = StdObjSpace(usemodules=['time']) + +class TestTime: + + def test_clock(self): + t0 = time.clock() + w_t1 = space.appexec([], """(): import time; return time.clock()""") + t2 = time.clock() + assert t0 <= space.unwrap(w_t1) <= t2 + + def test_time(self): + t0 = time.time() + w_t1 = space.appexec([], """(): import time; return time.time()""") + t2 = time.time() + assert t0 <= space.unwrap(w_t1) <= t2 + From cfbolz at codespeak.net Sun Jul 31 02:19:30 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 02:19:30 +0200 (CEST) Subject: [pypy-svn] r15451 - in pypy/dist/pypy: annotation rpython/memory rpython/memory/test Message-ID: <20050731001930.9D1B527B5C@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 02:19:27 2005 New Revision: 15451 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/memory/lladdress.py pypy/dist/pypy/rpython/memory/simulator.py pypy/dist/pypy/rpython/memory/test/test_address.py pypy/dist/pypy/rpython/memory/test/test_simulator.py Log: continued (more or less finished) the memory simulator: memory access is done by doing: address.signed[offset] = value address.signed[offset] this will check for all sorts of errors. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sun Jul 31 02:19:27 2005 @@ -618,6 +618,14 @@ def union((s_addr1, s_addr2)): return SomeAddress(is_null=s_addr1.is_null and s_addr2.is_null) + def sub((s_addr1, s_addr2)): + if s_addr1.is_null and s_addr2.is_null: + return getbookkeeper().immutablevalue(0) + return SomeInteger() + + def is_((s_addr1, s_addr2)): + assert False, "comparisons with is not supported by addresses" + class __extend__(pairtype(SomeTypedAddressAccess, SomeTypedAddressAccess)): def union((s_taa1, s_taa2)): assert s_taa1.type == s_taa2.type @@ -640,9 +648,3 @@ def sub((s_addr, s_int)): return SomeAddress(is_null=False) -class __extend__(pairtype(SomeAddress, SomeAddress)): - def sub((s_addr1, s_addr2)): - if s_addr1.is_null and s_addr2.is_null: - return getbookkeeper().immutablevalue(0) - return SomeInteger() - Modified: pypy/dist/pypy/rpython/memory/lladdress.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lladdress.py (original) +++ pypy/dist/pypy/rpython/memory/lladdress.py Sun Jul 31 02:19:27 2005 @@ -1,4 +1,8 @@ +import struct from pypy.rpython import lltype +from pypy.rpython.memory.simulator import MemorySimulator +from pypy.rpython.rarithmetic import r_uint + class Address(object): def __new__(cls, intaddress=0): @@ -14,34 +18,81 @@ def __init__(self, intaddress=0): self.intaddress = intaddress + def _getintattr(self): #needed to make _accessor easy + return self.intaddress + def __add__(self, offset): assert isinstance(offset, int) return Address(self.intaddress + offset) def __sub__(self, other): if isinstance(other, int): - return Address(self.intaddress + offset) + return Address(self.intaddress - other) else: return self.intaddress - other.intaddress def __cmp__(self, other): return cmp(self.intaddress, other.intaddress) -NULL = Address() + def __repr__(self): + return "" % self.intaddress +class _accessor(object): + def __init__(self, addr): + self.intaddress = addr.intaddress + def __getitem__(self, offset): + result = simulator.getstruct(self.format, + self.intaddress + offset * self.size) + return self.convert_from(result[0]) + + def __setitem__(self, offset, value): + simulator.setstruct(self.format, self.intaddress + offset * self.size, + self.convert_to(value)) + +class _signed_accessor(_accessor): + format = "i" + size = struct.calcsize("i") + convert_from = int + convert_to = int + +class _unsigned_accessor(_accessor): + format = "I" + size = struct.calcsize("I") + convert_from = r_uint + convert_to = long + +class _char_accessor(_accessor): + format = "c" + size = struct.calcsize("c") + convert_from = str + convert_to = str + +class _address_accessor(_accessor): + format = "P" + size = struct.calcsize("P") + convert_from = Address + convert_to = Address._getintattr + +Address.signed = property(_signed_accessor) +Address.unsigned = property(_unsigned_accessor) +Address.char = property(_char_accessor) +Address.address = property(_address_accessor) -supported_access_types = {"signed": lltype.Signed, - "unsigned": lltype.Unsigned, - "char": lltype.Char, - "address": Address, - } + +NULL = Address() +simulator = MemorySimulator() def raw_malloc(size): - pass + return Address(simulator.malloc(size)) def raw_free(addr): - pass + simulator.free(addr.intaddress) def raw_memcopy(addr1, addr2, size): pass +supported_access_types = {"signed": lltype.Signed, + "unsigned": lltype.Unsigned, + "char": lltype.Char, + "address": Address, + } Modified: pypy/dist/pypy/rpython/memory/simulator.py ============================================================================== --- pypy/dist/pypy/rpython/memory/simulator.py (original) +++ pypy/dist/pypy/rpython/memory/simulator.py Sun Jul 31 02:19:27 2005 @@ -1,4 +1,5 @@ import array +import struct # all addresses in the simulator are just ints @@ -18,6 +19,8 @@ self.freed = False def free(self): + if self.freed: + raise MemorySimulatorError, "trying to free already freed memory" self.freed = True self.memory = None self.status = None @@ -44,3 +47,51 @@ s.fromstring("i" * len(value)) self.memory[offset:offset + len(value)] = a self.status[offset:offset + len(value)] = s + +class MemorySimulator(object): + def __init__(self): + self.blocks = [] + self.freememoryaddress = 4 + + def find_block(self, address): + lo = 0 + hi = len(self.blocks) + while lo < hi: + mid = (lo + hi) // 2 + block = self.blocks[mid] + if address < block.baseaddress: + hi = mid + elif address < block.baseaddress + block.size: + return block + else: + lo = mid + return self.blocks[mid] + + def malloc(self, size): + result = self.freememoryaddress + self.blocks.append(MemoryBlock(result, size)) + self.freememoryaddress += size + return result + + def free(self, baseaddress): + if baseaddress == 0: + raise MemorySimulatorError, "trying to free NULL address" + block = self.find_block(baseaddress) + if baseaddress != block.baseaddress: + raise MemorySimulatorError, "trying to free address not malloc'ed" + block.free() + + def getstruct(self, fmt, address): + block = self.find_block(address) + offset = address - block.baseaddress + size = struct.calcsize(fmt) + return struct.unpack(fmt, block.getbytes(offset, size)) + + def setstruct(self, fmt, address, *types): + block = self.find_block(address) + offset = address - block.baseaddress + block.setbytes(offset, struct.pack(fmt, *types)) + + def memcopy(self, address1, address2, size): + data = self.getstruct("c" * size, address1) + self.setstruct("c" * size, address2, *data) 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 Sun Jul 31 02:19:27 2005 @@ -1,10 +1,12 @@ import py +import sys from pypy.annotation import model as annmodel from pypy.translator.annrpython import RPythonAnnotator from pypy.objspace.flow import FlowObjSpace from pypy.rpython.memory.lladdress import Address, NULL from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy +from pypy.rpython.memory.simulator import MemorySimulatorError class TestAddressAnnotation(object): def test_null(self): @@ -32,6 +34,7 @@ a = RPythonAnnotator() py.test.raises(AssertionError, a.build_types, f, [annmodel.SomeAddress(is_null=True)]) + py.test.raises(MemorySimulatorError, f, NULL) def test_memcopy(self): def f(addr1, addr2): @@ -61,11 +64,12 @@ s_false.const = False s = a.build_types(f, [bool, bool]) assert isinstance(s, annmodel.SomeAddress) - assert not s.is_null + assert not s.is_null a = RPythonAnnotator() s = a.build_types(f, [s_true, bool]) assert isinstance(s, annmodel.SomeAddress) assert s.is_null + assert f(True, False) == NULL a = RPythonAnnotator() s = a.build_types(f, [s_false, bool]) assert isinstance(s, annmodel.SomeAddress) @@ -82,13 +86,16 @@ def test_address_arithmetic(self): def f(offset, char): - addr = raw_malloc(offset * 2 + 1) + addr = raw_malloc(10000) same_offset = (addr + offset) - addr addr.char[offset] = char return (addr + same_offset).char[0] a = RPythonAnnotator() s = a.build_types(f, [annmodel.SomeInteger(), annmodel.SomeChar()]) assert isinstance(s, annmodel.SomeChar) + assert f(0, "c") == "c" + assert f(123, "c") == "c" + def test_address_comparison(self): def f(offset): @@ -104,3 +111,17 @@ def test_null_is_singleton(self): assert Address() is NULL assert Address() is Address(0) + + def test_memory_access(self): + addr = raw_malloc(1000) + addr.signed[0] = -1 + assert addr.unsigned[0] == sys.maxint * 2 + 1 + addr.address[0] = addr + assert addr.address[0] == addr + + def test_pointer_arithmetic(self): + addr = raw_malloc(100) + assert addr + 10 - 10 == addr + addr.char[10] = "c" + assert (addr + 10).char[0] == "c" + Modified: pypy/dist/pypy/rpython/memory/test/test_simulator.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_simulator.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_simulator.py Sun Jul 31 02:19:27 2005 @@ -1,10 +1,57 @@ import py -from pypy.rpython.memory.simulator import MemoryBlock +from pypy.rpython.memory.simulator import * class TestMemoryBlock(object): def test_getsetbyte(self): - block = MemoryBlock(1, 1000) + block = MemoryBlock(1, 100) block.setbytes(1, "hello") assert block.getbytes(1, 5) == "hello" - - + #uninitialized memory: + py.test.raises(MemorySimulatorError, block.getbytes, 2, 5) + #access over block borders: + py.test.raises(MemorySimulatorError, block.setbytes, 98, "long string") + #accessing freed memory: + block.free() + py.test.raises(MemorySimulatorError, block.getbytes, 2, 5) + #freeing free block: + py.test.raises(MemorySimulatorError, block.getbytes, 2, 5) + +class TestMemorySimulator(object): + def test_find_block(self): + simulator = MemorySimulator() + for size in [100, 100, 200, 300, 100, 50]: + simulator.malloc(size) + for address in [12, 99, 110, 190, 210, 310, 420, 450, 510, 630, 710]: + block = simulator.find_block(address) + assert block.baseaddress <= address < block.baseaddress + block.size + + def test_malloc(self): + simulator = MemorySimulator() + for size in [2, 4, 8, 16, 32, 64, 128]: + baseaddress = simulator.malloc(size) + block = simulator.find_block(baseaddress) + assert block.size == size + + def test_set_get_struct(self): + simulator = MemorySimulator() + address = simulator.malloc(100) + simulator.setstruct("iic", address, 1, 2, "a") + assert simulator.getstruct("iic", address) == (1, 2, "a") + + def test_free(self): + simulator = MemorySimulator() + addr = simulator.malloc(100) + simulator.free(addr) + py.test.raises(MemorySimulatorError, simulator.free, addr) + py.test.raises(MemorySimulatorError, simulator.free, 0) + + def test_memcopy(self): + simulator = MemorySimulator() + addr1 = simulator.malloc(1000) + addr2 = simulator.malloc(500) + simulator.setstruct("iii", addr1, 1, 2, 3) + simulator.memcopy(addr1, addr1 + 500, struct.calcsize("iii")) + simulator.memcopy(addr1 + 500, addr2, struct.calcsize("iii")) + assert simulator.getstruct("iii", addr1) == (1, 2, 3) + assert simulator.getstruct("iii", addr1 + 500) == (1, 2, 3) + assert simulator.getstruct("iii", addr2) == (1, 2, 3) From arigo at codespeak.net Sun Jul 31 11:53:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Jul 2005 11:53:40 +0200 (CEST) Subject: [pypy-svn] r15452 - in pypy/dist/pypy/lib: _stablecompiler test2 Message-ID: <20050731095340.94DF527B6A@code1.codespeak.net> Author: arigo Date: Sun Jul 31 11:53:37 2005 New Revision: 15452 Added: pypy/dist/pypy/lib/test2/test_stablecompiler.py (contents, props changed) Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py Log: Decoding numeric literals needs more care and some tests... Modified: pypy/dist/pypy/lib/_stablecompiler/transformer.py ============================================================================== --- pypy/dist/pypy/lib/_stablecompiler/transformer.py (original) +++ pypy/dist/pypy/lib/_stablecompiler/transformer.py Sun Jul 31 11:53:37 2005 @@ -714,14 +714,7 @@ def atom_number(self, nodelist): ### need to verify this matches compile.c s = nodelist[0][1] - if 'j' in s or 'J' in s: - k = complex(s) - elif '.' in s or 'e' in s or 'E' in s: - k = float(s) - elif 'l' in s or 'L' in s: - k = long(s) - else: - k = int(s) + k = decode_numeric_literal(s) return Const(k, lineno=nodelist[0][2]) def decode_literal(self, lit): @@ -1437,3 +1430,23 @@ else: l.append(debug_tree(elt)) return l + + +def decode_numeric_literal(s): + base = 10 + if len(s) >= 2 and s[0] == '0': + if s[1] in ('x', 'X'): + if s[-1] in ('l', 'L'): + return long(s[2:], 16) + else: + return int(s[2:], 16) + else: + base = 8 + if s[-1] in ('j', 'J'): + return complex(s) + if '.' in s or 'e' in s or 'E' in s: + return float(s) + if s[-1] in ('l', 'L'): + return long(s, base) + else: + return int(s, base) Added: pypy/dist/pypy/lib/test2/test_stablecompiler.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/test2/test_stablecompiler.py Sun Jul 31 11:53:37 2005 @@ -0,0 +1,73 @@ +import autopath +from pypy.lib._stablecompiler.transformer import decode_numeric_literal + + +def test_decode_numeric_literal(): + # decimal integer + numeric_decode('0', 0) + numeric_decode('1', 1) + numeric_decode('9', 9) + numeric_decode('10', 10) + numeric_decode('2117', 2117) + # octal integer + numeric_decode('03', 3) + numeric_decode('010', 8) + numeric_decode('002117', 1103) + # hexadecimal integer + numeric_decode('0x0', 0) + numeric_decode('0XE', 14) + numeric_decode('0x002117', 8471) + # decimal long + numeric_decode('0l', 0L) + numeric_decode('1L', 1L) + numeric_decode('9l', 9L) + numeric_decode('10L', 10L) + numeric_decode('2117l', 2117L) + # octal long + numeric_decode('03L', 3L) + numeric_decode('010l', 8L) + numeric_decode('002117L', 1103L) + # hexadecimal long + numeric_decode('0x0l', 0L) + numeric_decode('0XEL', 14L) + numeric_decode('0x002117l', 8471L) + # automatic long results for ints that are too large + numeric_decode('99999999999999999999999999999999999999999999999999999', + 99999999999999999999999999999999999999999999999999999) + numeric_decode('0xdeadbeef', int('deadbeef', 16)) + numeric_decode('01236417564174623643237641763', + 01236417564174623643237641763) + # floating point + numeric_decode('3.25', 3.25) + numeric_decode('10.', 10.0) + numeric_decode('.015625', 0.015625) + numeric_decode('0.015625', 0.015625) + numeric_decode('00.015625', 0.015625) + numeric_decode('1e100', 1e100) + numeric_decode('1.5625E-2', 0.015625) + numeric_decode('1.5625e-000000000002', 0.015625) + numeric_decode('0e0', 0.0) + # imaginary number + numeric_decode('0j', 0.0j) + numeric_decode('1J', 1.0j) + numeric_decode('9j', 9.0j) + numeric_decode('10J', 10.0j) + numeric_decode('2117j', 2117.0j) + numeric_decode('03J', 3.0j) + numeric_decode('010j', 10.0j) + numeric_decode('002117J', 2117.0j) + numeric_decode('3.25j', 3.25j) + numeric_decode('10.J', 10.0j) + numeric_decode('.015625j', 0.015625j) + numeric_decode('0.015625J', 0.015625j) + numeric_decode('00.015625j', 0.015625j) + numeric_decode('1e100J', 1e100j) + numeric_decode('1.5625E-2j', 0.015625j) + numeric_decode('1.5625e-000000000002J', 0.015625j) + numeric_decode('0e0j', 0.0j) + + +def numeric_decode(string, expected): + result = decode_numeric_literal(string) + assert result == expected + assert type(result) == type(expected) From hpk at codespeak.net Sun Jul 31 13:17:26 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 13:17:26 +0200 (CEST) Subject: [pypy-svn] r15456 - pypy/dist/pypy/documentation/website Message-ID: <20050731111726.0E72727B6A@code1.codespeak.net> Author: hpk Date: Sun Jul 31 13:17:26 2005 New Revision: 15456 Modified: pypy/dist/pypy/documentation/website/news.txt Log: more explicit news title Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sun Jul 31 13:17:26 2005 @@ -9,8 +9,8 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: ../architecture.html#mission-statement -Heidelberg sprint planning -=========================== +Next PyPy Sprint in Heidelberg 22nd-29th August 2005 +====================================================== The next PyPy sprint will take place at the Heidelberg University in Germany from 22nd August to 29th August (both days included). From cfbolz at codespeak.net Sun Jul 31 13:28:10 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 13:28:10 +0200 (CEST) Subject: [pypy-svn] r15457 - in pypy/dist/pypy/rpython: . test Message-ID: <20050731112810.073EC27B6A@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 13:28:07 2005 New Revision: 15457 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: added op_int_mod_ovf_zer. It was found missing by running the llinterpreter on PyPy. It crashed after running for hours :-(. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Jul 31 13:28:07 2005 @@ -57,6 +57,10 @@ opimpls = FunctionByName.copy() opimpls['is_true'] = bool +ops_returning_a_bool = {'gt': True, 'ge': True, + 'lt': True, 'le': True, + 'eq': True, 'ne': True, + 'is_true': True} class LLFrame(object): def __init__(self, graph, args, llinterpreter, f_back=None): @@ -349,7 +353,13 @@ self.make_llexception(ZeroDivisionError()) return self.op_int_floordiv_ovf(a, b) - + def op_int_mod_ovf_zer(self, a, b): + assert type(a) is int + assert type(b) is int + if b == 0: + self.make_llexception(ZeroDivisionError()) + return self.op_int_mod_ovf(a, b) + def op_float_floor(self, b): assert type(b) is float return math.floor(b) @@ -385,10 +395,6 @@ # __________________________________________________________ # primitive operations -ops_returning_a_bool = {'gt': True, 'ge': True, - 'lt': True, 'le': True, - 'eq': True, 'ne': True, - 'is_true': True} for typ in (float, int, r_uint): typname = typ.__name__ Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Sun Jul 31 13:28:07 2005 @@ -279,7 +279,7 @@ res = interpret(g, [-15]) assert res == 15 -def test_ovf_zer(): +def test_div_ovf_zer(): import sys def f(x): try: @@ -294,7 +294,23 @@ assert res == 1 res = interpret(f, [30]) assert res == (-sys.maxint - 1) // 30 - + +def test_mod_ovf_zer(): + import sys + def f(x): + try: + return ovfcheck((-sys.maxint - 1) % x) + except OverflowError: + return 1 + except ZeroDivisionError: + return 0 + res = interpret(f, [0]) + assert res == 0 + res = interpret(f, [-1]) + assert res == 1 + res = interpret(f, [30]) + assert res == (-sys.maxint - 1) % 30 + def test_obj_obj_is(): def f(x,y): From hpk at codespeak.net Sun Jul 31 13:48:44 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 13:48:44 +0200 (CEST) Subject: [pypy-svn] r15459 - pypy/dist/pypy/documentation/website Message-ID: <20050731114844.6027927B6C@code1.codespeak.net> Author: hpk Date: Sun Jul 31 13:48:43 2005 New Revision: 15459 Modified: pypy/dist/pypy/documentation/website/news.txt Log: linked day 6 and some pictures Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sun Jul 31 13:48:43 2005 @@ -35,12 +35,16 @@ to fully annotate the PyPy code base and have a mode where we don't borrow object implementations from CPython anymore (which of course means that we have some modules missing). -Moreover, there are almost no direct annotation and RTyping -problems remaining. Stay tuned. +On `day 6`_ we finally had a `breakthrough`_: PyPy runs +on its own! Hurray_!. .. _`report about day 1`: http://codespeak.net/pipermail/pypy-dev/2005q3/002217.html .. _`day 2 and day 3`: http://codespeak.net/pipermail/pypy-dev/2005q3/002220.html .. _`day 4 and day 5`: http://codespeak.net/pipermail/pypy-dev/2005q3/002234.html +.. _`day 6`: http://codespeak.net/pipermail/pypy-dev/2005q3/002239.html +.. _`breakthrough`: http://codespeak.net/~hpk/hildesheim2-sprint-www/hildesheim2-sprint-www-Pages/Image35.html +.. _`hurray`: http://codespeak.net/~hpk/hildesheim2-sprint-www/hildesheim2-sprint-www-Pages/Image36.html + .. _`pictures from the sprint`: http://codespeak.net/~hpk/hildesheim2-sprint-www/ .. _`Trillke-Gut`: http://www.trillke.net/images/HomePagePictureSmall.jpg From cfbolz at codespeak.net Sun Jul 31 13:49:33 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 13:49:33 +0200 (CEST) Subject: [pypy-svn] r15460 - pypy/dist/pypy/rpython Message-ID: <20050731114933.4CDE227B6C@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 13:49:31 2005 New Revision: 15460 Modified: pypy/dist/pypy/rpython/llinterp.py Log: refactored llinterpreter a bit to unify all the operation handlers in one place: as methods of the class Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun Jul 31 13:49:31 2005 @@ -102,15 +102,10 @@ # _______________________________________________________ # other helpers def getoperationhandler(self, opname): - try: - return getattr(self, 'op_' + opname) - except AttributeError: - g = globals() - assert opname in g, ( - "cannot handle operation %r yet" %(opname,)) - ophandler = g[opname] - return ophandler - + ophandler = getattr(self, 'op_' + opname, None) + if ophandler is None: + raise AssertionError, "cannot handle operation %r yet" %(opname,) + return ophandler # _______________________________________________________ # evaling functions @@ -391,97 +386,90 @@ res = f._obj.value(*[pyo._obj.value for pyo in args]) return pyobjectptr(res) + # __________________________________________________________ + # primitive operations - -# __________________________________________________________ -# primitive operations - -for typ in (float, int, r_uint): - typname = typ.__name__ - optup = ('add', 'sub', 'mul', 'div', 'truediv', 'floordiv', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq',) - if typ is r_uint: - opnameprefix = 'uint' - else: - opnameprefix = typname - if typ in (int, r_uint): - optup += 'and_', 'or_', 'lshift', 'rshift', 'xor' - for opname in optup: - assert opname in opimpls - if typ is int and opname not in ops_returning_a_bool: - adjust_result = 'intmask' + for typ in (float, int, r_uint): + typname = typ.__name__ + optup = ('add', 'sub', 'mul', 'div', 'truediv', 'floordiv', + 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq',) + if typ is r_uint: + opnameprefix = 'uint' else: - adjust_result = '' - pureopname = opname.rstrip('_') - exec py.code.Source(""" - def %(opnameprefix)s_%(pureopname)s(x, y): - assert isinstance(x, %(typname)s) - assert isinstance(y, %(typname)s) - func = opimpls[%(opname)r] - return %(adjust_result)s(func(x, y)) - """ % locals()).compile() - if typ is int: - opname += '_ovf' + opnameprefix = typname + if typ in (int, r_uint): + optup += 'and_', 'or_', 'lshift', 'rshift', 'xor' + for opname in optup: + assert opname in opimpls + if typ is int and opname not in ops_returning_a_bool: + adjust_result = 'intmask' + else: + adjust_result = '' + pureopname = opname.rstrip('_') exec py.code.Source(""" - def op_%(opnameprefix)s_%(pureopname)s_ovf(self, x, y): + def op_%(opnameprefix)s_%(pureopname)s(self, x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) func = opimpls[%(opname)r] - try: - return %(adjust_result)s(func(x, y)) - except OverflowError, e: - self.make_llexception(e) + return %(adjust_result)s(func(x, y)) """ % locals()).compile() - funcname = "op_%(opnameprefix)s_%(pureopname)s_ovf" % locals() - setattr(LLFrame, funcname, globals()[funcname]) - - for opname in 'is_true', 'neg', 'abs', 'invert': - assert opname in opimpls - if typ is int and opname not in ops_returning_a_bool: - adjust_result = 'intmask' - else: - adjust_result = '' - exec py.code.Source(""" - def %(opnameprefix)s_%(opname)s(x): - assert isinstance(x, %(typname)s) - func = opimpls[%(opname)r] - return %(adjust_result)s(func(x)) - """ % locals()).compile() - if typ is int: - opname += '_ovf' + if typ is int: + opname += '_ovf' + exec py.code.Source(""" + def op_%(opnameprefix)s_%(pureopname)s_ovf(self, x, y): + assert isinstance(x, %(typname)s) + assert isinstance(y, %(typname)s) + func = opimpls[%(opname)r] + try: + return %(adjust_result)s(func(x, y)) + except OverflowError, e: + self.make_llexception(e) + """ % locals()).compile() + for opname in 'is_true', 'neg', 'abs', 'invert': + assert opname in opimpls + if typ is int and opname not in ops_returning_a_bool: + adjust_result = 'intmask' + else: + adjust_result = '' exec py.code.Source(""" def op_%(opnameprefix)s_%(opname)s(self, x): assert isinstance(x, %(typname)s) func = opimpls[%(opname)r] - try: - return %(adjust_result)s(func(x)) - except OverflowError, e: - self.make_llexception(e) + return %(adjust_result)s(func(x)) """ % locals()).compile() - funcname = "op_%(opnameprefix)s_%(opname)s" % locals() - setattr(LLFrame, funcname, globals()[funcname]) + if typ is int: + opname += '_ovf' + exec py.code.Source(""" + def op_%(opnameprefix)s_%(opname)s(self, x): + assert isinstance(x, %(typname)s) + func = opimpls[%(opname)r] + try: + return %(adjust_result)s(func(x)) + except OverflowError, e: + self.make_llexception(e) + """ % locals()).compile() - -for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'): - assert opname in opimpls - exec py.code.Source(""" - def char_%(opname)s(x, y): - assert isinstance(x, str) and len(x) == 1 - assert isinstance(y, str) and len(y) == 1 - func = opimpls[%(opname)r] - return func(x, y) - """ % locals()).compile() + for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'): + assert opname in opimpls + exec py.code.Source(""" + def op_char_%(opname)s(self, x, y): + assert isinstance(x, str) and len(x) == 1 + assert isinstance(y, str) and len(y) == 1 + func = opimpls[%(opname)r] + return func(x, y) + """ % locals()).compile() -def unichar_eq(x, y): - assert isinstance(x, unicode) and len(x) == 1 - assert isinstance(y, unicode) and len(y) == 1 - func = opimpls['eq'] - return func(x, y) - -def unichar_ne(x, y): - assert isinstance(x, unicode) and len(x) == 1 - assert isinstance(y, unicode) and len(y) == 1 - func = opimpls['ne'] - return func(x, y) + def op_unichar_eq(self, x, y): + assert isinstance(x, unicode) and len(x) == 1 + assert isinstance(y, unicode) and len(y) == 1 + func = opimpls['eq'] + return func(x, y) + + def op_unichar_ne(self, x, y): + assert isinstance(x, unicode) and len(x) == 1 + assert isinstance(y, unicode) and len(y) == 1 + func = opimpls['ne'] + return func(x, y) # by default we route all logging messages to nothingness # e.g. tests can then switch on logging to get more help From rxe at codespeak.net Sun Jul 31 13:56:17 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 13:56:17 +0200 (CEST) Subject: [pypy-svn] r15461 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050731115617.28C8327B6C@code1.codespeak.net> Author: rxe Date: Sun Jul 31 13:56:15 2005 New Revision: 15461 Modified: pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_exception.py Log: Slight modification to make (some) exception tests work again. It would be better to go through the database interface than talk directly to nodes - I guess. Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sun Jul 31 13:56:15 2005 @@ -205,13 +205,15 @@ if returntype != "void": self.codewriter.invoke(targetvar, returntype, functionref, argrefs, - argtypes, none_label, exc_label) + argtypes, none_label, exc_label) else: self.codewriter.invoke_void(functionref, argrefs, argtypes, none_label, exc_label) e = self.db._translator.rtyper.getexceptiondata() - ll_exception_match = '%' + e.ll_exception_match.__name__ - lltype_of_exception_type = '%structtype.' + e.lltype_of_exception_type.TO.__name__ + '*' + ll_exception_match = '%' + e.ll_exception_match.__name__ + lltype_of_exception_type = ('%structtype.' + + e.lltype_of_exception_type.TO.__name__ + + '*') tmptype1, tmpvar1 = 'sbyte*', self.db.repr_tmpvar() tmptype2, tmpvar2 = lltype_of_exception_type, self.db.repr_tmpvar() @@ -237,7 +239,7 @@ self.codewriter.call(ll_issubclass_cond, 'bool', ll_exception_match, - [etype.ref, tmpvar2], + [etype.get_ref(), tmpvar2], [lltype_of_exception_type, lltype_of_exception_type]) self.codewriter.br(ll_issubclass_cond, not_this_exception_label, exc_found_label) self.codewriter.label(not_this_exception_label) Modified: pypy/dist/pypy/translator/llvm2/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_exception.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_exception.py Sun Jul 31 13:56:15 2005 @@ -3,9 +3,6 @@ from pypy.translator.llvm2.genllvm import compile_function from pypy.translator.test.snippet import try_raise_choose -def setup_module(module): - py.test.skip("tmp - just to sync up changes") - class TestException(Exception): pass @@ -171,6 +168,7 @@ assert f(i) == fn(i) def test_catch_base_exception(): + py.test.skip('aborted') #py.test.skip("not working yet, lst[n] raises no exceptions") def fn(n): lst = range(10) From hpk at codespeak.net Sun Jul 31 13:59:54 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 13:59:54 +0200 (CEST) Subject: [pypy-svn] r15462 - pypy/dist/pypy/translator/goal Message-ID: <20050731115954.0E15527B6C@code1.codespeak.net> Author: hpk Date: Sun Jul 31 13:59:53 2005 New Revision: 15462 Modified: pypy/dist/pypy/translator/goal/app_main.py pypy/dist/pypy/translator/goal/translate_pypy.py Log: - allow pypy.rpython.memory to be imported before forking - set recursion limit to 1000 for the translated PyPy's entry_point (otherwise the compiler doesn't run successfully with the translated PyPy) Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Jul 31 13:59:53 2005 @@ -6,6 +6,9 @@ import sys sys.executable = argv[0] sys.argv = argv[1:] + # with PyPy in top of CPython we can only have around 100 + # but we need more in the translated PyPy for the compiler package + sys.setrecursionlimit(1000) mainmodule = type(sys)('__main__') sys.modules['__main__'] = mainmodule Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sun Jul 31 13:59:53 2005 @@ -134,7 +134,10 @@ for name, module in sys.modules.items(): if module is not None and name.startswith(prefix): sname = name[len(prefix):] - if sname not in oknames: + for okname in oknames: + if sname.startswith(okname): + break + else: wrongimports.append(name) if wrongimports: raise RuntimeError("cannot fork because improper rtyper code" From hpk at codespeak.net Sun Jul 31 14:23:24 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 14:23:24 +0200 (CEST) Subject: [pypy-svn] r15463 - pypy/extradoc/sprintinfo Message-ID: <20050731122324.1A92327B6C@code1.codespeak.net> Author: hpk Date: Sun Jul 31 14:23:23 2005 New Revision: 15463 Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt pypy/extradoc/sprintinfo/hildesheim2-planning.txt Log: (arigo) updated sprint planning and done items Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-done.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-done.txt Sun Jul 31 14:23:23 2005 @@ -147,3 +147,30 @@ - DONE bug to be fixed: applevel test stdout is no longer captured. +- DONE running translate_pypy! + +- DONE try to extend test framework a bit to make applevel + tests allow to use 'self.somevalue' coming from interplevel 'self.w_somevalue'. + +- DONE finish/send out the Heidelberg sprint announcement + goals: do the 0.7 release! + (0.7 is meant as a first self-contained pypy release + with quite some c-extension modules missing (everything + below 1.0 is implicitly alpha'ed or XXXed or both) + + - translation efforts + - work on 2.4.1 compliancy (let's have a lib-python/ISSUE.txt well + before the sprint and let's try to count by failing tests not + failing test files) + - rewriting c-extension modules/integrating existing rewrites + - all kinds of small release issues + - possibly some more LLVM efforts + +- DONE finally start with garbage collection (CF) + +- DONE (plus no more segfaults, and all "class" tests are working) + let llvm support + varsize structs and possibly refactor/cleanup a bit the current + code (richard already contacted Eric and also worked a bit on improving + PBC support for llvm) + Modified: pypy/extradoc/sprintinfo/hildesheim2-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-planning.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-planning.txt Sun Jul 31 14:23:23 2005 @@ -32,12 +32,11 @@ Left:: - - running translate_pypy! - - - (Armin, Holger) add a compiling option to the C backend that allows to + - (Holger, Armin) add a compiling option to the C backend that allows to generate a standalone binary (as opposed to a Python extension module) - - (Armin, Holger) likely we have a possibly deep exception handling problem: + - (Samuele, Carl) WRITE A TEST or TRACKER or TRY TO FIX -> + likely we have a possibly deep exception handling problem: implicitely exceptions are attached to the last (high level) operation in a block but when the RTyper converts this operation into possibly many low-level operations then it's unlikely @@ -50,25 +49,10 @@ describing the interactions/processing of exceptions in flowobjspace/annotation/rtyping - - (Holger, X) try to extend test framework a bit to make applevel - tests allow to use 'self.somevalue' coming from interplevel 'self.w_somevalue'. - - (Holger, X) finish and polish and test our own posix module - - - (Carl, Samuele) finish/send out the Heidelberg sprint announcement - goals: do the 0.7 release! - (0.7 is meant as a first self-contained pypy release - with quite some c-extension modules missing (everything - below 1.0 is implicitly alpha'ed or XXXed or both) - - - translation efforts - - work on 2.4.1 compliancy (let's have a lib-python/ISSUE.txt well - before the sprint and let's try to count by failing tests not - failing test files) - - rewriting c-extension modules/integrating existing rewrites - - all kinds of small release issues - - possibly some more LLVM efforts + - (Richard) TRACKER -> finish and polish and test our own posix module - - (Armin ...) integrate Niklaus's applevel _sre module as a mixed module + - (Nik with help of one of us) + integrate Niklaus's applevel _sre module as a mixed module (so that you can switch it in via usemodules=_sre). This may also ease moving gradually to an interplevel implementation. @@ -77,20 +61,23 @@ conftest.py # don't recurse into full_sre_project (unless the unittests are converted to py.test) __init__.py: (appleveldefs -> full_sre_projec/...) - Armin is going to ask niklaus about his plans and + DONE Armin is going to ask niklaus about his plans and suggest something along these lines. - - (Carl, Samuele) finally start with garbage collection (CF) + OUTCOME: should go as a mixed module, but we don't have to keep the full + subproject structure but just keep _sre and the tests in PyPy. Nik will + keep the stand-alone version only if there is interest. (The sre-pypy + branch should be ignored and removed.) - - investigate the possibility of translating the interactive part of PyPy + - (all) investigate the possibility of translating the interactive part of PyPy or alternatively (probably preferably) running it completely at applevel - - (Richard, with Armin's throwing-examples help) let llvm support - varsize structs and possibly refactor/cleanup a bit the current - code (richard already contacted Eric and also worked a bit on improving - PBC support for llvm) - - (Christian, Samuele) rewriting the marshal module on interplevel (mostly + - (Richard, Eric) more llvm stuff: overflow, missing basic + operations, and exceptions. Think about unifying the tests between genc + and llvm2. + + - GOOD PROGRESS WE GUESS rewriting the marshal module on interplevel (mostly done but there are difficult dependencies on the applevel _codecs.py and some builtins (like frozenset) that live at applevel) From hpk at codespeak.net Sun Jul 31 14:25:33 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 14:25:33 +0200 (CEST) Subject: [pypy-svn] r15464 - pypy/dist/pypy/translator/goal Message-ID: <20050731122533.5982F27B6C@code1.codespeak.net> Author: hpk Date: Sun Jul 31 14:25:33 2005 New Revision: 15464 Modified: pypy/dist/pypy/translator/goal/runtranslate.sh Log: simplify main invocation of translation target Modified: pypy/dist/pypy/translator/goal/runtranslate.sh ============================================================================== --- pypy/dist/pypy/translator/goal/runtranslate.sh (original) +++ pypy/dist/pypy/translator/goal/runtranslate.sh Sun Jul 31 14:25:33 2005 @@ -2,4 +2,4 @@ # stopping on the first error #python translate_pypy.py -no-c -no-o -text -no-snapshot -fork # running it all -python translate_pypy.py -no-c -no-o -text -t-insist -no-snapshot -fork +python translate_pypy.py -no-o -text -t-insist -no-snapshot From rxe at codespeak.net Sun Jul 31 14:45:42 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 14:45:42 +0200 (CEST) Subject: [pypy-svn] r15465 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050731124542.5503B27B61@code1.codespeak.net> Author: rxe Date: Sun Jul 31 14:45:40 2005 New Revision: 15465 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py Log: Check in a null terminated str array nodes - fwiw (it doesnt break anything). Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 31 14:45:40 2005 @@ -75,6 +75,7 @@ self.db.prepare_constant(lltype.typeOf(p), p) def get_length(self): + """ returns logical length of array """ items = self.value.items return len(items) @@ -83,8 +84,9 @@ return [self.db.repr_constant(v)[1] for v in items] def get_typerepr(self): + arraylen = len(self.get_arrayvalues()) typeval = self.db.repr_arg_type(self.arraytype) - return "{ int, [%s x %s] }" % (self.get_length(), typeval) + return "{ int, [%s x %s] }" % (arraylen, typeval) def get_ref(self): """ Returns a reference as used for operations in blocks. """ @@ -118,16 +120,17 @@ def constantvalue(self): """ Returns the constant representation for this node. """ - arraylen = self.get_length() arrayvalues = self.get_arrayvalues() typeval = self.db.repr_arg_type(self.arraytype) - value = "int %s, [%s x %s] [ %s ]" % (arraylen, - arraylen, + # first length is logical, second is physical + value = "int %s, [%s x %s] [ %s ]" % (self.get_length(), + len(arrayvalues), typeval, ", ".join(arrayvalues)) s = "%s {%s}" % (self.get_typerepr(), value) + #XXXX ???????? #XXX this does not work for arrays inlined in struct. How else to do this? #if typeval == 'sbyte': #give more feedback for strings @@ -149,12 +152,10 @@ if p is None: codewriter.globalinstance(self.ref, self.constantvalue()) -class StrArrayNode(ConstantLLVMNode): - - def get_length(self): - # For null character - return super(StrArrayNode, self).get_length() + 1 +class StrArrayNode(ArrayNode): def get_arrayvalues(self): - items = self.value.items + [chr(0)] + items = self.value.items + if len(items) == 0 or items[-1] != chr(0): + items = items + [chr(0)] return [self.db.repr_constant(v)[1] for v in items] Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 31 14:45:40 2005 @@ -3,12 +3,14 @@ from pypy.translator.llvm2.extfuncnode import ExternalFuncNode from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ StructTypeNode, StructVarsizeTypeNode -from pypy.translator.llvm2.arraynode import ArrayNode, ArrayTypeNode +from pypy.translator.llvm2.arraynode import ArrayNode, StrArrayNode, \ + ArrayTypeNode from pypy.translator.llvm2.opaquenode import OpaqueNode, OpaqueTypeNode from pypy.translator.llvm2.node import ConstantLLVMNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable - +from pypy.rpython.rstr import STR + log = log.database PRIMITIVES_TO_LLVM = {lltype.Signed: "int", @@ -122,7 +124,10 @@ node = StructNode(self, value) elif isinstance(type_, lltype.Array): - node = ArrayNode(self, value) + if type_ is STR.chars: + node = StrArrayNode(self, value) + else: + node = ArrayNode(self, value) elif isinstance(type_, lltype.OpaqueType): node = OpaqueNode(self, value) From rxe at codespeak.net Sun Jul 31 14:51:04 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 14:51:04 +0200 (CEST) Subject: [pypy-svn] r15467 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050731125104.6090427B61@code1.codespeak.net> Author: rxe Date: Sun Jul 31 14:51:02 2005 New Revision: 15467 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/structnode.py Log: Mostly cosmetic stuff, either in python code or in generated llvm code. Disabled line counting for now, as misleading with multiline constantvalue(). Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jul 31 14:51:02 2005 @@ -3,7 +3,7 @@ from pypy.translator.llvm2.log import log log = log.codewriter -show_line_numbers = True # False +show_line_numbers = False # True count = count().next class CodeWriter(object): @@ -14,7 +14,8 @@ if show_line_numbers: line = "%-75s; %d" % (line, len(self._lines) + 1) self._lines.append(line) - log(line) + #XXXlog(line) + print line def comment(self, line, indent=True): line = ";; " + line Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jul 31 14:51:02 2005 @@ -150,7 +150,8 @@ for op_index, op in enumerate(block.operations): # print out debug string - codewriter.comment(str(op)) + codewriter.newline() + codewriter.comment("** %s **" % str(op)) info = self.db.get_op2comment(op) if info is not None: lenofopstr, opstrname = info Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jul 31 14:51:02 2005 @@ -12,8 +12,6 @@ from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter from pypy.translator.llvm2.extfuncnode import ExternalFuncNode -from pypy.translator.backendoptimization import remove_void -#from pypy.translator.backendoptimization import rename_extfunc_calls from pypy.translator.llvm2.module.extfunction import extdeclarations, \ extfunctions, gc_boehm, gc_disabled, dependencies from pypy.translator.llvm2.node import LLVMNode @@ -25,17 +23,15 @@ class GenLLVM(object): def __init__(self, translator, debug=False, embedexterns=True): - LLVMNode.nodename_count = {} #reset counters + # reset counters + LLVMNode.nodename_count = {} self.db = Database(translator) self.translator = translator self.embedexterns = embedexterns - # transformations - #remove_void(translator) - #rename_extfunc_calls(translator) translator.checkgraphs() ExternalFuncNode.used_external_functions = {} - # For debug we create comments of every operation that may be executed + # for debug we create comments of every operation that may be executed self.debug = debug def compile(self, func=None): @@ -43,7 +39,7 @@ func = self.translator.entrypoint self.entrypoint = func - #make sure exception matching and exception type are available + # make sure exception matching and exception type are available e = self.translator.rtyper.getexceptiondata() for ll_helper in (e.ll_exception_match,): ptr = getfunctionptr(self.translator, ll_helper) @@ -58,7 +54,6 @@ self.db.setup_all() self.db.dump_pbcs() - #assert False self.entrynode = self.db.obj2node[c] codewriter = CodeWriter() @@ -89,7 +84,6 @@ for typ_decl in self.db.getnodes(): typ_decl.writedecl(codewriter) - #import pdb ; pdb.set_trace() nl(); comment("Function Implementation") codewriter.startimpl() if use_boehm_gc: @@ -149,7 +143,7 @@ def genllvm(translator, embedexterns=True): gen = GenLLVM(translator, embedexterns=embedexterns) - log.source(gen.compile()) + gen.compile() return gen.create_module() def llvm_is_on_path(): Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sun Jul 31 14:51:02 2005 @@ -143,7 +143,7 @@ """ Returns the constant representation for this node. """ values = self._getvalues() all_values = ",\n ".join(values) - return "%s {\n %s\n }\n\n" % (self.get_typerepr(), all_values) + return "%s {\n %s\n }\n" % (self.get_typerepr(), all_values) # ______________________________________________________________________ # main entry points from genllvm @@ -201,7 +201,6 @@ return "{%s}" % ", ".join(types_repr) def get_ref(self): - #XXX Is this right? ref = super(StructVarsizeNode, self).get_ref() typeval = self.db.repr_arg_type(lltype.typeOf(self.value)) ref = "cast (%s* %s to %s*)" % (self.get_typerepr(), From hpk at codespeak.net Sun Jul 31 14:57:33 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 14:57:33 +0200 (CEST) Subject: [pypy-svn] r15468 - pypy/dist/pypy/translator/goal Message-ID: <20050731125733.97C5C27B61@code1.codespeak.net> Author: hpk Date: Sun Jul 31 14:57:32 2005 New Revision: 15468 Modified: pypy/dist/pypy/translator/goal/app_main.py pypy/dist/pypy/translator/goal/targetpypymain.py Log: (arigo, hpk) refactored the main entry_point so that it accepts no arguments (starting code.interact()) or just a single string argument (compiling and running the given filename). Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Jul 31 14:57:32 2005 @@ -4,19 +4,29 @@ def entry_point(argv): import sys - sys.executable = argv[0] - sys.argv = argv[1:] + sys.executable = "pypy" + sys.argv = argv # with PyPy in top of CPython we can only have around 100 # but we need more in the translated PyPy for the compiler package - sys.setrecursionlimit(1000) + sys.setrecursionlimit(5000) mainmodule = type(sys)('__main__') sys.modules['__main__'] = mainmodule try: - execfile(sys.argv[0], mainmodule.__dict__) + if argv: + execfile(sys.argv[0], mainmodule.__dict__) + else: + print >> sys.stderr, "importing code" + import code + print >> sys.stderr, "calling code.interact()" + code.interact(local=mainmodule.__dict__) except: - sys.excepthook(*sys.exc_info()) + excinfo = sys.exc_info() + typ, val, tb = excinfo + print >> sys.stderr, "exception-type:", typ.__name__ + print >> sys.stderr, "exception-value:", str(val) + sys.excepthook(typ, val, tb) return 1 else: return 0 @@ -24,4 +34,4 @@ if __name__ == '__main__': # debugging only import sys - sys.exit(entry_point(sys.argv)) + sys.exit(entry_point(sys.argv[1:])) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sun Jul 31 14:57:32 2005 @@ -63,7 +63,7 @@ w_entry_point = space.getitem(w_dict, space.wrap('entry_point')) # sanity-check: call the entry point - res = entry_point("pypy\x00app_example.py") + res = entry_point("app_example.py") assert res == 0 return entry_point, [SomeString()] @@ -76,6 +76,6 @@ # _____ Run translated _____ def run(c_entry_point): - argv = ["pypy", os.path.join(this_dir, 'app_example.py')] + argv = [os.path.join(this_dir, 'app_example.py')] exitcode = c_entry_point('\x00'.join(argv)) assert exitcode == 0 From hpk at codespeak.net Sun Jul 31 15:02:12 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 15:02:12 +0200 (CEST) Subject: [pypy-svn] r15469 - in pypy/dist/pypy/translator: . c Message-ID: <20050731130212.83D1A27B6A@code1.codespeak.net> Author: hpk Date: Sun Jul 31 15:02:11 2005 New Revision: 15469 Modified: pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/translator.py Log: (arigo, hpk) refactored genc's compilation/translation interface into a CBuilder class where one can invoke the different steps. Next is to go for implementing the build of a completely 'standalone' i.e. CPython-independent executable Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sun Jul 31 15:02:11 2005 @@ -4,10 +4,60 @@ from pypy.translator.c.database import LowLevelDatabase from pypy.translator.c.extfunc import pre_include_code_lines from pypy.translator.gensupp import uniquemodulename -from pypy.translator.tool.cbuild import make_module_from_c +from pypy.translator.tool.cbuild import compile_c_module +from pypy.translator.tool.cbuild import import_module_from_directory from pypy.rpython.lltype import pyobjectptr from pypy.tool.udir import udir +class CBuilder: + def __init__(self, translator, standalone=False): + self.translator = translator + self.standalone = standalone + self.c_source_filename = None + self._compiled = False + self.c_ext_module = None + + def generate_source(self): + assert not self.standalone + assert self.c_source_filename is None + translator = self.translator + db, pf = translator2database(translator) + modulename = uniquemodulename('testing') + targetdir = udir.ensure(modulename, dir=1) + if not self.standalone: + from pypy.translator.c.symboltable import SymbolTable + self.symboltable = SymbolTable() + else: + self.symboltable = None + cfile = gen_source(db, modulename, targetdir, + # defines={'COUNT_OP_MALLOCS': 1}, + exports = {translator.entrypoint.func_name: pf}, + symboltable = self.symboltable) + self.c_source_filename = py.path.local(cfile) + return cfile + + def compile(self): + assert self.c_source_filename + assert not self.standalone, "XXX" + compile_c_module(self.c_source_filename, + self.c_source_filename.purebasename, + include_dirs = [autopath.this_dir]) + self._compiled = True + + def import_module(self): + assert self._compiled + assert not self.c_ext_module + mod = import_module_from_directory(self.c_source_filename.dirpath(), + self.c_source_filename.purebasename) + self.c_ext_module = mod + if self.symboltable: + self.symboltable.attach(mod) # hopefully temporary hack + return mod + + def get_entry_point(self): + assert self.c_ext_module + return getattr(self.c_ext_module, + self.translator.entrypoint.func_name) def translator2database(translator): pf = pyobjectptr(translator.entrypoint) @@ -16,39 +66,6 @@ db.complete() return db, pf - -def genc(translator, targetdir=None, modulename=None, compile=True, - symtable=True): - """Generate C code starting at the translator's entry point. - The files are written to the targetdir if specified. - If 'compile' is True, compile and return the new module. - If 'compile' is False, just return the name of the main '.c' file. - """ - db, pf = translator2database(translator) - - if modulename is None: - modulename = uniquemodulename('testing') - if targetdir is None: - targetdir = udir.join(modulename) - elif isinstance(targetdir, str): - targetdir = py.path.local(targetdir) - targetdir.ensure(dir=1) - if symtable: - from pypy.translator.c.symboltable import SymbolTable - symboltable = SymbolTable() - else: - symboltable = None - cfile = gen_source(db, modulename, targetdir, - # defines={'COUNT_OP_MALLOCS': 1}, - exports = {translator.entrypoint.func_name: pf}, - symboltable = symboltable) - if not compile: - return cfile - m = make_module_from_c(cfile, include_dirs = [autopath.this_dir]) - symboltable.attach(m) # hopefully temporary hack - return m - - # ____________________________________________________________ def gen_readable_parts_of_main_c_file(f, database, preimplementationlines=[]): Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Sun Jul 31 15:02:11 2005 @@ -253,16 +253,22 @@ return getattr(mod, name) def ccompile(self, really_compile=True): - """Returns compiled function, compiled using the C generator. + """Returns compiled function (living in a new C-extension module), + compiled using the C generator. """ - from pypy.translator.c import genc if self.annotator is not None: self.frozen = True + cbuilder = self.cbuilder(standalone=False) + c_source_filename = cbuilder.generate_source() + if not really_compile: + return c_source_filename + cbuilder.compile() + cbuilder.import_module() + return cbuilder.get_entry_point() - result = genc.genc(self, compile=really_compile) - if really_compile: # result is the module - result = getattr(result, self.entrypoint.func_name) - return result + def cbuilder(self, standalone=False): + from pypy.translator.c import genc + return genc.CBuilder(self, standalone=standalone) def llvmcompile(self, optimize=True): """llvmcompile(self, optimize=True) -> LLVM translation From cfbolz at codespeak.net Sun Jul 31 15:27:17 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 15:27:17 +0200 (CEST) Subject: [pypy-svn] r15472 - pypy/dist/pypy/rpython/test Message-ID: <20050731132717.8F99627B6A@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 15:27:16 2005 New Revision: 15472 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: (pedronis, cfbolz): added a skipped test which shows the problem of our current handling of exceptions in the RTyper. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sun Jul 31 15:27:16 2005 @@ -789,3 +789,42 @@ res = interpret(f, [1]) assert res == 3*2+11*7 + +def test_mulitple_ll_one_hl_op(): + class E(Exception): + pass + class A(object): + pass + class B(A): + pass + class C(object): + def method(self, x): + if x: + raise E() + else: + return A() + class D(C): + def method(self, x): + if x: + raise E() + else: + return B() + def call(x): + c = D() + c.method(x) + try: + c.method(x + 1) + except E: + pass + c = C() + c.method(x) + try: + return c.method(x + 1) + except E: + return None + try: + res = interpret(call, [0]) + except: + py.test.skip("this test shows the problem with rtyping exceptions") + + From cfbolz at codespeak.net Sun Jul 31 16:29:13 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 16:29:13 +0200 (CEST) Subject: [pypy-svn] r15474 - in pypy/dist/pypy: rpython/test translator Message-ID: <20050731142913.19B1927B6A@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 16:29:10 2005 New Revision: 15474 Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py pypy/dist/pypy/translator/backendoptimization.py pypy/dist/pypy/translator/simplify.py Log: (pedronis, cfbolz): fixed eliminate_empty_blocks so that it removes now empty try blocks. Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rspecialcase.py (original) +++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Sun Jul 31 16:29:10 2005 @@ -1,5 +1,5 @@ from pypy.rpython.lltype import * -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, gengraph from pypy.translator.ann_override import PyPyAnnotatorPolicy @@ -13,13 +13,32 @@ return "ab" else: return f() - res = interpret(g, [0]) assert not res res = interpret(g, [1]) assert ''.join(res.chars) == "ab" + +def test_ignore_breaking_transformations(): + def f(): + pass + f._annspecialcase_ = "override:ignore" + def g(i): + if i == 1: + return "ab" + else: + try: + return f() + except: + return "hello!" + t, typer = gengraph(g, [int]) + from pypy.translator import backendoptimization, simplify + from pypy.objspace.flow.model import checkgraph + graph = t.getflowgraph(g) + backendoptimization.remove_same_as(graph) + simplify.eliminate_empty_blocks(graph) + #should not crash: + checkgraph(graph) - def test_meth_override_ignore(): class X: def f(self): Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Sun Jul 31 16:29:10 2005 @@ -1,5 +1,6 @@ import autopath from pypy.translator.translator import Translator +from pypy.translator.simplify import eliminate_empty_blocks from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph @@ -148,6 +149,8 @@ def backend_optimizations(graph): remove_same_as(graph) + eliminate_empty_blocks(graph) + checkgraph(graph) SSI_to_SSA(graph) checkgraph(graph) Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Sun Jul 31 16:29:10 2005 @@ -18,7 +18,13 @@ following link. Arguments of the links should be updated.""" def visit(link): if isinstance(link, Link): - while not link.target.operations and len(link.target.exits) == 1: + while not link.target.operations: + if len(link.target.exits) != 1: + print link.target.exits + print link.target.exitswitch + print "###########################################" + if link.target.exitswitch != Constant(last_exception): + break assert link.target is not link.prevblock, ( "the graph contains an empty infinite loop") block1 = link.target From cfbolz at codespeak.net Sun Jul 31 16:41:12 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 16:41:12 +0200 (CEST) Subject: [pypy-svn] r15475 - pypy/dist/pypy/translator Message-ID: <20050731144112.00B7A27B6A@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 16:41:11 2005 New Revision: 15475 Modified: pypy/dist/pypy/translator/simplify.py Log: removed debug prints Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Sun Jul 31 16:41:11 2005 @@ -19,12 +19,9 @@ def visit(link): if isinstance(link, Link): while not link.target.operations: - if len(link.target.exits) != 1: - print link.target.exits - print link.target.exitswitch - print "###########################################" - if link.target.exitswitch != Constant(last_exception): - break + if (len(link.target.exits) != 1 and + link.target.exitswitch != Constant(last_exception)): + break assert link.target is not link.prevblock, ( "the graph contains an empty infinite loop") block1 = link.target From hpk at codespeak.net Sun Jul 31 17:11:00 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 17:11:00 +0200 (CEST) Subject: [pypy-svn] r15477 - pypy/dist/pypy/translator/goal Message-ID: <20050731151100.A155D27B6A@code1.codespeak.net> Author: hpk Date: Sun Jul 31 17:10:59 2005 New Revision: 15477 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: allow the entrypoint really accept a string (if it's empty call import code ; code.interact() basically) Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Sun Jul 31 17:10:59 2005 @@ -25,7 +25,10 @@ def entry_point(argvstring): debug("entry point starting") debug(argvstring) - argv = argvstring.split('\x00') + if argvstring: + argv = [argvstring] + else: + argv = [] for arg in argv: debug(" argv -> " + arg) try: @@ -76,6 +79,5 @@ # _____ Run translated _____ def run(c_entry_point): - argv = [os.path.join(this_dir, 'app_example.py')] - exitcode = c_entry_point('\x00'.join(argv)) + exitcode = c_entry_point(os.path.join(this_dir, 'app_example.py')) assert exitcode == 0 From hpk at codespeak.net Sun Jul 31 17:16:23 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 17:16:23 +0200 (CEST) Subject: [pypy-svn] r15478 - in pypy/dist/pypy/translator/c: . src test Message-ID: <20050731151623.52B8527B6A@code1.codespeak.net> Author: hpk Date: Sun Jul 31 17:16:20 2005 New Revision: 15478 Added: pypy/dist/pypy/translator/c/src/main.h pypy/dist/pypy/translator/c/src/standalone.h pypy/dist/pypy/translator/c/test/inprogress_test_standalone.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/src/exception.h pypy/dist/pypy/translator/c/src/g_include.h pypy/dist/pypy/translator/c/src/ll_math.h pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/src/support.h Log: (hpk, arigo) Progressing towards generating stand-alone C programs that don't link against CPython at all. Mostly works when tested by hand. Missing distutils incantations to compile the C source automatically (the inprogress test is disabled because of that). Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sun Jul 31 17:16:20 2005 @@ -13,14 +13,16 @@ class LowLevelDatabase: - def __init__(self, translator=None): + def __init__(self, translator=None, standalone=False): self.translator = translator + self.standalone = standalone self.structdefnodes = {} self.containernodes = {} self.containerlist = [] self.externalfuncs = {} self.namespace = CNameManager() - self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) + if not standalone: + self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) def gettypedefnode(self, T, varlength=1): if varlength <= 1: @@ -136,7 +138,8 @@ def complete(self): i = 0 while True: - self.pyobjmaker.collect_initcode() + if hasattr(self, 'pyobjmaker'): + self.pyobjmaker.collect_initcode() if i == len(self.containerlist): break node = self.containerlist[i] Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Sun Jul 31 17:16:20 2005 @@ -3,6 +3,7 @@ from pypy.translator.c.support import cdecl from pypy.rpython.rmodel import getfunctionptr from pypy.rpython.rstr import STR +from pypy.rpython import rlist from pypy.rpython.module import ll_os, ll_time, ll_math @@ -48,6 +49,7 @@ def predeclare_common_types(db, rtyper): # Common types yield ('RPyString', STR) + yield ('RPyListOfString', rlist.LIST_OF_STR) yield ('RPyFREXP_RESULT', ll_math.FREXP_RESULT) yield ('RPyMODF_RESULT', ll_math.MODF_RESULT) yield ('RPySTAT_RESULT', ll_os.STAT_RESULT) @@ -57,6 +59,16 @@ def RPyString_New(length=lltype.Signed): return lltype.malloc(STR, length) + p = lltype.Ptr(rlist.LIST_OF_STR) + + def RPyListOfString_New(length=lltype.Signed): + return rlist.ll_newlist(p, length) + + def RPyListOfString_SetItem(l=p, + index=lltype.Signed, + newstring=lltype.Ptr(STR)): + rlist.ll_setitem_nonneg(l, index, newstring) + for fname, f in locals().items(): if isinstance(f, types.FunctionType): # hack: the defaults give the type of the arguments @@ -87,8 +99,9 @@ yield ('RPYTHON_EXCEPTION_MATCH', exceptiondata.ll_exception_match) yield ('RPYTHON_TYPE_OF_EXC_INST', exceptiondata.ll_type_of_exc_inst) - yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) yield ('RAISE_OSERROR', exceptiondata.ll_raise_OSError) + if not db.standalone: + yield ('RPYTHON_PYEXCCLASS2EXC', exceptiondata.ll_pyexcclass2exc) for pyexccls in exceptiondata.standardexceptions: exc_llvalue = exceptiondata.ll_pyexcclass2exc( Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sun Jul 31 17:16:20 2005 @@ -6,7 +6,8 @@ from pypy.translator.gensupp import uniquemodulename from pypy.translator.tool.cbuild import compile_c_module from pypy.translator.tool.cbuild import import_module_from_directory -from pypy.rpython.lltype import pyobjectptr +from pypy.rpython.rmodel import getfunctionptr +from pypy.rpython import lltype from pypy.tool.udir import udir class CBuilder: @@ -18,21 +19,35 @@ self.c_ext_module = None def generate_source(self): - assert not self.standalone assert self.c_source_filename is None translator = self.translator - db, pf = translator2database(translator) + entrypoint = translator.entrypoint + if not self.standalone: + pf = lltype.pyobjectptr(entrypoint) + else: + # XXX check that the entrypoint has the correct + # signature: list-of-strings -> int + pf = getfunctionptr(translator, entrypoint) + db = LowLevelDatabase(translator, standalone=self.standalone) + pfname = db.get(pf) + db.complete() + modulename = uniquemodulename('testing') targetdir = udir.ensure(modulename, dir=1) + defines = {} + # defines={'COUNT_OP_MALLOCS': 1} if not self.standalone: from pypy.translator.c.symboltable import SymbolTable self.symboltable = SymbolTable() + cfile = gen_source(db, modulename, targetdir, + defines = defines, + exports = {translator.entrypoint.func_name: pf}, + symboltable = self.symboltable) else: self.symboltable = None - cfile = gen_source(db, modulename, targetdir, - # defines={'COUNT_OP_MALLOCS': 1}, - exports = {translator.entrypoint.func_name: pf}, - symboltable = self.symboltable) + cfile = gen_source_standalone(db, modulename, targetdir, + entrypointname = pfname, + defines = defines) self.c_source_filename = py.path.local(cfile) return cfile @@ -115,9 +130,37 @@ print >> f, line blank = True +def gen_source_standalone(database, modulename, targetdir, + entrypointname, defines={}): + assert database.standalone + if isinstance(targetdir, str): + targetdir = py.path.local(targetdir) + filename = targetdir.join(modulename + '.c') + f = filename.open('w') + + # + # Header + # + defines['PYPY_STANDALONE'] = entrypointname + for key, value in defines.items(): + print >> f, '#define %s %s' % (key, value) + + preimplementationlines = list( + pre_include_code_lines(database, database.translator.rtyper)) + + # + # 1) All declarations + # 2) Implementation of functions and global structures and arrays + # + gen_readable_parts_of_main_c_file(f, database, preimplementationlines) + + f.close() + return filename + def gen_source(database, modulename, targetdir, defines={}, exports={}, - symboltable=None): + symboltable=None): + assert not database.standalone if isinstance(targetdir, str): targetdir = py.path.local(targetdir) filename = targetdir.join(modulename + '.c') 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 Jul 31 17:16:20 2005 @@ -2,8 +2,9 @@ /************************************************************/ /*** C header subsection: exceptions ***/ -static PyObject *RPythonError; - +#ifndef PYPY_STANDALONE + static PyObject *RPythonError; +#endif /******************************************************************/ #ifdef HAVE_RTYPER /* RPython version of exceptions */ @@ -28,6 +29,7 @@ #define MatchException(etype) RPYTHON_EXCEPTION_MATCH(rpython_exc_type, \ (RPYTHON_EXCEPTION_VTABLE) etype) +#ifndef PYPY_STANDALONE static void ConvertExceptionFromCPython(void) { /* convert the CPython exception to an RPython one */ @@ -64,7 +66,9 @@ vanishing = rpython_exc_value; \ rpython_exc_type = NULL; \ rpython_exc_value = NULL; - + +#endif /* !PYPY_STANDALONE */ + #define RaiseSimpleException(exc, msg) \ /* XXX 1. uses officially bad fishing */ \ Modified: pypy/dist/pypy/translator/c/src/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/src/g_include.h (original) +++ pypy/dist/pypy/translator/c/src/g_include.h Sun Jul 31 17:16:20 2005 @@ -2,18 +2,25 @@ /************************************************************/ /*** C header file for code produced by genc.py ***/ -#include "Python.h" -#include "compile.h" -#include "frameobject.h" -#include "structmember.h" -#include "traceback.h" -#include "marshal.h" -#include "eval.h" +#ifndef PYPY_STANDALONE +# include "Python.h" +# include "compile.h" +# include "frameobject.h" +# include "structmember.h" +# include "traceback.h" +# include "marshal.h" +# include "eval.h" +#else +# include "src/standalone.h" +#endif #include "src/exception.h" #include "src/trace.h" #include "src/support.h" -#include "src/module.h" + +#ifndef PYPY_STANDALONE +# include "src/module.h" +#endif #include "src/mem.h" #include "src/int.h" @@ -29,3 +36,8 @@ # include "src/ll_time.h" # include "src/ll_math.h" #endif + +#ifdef PYPY_STANDALONE +# include "src/main.h" +#endif + Modified: pypy/dist/pypy/translator/c/src/ll_math.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_math.h (original) +++ pypy/dist/pypy/translator/c/src/ll_math.h Sun Jul 31 17:16:20 2005 @@ -1,8 +1,6 @@ /************************************************************/ /*** C header subsection: math module ***/ -#include "math.h" - /* The functions below are mapped to functions from pypy.rpython.module.* by the pypy.translator.c.extfunc.EXTERNALS dictionary. They should correspond to the functions with the suggested_primitive Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Sun Jul 31 17:16:20 2005 @@ -1,9 +1,13 @@ /************************************************************/ /*** C header subsection: os module ***/ -/*#include -- XXX re-enable with lots of #ifdefs */ -/*#include */ -/*#include */ +#if !(defined(MS_WIN64) || defined(MS_WINDOWS)) +# include +# include +# include +#endif + +#include #include #ifndef PATH_MAX /* assume windows */ @@ -36,7 +40,7 @@ { /* XXX unicode_file_names */ char buf[PATH_MAX]; - int fd, error, namelen = RPyString_Size(filename); + int fd, namelen = RPyString_Size(filename); if (namelen >= PATH_MAX) { RAISE_OSERROR(ENAMETOOLONG); return -1; Added: pypy/dist/pypy/translator/c/src/main.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/main.h Sun Jul 31 17:16:20 2005 @@ -0,0 +1,14 @@ + +#define STANDALONE_ENTRY_POINT PYPY_STANDALONE + +int main(int argc, char *argv[]) +{ + int i; + RPyListOfString *list = RPyListOfString_New(argc); + for (i=0; i +#include +#include +#include + +#define PyObject_Malloc malloc +#define PyObject_Free free + Modified: pypy/dist/pypy/translator/c/src/support.h ============================================================================== --- pypy/dist/pypy/translator/c/src/support.h (original) +++ pypy/dist/pypy/translator/c/src/support.h Sun Jul 31 17:16:20 2005 @@ -19,6 +19,9 @@ #define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, Exc_ZeroDivisionError, msg) #define CFAIL(err) { ConvertExceptionFromCPython(); FAIL(err) } + +#ifndef PYPY_STANDALONE + /* we need a subclass of 'builtin_function_or_method' which can be used as methods: builtin function objects that can be bound on instances */ static PyObject * @@ -375,3 +378,4 @@ #define PyString_ToLLCharArray(s, itemsarray) \ memcpy(itemsarray->items, PyString_AS_STRING(s), \ itemsarray->length) +#endif /* PYPY_STANDALONE */ Added: pypy/dist/pypy/translator/c/test/inprogress_test_standalone.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/inprogress_test_standalone.py Sun Jul 31 17:16:20 2005 @@ -0,0 +1,23 @@ +from pypy.translator.translator import Translator +from pypy.translator.tool.cbuild import build_executable +from pypy.annotation.model import SomeList, SomeString +from pypy.annotation.listdef import ListDef +import os + + +def test_hello_world(): + def entry_point(argv): + os.write(1, "hello world\n") + os.write(1, "argument count: " + str(len(argv)) + "\n") + for s in argv: + os.write(1, " '" + str(s) + "'\n") + return 0 + + t = Translator(entry_point) + s_list_of_strings = SomeList(ListDef(None, SomeString())) + t.annotate([s_list_of_strings]) + t.specialize() + cbuilder = t.cbuilder(standalone=True) + cbuilder.generate_source() + cbuilder.compile() + XXX From hpk at codespeak.net Sun Jul 31 17:16:35 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 17:16:35 +0200 (CEST) Subject: [pypy-svn] r15479 - pypy/dist/pypy/translator/goal Message-ID: <20050731151635.1680427B73@code1.codespeak.net> Author: hpk Date: Sun Jul 31 17:16:34 2005 New Revision: 15479 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: try to get a short traceback instead of waiting for the end of times trying to see the full traceback Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Jul 31 17:16:34 2005 @@ -26,7 +26,15 @@ typ, val, tb = excinfo print >> sys.stderr, "exception-type:", typ.__name__ print >> sys.stderr, "exception-value:", str(val) - sys.excepthook(typ, val, tb) + # print short tracebacks filename:lineno + tbentry = tb + while tbentry: + lineno = tbentry.tb_lineno + filename = tbentry.tb_frame.f_code.co_filename + print >>sys.stderr, " %s:%d" %(filename, lineno) + tbentry = tbentry.tb_next + # then take forever trying to print a traceback ... + #sys.excepthook(typ, val, tb) return 1 else: return 0 From hpk at codespeak.net Sun Jul 31 17:18:10 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 17:18:10 +0200 (CEST) Subject: [pypy-svn] r15480 - pypy/dist/pypy/rpython Message-ID: <20050731151810.D68ED27B6A@code1.codespeak.net> Author: hpk Date: Sun Jul 31 17:18:09 2005 New Revision: 15480 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rtyper.py Log: (hpk, arigo) Oups, missing from previous check-in. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jul 31 17:18:09 2005 @@ -731,3 +731,8 @@ raise StopIteration iter.index = index + 1 return l.items[index] + +# ___________________________________________________________ + +LIST_OF_STR = GcStruct("list", + ("items", Ptr(GcArray(Ptr(rstr.STR))))) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun Jul 31 17:18:09 2005 @@ -267,13 +267,15 @@ # insert the needed conversions on the links can_insert_here = block.exitswitch is None and len(block.exits) == 1 for link in block.exits: - if block.exitswitch is not None and link.exitcase is not None: + if link.exitcase is not None: if isinstance(block.exitswitch, Variable): r_case = self.bindingrepr(block.exitswitch) else: assert block.exitswitch == Constant(last_exception) r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) + else: + link.llexitcase = None a = link.last_exception if isinstance(a, Variable): From rxe at codespeak.net Sun Jul 31 17:30:27 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 17:30:27 +0200 (CEST) Subject: [pypy-svn] r15481 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050731153027.DC9C427B6A@code1.codespeak.net> Author: rxe Date: Sun Jul 31 17:30:24 2005 New Revision: 15481 Added: pypy/dist/pypy/translator/llvm2/test/test_typed.py Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: More tests and very little code added. Tests were stolen kindly from c/test/test_typed.py Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 31 17:30:24 2005 @@ -18,8 +18,6 @@ lltype.Unsigned: "uint", lltype.Bool: "bool", lltype.Float: "double", - # XXX Preliminary support for unicode, makes sense to - # make this more configurable lltype.UniChar: "uint", lltype.Void: "void"} @@ -66,7 +64,7 @@ elif type_ is lltype.Char: repr = str(ord(value)) elif type_ is lltype.UniChar: - repr = "0" # XXX Dont know what to do here at all? + repr = str(ord(value)) else: repr = str(value) return repr Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sun Jul 31 17:30:24 2005 @@ -82,13 +82,45 @@ assert meth is not None, "operation %r not found" %(op.opname,) meth(op) - def int_neg(self, op): + def _generic_pow(self, op, onestr): + mult_type = self.db.repr_arg_type(op.args[0]) + mult_val = self.db.repr_arg(op.args[0]) + last_val = mult_val + operand = int(op.args[1].value) + if operand < 1: + res_val = onestr + else: + res_val = mult_val + for ii in range(operand - 1): + res_val = self.db.repr_tmpvar() + self.codewriter.binaryop("mul", + res_val, + mult_type, + last_val, + mult_val) + last_val = res_val + targetvar = self.db.repr_arg(op.result) + self.codewriter.cast(targetvar, mult_type, res_val, mult_type) + + def int_pow(self, op): + self._generic_pow(op, "1") + uint_pow = int_pow + + def float_pow(self, op): + self._generic_pow(op, "1.0") + + def _generic_neg(self, op, zerostr): self.codewriter.binaryop("sub", self.db.repr_arg(op.result), self.db.repr_arg_type(op.args[0]), - "0", + zerostr, self.db.repr_arg(op.args[0]), ) + def int_neg(self, op): + self._generic_neg(op, "0") + + def float_neg(self, op): + self._generic_neg(op, "0.0") def bool_not(self, op): self.codewriter.binaryop("xor", @@ -96,7 +128,6 @@ self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), "true") - def binaryop(self, op): name = self.binary_operations[op.opname] @@ -133,6 +164,7 @@ cast_char_to_bool = cast_char_to_int = cast_char_to_uint = cast_primitive cast_int_to_bool = cast_int_to_char = cast_int_to_uint = cast_primitive cast_uint_to_bool = cast_uint_to_char = cast_uint_to_int = cast_primitive + cast_int_to_float = cast_float_to_int = cast_primitive cast_pointer = cast_primitive same_as = cast_primitive Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jul 31 17:30:24 2005 @@ -52,13 +52,58 @@ x += i >= i x += i > i x += x % i + x += x ** 0 + x += x ** 1 + x += x ** 2 + x += i + 1 * i // i - 1 #x += i is not None #x += i is None - return i + 1 * i // i - 1 + return x f = compile_function(ops, [int]) - assert f(1) == 1 - assert f(2) == 2 + 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 += x ** 0 + x += x ** 1 + x += x ** 2 + x += i + 1 * i // i - 1 + #x += i is not None + #x += i is None + return x + 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 += x ** 0 + x += x ** 1 + x += x ** 2 + x += int(flt + 1 * flt / flt - 1) + #x += flt fs not None + #x += flt is None + 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 @@ -108,39 +153,6 @@ assert f(256.0) assert not f(0.0) -def test_uint_ops(): - def ops(i): - x = r_uint(0) - x += i < i - x += i <= i - x += i == i - x += i != i - x += i >= i - x += i > i - x += x % i - #x += i is not None - #x += i is None - return i + 1 * i // i - 1 - f = compile_function(ops, [r_uint]) - assert f(1) == 1 - assert f(2) == 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 += flt fs not None - #x += flt is None - return flt + 1 * flt / flt - 1 - f = compile_function(ops, [float]) - assert f(1) == 1 - assert f(2) == 2 - def test_function_call(): def callee(): return 1 Added: pypy/dist/pypy/translator/llvm2/test/test_typed.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_typed.py Sun Jul 31 17:30:24 2005 @@ -0,0 +1,285 @@ +import sys +import py +from py.test import raises +from pypy.translator.test import snippet +from pypy.rpython.rarithmetic import r_uint + +from pypy.translator.llvm2.genllvm import compile_function + +def test_call_five(): + # -- the result of call_five() isn't a real list, but an rlist + # that can't be converted to a PyListObject + def wrapper(): + lst = snippet.call_five() + 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(): + py.test.skip("array type of void") + def testfn(): + l1 = [] + return l1 is l1 + fn = compile_function(testfn, []) + result = fn() + assert result is True + def testfn(): + l1 = [] + return l1 is None + fn = compile_function(testfn, []) + result = fn() + assert result is False + +def test_str_compare(): + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] == s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] != s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] < s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] <= s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] > s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + + def testfn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] >= s2[j] + fn = compile_function(testfn, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn(i, j) + +def test_str_methods(): + def testfn(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, [int, int]) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res == testfn(i, j) + def testfn(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, [int, int]) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res == testfn(i, j) + +def test_str_join(): + 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(): + py.test.skip("unichar_eq operation missing") + 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(): + py.test.skip("unichar_ne operation missing") + 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("cast_unichar_to_int operation missing") + 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("cast_int_to_unichar operation missing") + 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("strangness with llvm rem operation...") + def func(x, y): + z = x + y / 2.1 * x + z = 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 + +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(): + 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_float2int(): + py.test.skip("XXX dont understand") + def fn(f): + return str(f) + def wrapper(): + res = fn(1.0) + return res == "1.0" + + f = compile_function(wrapper, [], view=True) + assert f() + +def test_uint_arith(): + py.test.skip("uint_invert operation missing") + 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) From ericvrp at codespeak.net Sun Jul 31 21:00:33 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 31 Jul 2005 21:00:33 +0200 (CEST) Subject: [pypy-svn] r15482 - pypy/extradoc/sprintinfo Message-ID: <20050731190033.0701827B61@code1.codespeak.net> Author: ericvrp Date: Sun Jul 31 21:00:32 2005 New Revision: 15482 Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt Log: I will arrive the 22nd in the afternoon Modified: pypy/extradoc/sprintinfo/heidelberg-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/heidelberg-people.txt (original) +++ pypy/extradoc/sprintinfo/heidelberg-people.txt Sun Jul 31 21:00:32 2005 @@ -15,7 +15,7 @@ Samuele Pedroni ?21st-29th Aug ? Carl Friedrich Bolz 21st-29th Aug ? Niklaus Haldimann 21st-29th Aug private -Eric van Riet Paap ? probably private +Eric van Riet Paap 22nd-28th Aug private Holger Krekel 21st-29th Aug private Richard Emslie 22nd-29th Aug private Michael Hudson (?) ? ? From tismer at codespeak.net Sun Jul 31 21:01:50 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 31 Jul 2005 21:01:50 +0200 (CEST) Subject: [pypy-svn] r15483 - pypy/extradoc/sprintinfo Message-ID: <20050731190150.5F37527B5D@code1.codespeak.net> Author: tismer Date: Sun Jul 31 21:01:48 2005 New Revision: 15483 Added: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt (contents, props changed) Log: some notes about the time between Hildesberg and Heidelheim. Please check, augment, ... Added: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt Sun Jul 31 21:01:48 2005 @@ -0,0 +1,47 @@ +planning for the time between the Hildesheim and Heidelberg sprints +=================================================================== + +clean-up areas +-------------- + +the following issues are meant to be 0.7 issues. + +- translate_pypy and the translator class need some cleanup + +- initialization of the object space is still messy + +- rtyper problem: exceptions are no longer always at the end of a code + block because of the lowlevel rewriting + +- move bits around in the annotator to make different uses + more pluggable + +- better support of math and float exceptions + +- reorganizing some wrongly named things + +- erasing useless files + +- cleanup of import dependencies + +- support for tests from external users and different platforms + +- preparing the next release + +- documentation about external function calls and implementing + builtin modules + +- related to the previous: documenting how interplevel marshal + is plugged into the system + +- prefixing all the C macros and names with pypy + +- look into XXX issues + +- support producing a windows binary, choose a suitable compiler + +additional wild ideas +--------------------- + +- thinking of an RPython flowgraph interpreter as an executable? + From rxe at codespeak.net Sun Jul 31 21:08:04 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 21:08:04 +0200 (CEST) Subject: [pypy-svn] r15484 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050731190804.547EF27B5D@code1.codespeak.net> Author: rxe Date: Sun Jul 31 21:08:02 2005 New Revision: 15484 Modified: pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_typed.py Log: A few more ops, a few more tests pass. Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sun Jul 31 21:08:02 2005 @@ -43,6 +43,13 @@ 'char_ge': 'setge', 'char_gt': 'setgt', + 'unichar_lt': 'setlt', + 'unichar_le': 'setle', + 'unichar_eq': 'seteq', + 'unichar_ne': 'setne', + 'unichar_ge': 'setge', + 'unichar_gt': 'setgt', + 'float_mul': 'mul', 'float_add': 'add', 'float_sub': 'sub', @@ -165,6 +172,7 @@ cast_int_to_bool = cast_int_to_char = cast_int_to_uint = cast_primitive cast_uint_to_bool = cast_uint_to_char = cast_uint_to_int = cast_primitive cast_int_to_float = cast_float_to_int = cast_primitive + cast_unichar_to_int = cast_int_to_unichar = cast_primitive cast_pointer = cast_primitive same_as = cast_primitive Modified: pypy/dist/pypy/translator/llvm2/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_typed.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_typed.py Sun Jul 31 21:08:02 2005 @@ -163,7 +163,6 @@ assert res == testfn(i, j) def test_unichr_eq(): - py.test.skip("unichar_eq operation missing") l = list(u'Hello world') def f(i, j): return l[i] == l[j] @@ -174,7 +173,6 @@ assert res == f(i,j) def test_unichr_ne(): - py.test.skip("unichar_ne operation missing") l = list(u'Hello world') def f(i, j): return l[i] != l[j] @@ -185,7 +183,6 @@ assert res == f(i, j) def test_unichr_ord(): - py.test.skip("cast_unichar_to_int operation missing") l = list(u'Hello world') def f(i): return ord(l[i]) @@ -195,7 +192,6 @@ assert res == f(i) def test_unichr_unichr(): - py.test.skip("cast_int_to_unichar operation missing") l = list(u'Hello world') def f(i, j): return l[i] == unichr(j) From hpk at codespeak.net Sun Jul 31 21:15:10 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 31 Jul 2005 21:15:10 +0200 (CEST) Subject: [pypy-svn] r15485 - pypy/extradoc/sprintinfo Message-ID: <20050731191510.934E027B61@code1.codespeak.net> Author: hpk Date: Sun Jul 31 21:15:09 2005 New Revision: 15485 Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt Log: fix ReST Modified: pypy/extradoc/sprintinfo/hildesheim2-done.txt ============================================================================== --- pypy/extradoc/sprintinfo/hildesheim2-done.txt (original) +++ pypy/extradoc/sprintinfo/hildesheim2-done.txt Sun Jul 31 21:15:09 2005 @@ -153,7 +153,7 @@ tests allow to use 'self.somevalue' coming from interplevel 'self.w_somevalue'. - DONE finish/send out the Heidelberg sprint announcement - goals: do the 0.7 release! + goals: do the 0.7 release! (0.7 is meant as a first self-contained pypy release with quite some c-extension modules missing (everything below 1.0 is implicitly alpha'ed or XXXed or both) From arigo at codespeak.net Sun Jul 31 22:17:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Jul 2005 22:17:26 +0200 (CEST) Subject: [pypy-svn] r15486 - pypy/dist/pypy/translator/goal Message-ID: <20050731201726.6965427B61@code1.codespeak.net> Author: arigo Date: Sun Jul 31 22:17:24 2005 New Revision: 15486 Removed: pypy/dist/pypy/translator/goal/ISSUES.txt Modified: pypy/dist/pypy/translator/goal/runtranslate.sh Log: Removed ISSUES.txt. Moved the still relevant paragraph to runtranslate.sh. Deleted: /pypy/dist/pypy/translator/goal/ISSUES.txt ============================================================================== --- /pypy/dist/pypy/translator/goal/ISSUES.txt Sun Jul 31 22:17:24 2005 +++ (empty file) @@ -1,170 +0,0 @@ -Known RTyper issues -------------------- - -Let's list and update here the issues that will show up, or have shown up -already sometime ago, while running translate_pypy:: - - * how to implement the three overrides of translator/ann_override.py ? - - * a new snapshot (14956) of the trunk (which is again annotable) has been made - - * current list of RTyper problems: - - TyperError-1: (pypy.objspace.std.listobject:unwrap) - no list() support for - .. block at 73 with 1 exits - .. v627007 = simple_call((type list), v627002) - - TyperError-2: (pypy.module.__builtin__.importing:try_import_mod) - don't know about built-in function - .. block at -1 with 2 exits(v908659) - .. v908643 = simple_call((function exists), f_908613) - - TyperError-3: (pypy.module.__builtin__.importing:load_part) - don't know about built-in function - .. block at 201 with 2 exits(v853316) - .. v853285 = simple_call((function isdir), v853248) - - TyperError-4: (pypy.module.sys.vm:getrefcount) - don't know about built-in function - .. block at -1 with 1 exits - .. v324725 = simple_call((builtin_function_or_method getrefcount), w_obj_324706) - - TyperError-5: (pypy.objspace.std.fake:fake__new__) - don't know about built-in function - .. block at 145 with 1 exits - .. v439600 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v439572, v43 - 9573) - - TyperError-6: (pypy.objspace.std.fake:fake__new__) - don't know about built-in function - .. block at 145 with 1 exits - .. v338257 = simple_call((builtin_function_or_method apply), (builtin_function_or_method __new__), v338229, v33 - 8230) - - TyperError-7: (pypy.objspace.std.fake:setfastscope) - ll_str unsupported for: - .. block at 118 with 1 exits - .. v181912 = mod(('calling %s: %s'), v181901) - - TyperError-8: (pypy.objspace.std.fake:run) - don't know about built-in function - .. block at 62 with 1 exits - .. v185355 = simple_call((builtin_function_or_method apply), v185337, v185338, v185339) - - TyperError-9: (pypy.objspace.std.floatobject:hash__Float) - unimplemented operation: 'hash' on - .. block at -1 with 1 exits - .. v374573 = hash(v374562) - - TyperError-10: (pypy.objspace.std.longobject:longval) - don't know about built-in function - .. block at 50 with 1 exits - .. v630648 = simple_call((type long), d_630611) - - TyperError-11: (pypy.objspace.std.objspace:unwrap) - don't know how to convert from to - .. block at -1 EH with 2 exits(v471216) - .. link from block at -1 EH to codeless block - - TyperError-12: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v768205) - .. link from block at -1 to block at 945 - - TyperError-13: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v767254) - .. link from block at -1 to block at -1 - - TyperError-14: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v767231) - .. link from block at -1 to block at -1 - - TyperError-15: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:wrap_exception_cls - .. block at 886 with 2 exits(v768328) - .. v768288 = call_specialcase(v768251, x_768230) - - TyperError-16: (pypy.objspace.std.objspace:wrap__object) - no unichr() support for - .. block at 265 with 1 exits - .. v767616 = simple_call((builtin_function_or_method unichr), v767586) - - TyperError-17: (pypy.objspace.std.objspace:unwrap) - unimplemented operation: 'mod' on (, - ) - .. block at 63 with 1 exits - .. v471239 = mod(('cannot unwrap: %r'), v471233) - - TyperError-18: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v767718) - .. link from block at -1 to block at -1 - - TyperError-19: (pypy.objspace.std.objspace:wrap__object) - don't know how to convert from to - .. block at -1 with 2 exits(v768158) - .. link from block at -1 to block at -1 - - TyperError-20: (pypy.objspace.std.objspace:wrap__object) - call_specialcase: unknown tag override:fake_object - .. block at 945 with 1 exits - .. v768246 = call_specialcase((function fake_object), v768225, v768226) - - TyperError-21: (pypy.objspace.std.objspace:wrap__object) - no list() support for - .. block at 446 with 1 exits - .. v767707 = simple_call((type list), x_767610) - - TyperError-22: (pypy.objspace.std.sliceobject:unwrap) - don't know about built-in function - .. block at -1 with 1 exits - .. v626191 = simple_call((type slice), v626103, v626139, v626178) - - TyperError-23: (pypy.objspace.std.tupleobject:unwrap) - don't know about built-in function - .. block at 66 with 1 exits - .. v626786 = simple_call((type tuple), v626781) - - TyperError-24: (pypy.objspace.std.unicodeobject:unwrap) - don't know how to convert from to - .. block at -1 with 1 exits - .. v626273 = simple_call((builtin_function_or_method join), v626264) - - TyperError-25: (pypy.objspace.std.unicodeobject:unicode_zfill__Unicode_ANY) - cannot make repr of - .. block at 185 with 2 exits(v366540) - .. v366515 = contains(((u'+', u'-')), v366475) - - TyperError-26: (pypy.interpreter.pycompiler:compile) - call_specialcase: unknown tag override:cpy_stablecompiler - .. block at 156 with 1 exits - .. v775851 = call_specialcase(v775814, parse_result_775797, filename_775793, mode_775794) - - -How to work in parallel: -There is an environment variable to be set with your personal random seed. -Seeds taken so far are -Armin: 42, Samuele: 46, Chris: 49, Arre: 97, hpk/rxe: 23 -Under Windows, use -SET RTYPERSEED=xx -where xx is your seed. When you run translate_pypy, you will get a message -with your seed, if everything is fine. The purpose of the seed is to -shuffle the annotated blocks, in order to create different errors. - -To get the above RTYPER problems, do:: - - RTYPERORDER=order,SOMEFILE - # stopping on the first error - python translate_pypy.py -no-c -no-o -fork -text -t-insist - - # seeing things in the graph - python translate_pypy.py -no-c -no-o - -In the SOMEFILE you put: - pypy.rpython.rarithmetic.ovfcheck_float_to_int Modified: pypy/dist/pypy/translator/goal/runtranslate.sh ============================================================================== --- pypy/dist/pypy/translator/goal/runtranslate.sh (original) +++ pypy/dist/pypy/translator/goal/runtranslate.sh Sun Jul 31 22:17:24 2005 @@ -3,3 +3,26 @@ #python translate_pypy.py -no-c -no-o -text -no-snapshot -fork # running it all python translate_pypy.py -no-o -text -t-insist -no-snapshot + + +# How to work in parallel: +# There is an environment variable to be set with your personal random seed. +# Seeds taken so far are +# Armin: 42, Samuele: 46, Chris: 49, Arre: 97, hpk/rxe: 23 +# Under Windows, use +# SET RTYPERSEED=xx +# where xx is your seed. When you run translate_pypy, you will get a message +# with your seed, if everything is fine. The purpose of the seed is to +# shuffle the annotated blocks, in order to create different errors. + +# To get the above RTYPER problems, do:: + +# RTYPERORDER=order,SOMEFILE +# # stopping on the first error +# python translate_pypy.py -no-c -no-o -fork -text -t-insist + +# # seeing things in the graph +# python translate_pypy.py -no-c -no-o + +# In the SOMEFILE you put: +# pypy.rpython.rarithmetic.ovfcheck_float_to_int From pedronis at codespeak.net Sun Jul 31 22:48:10 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 31 Jul 2005 22:48:10 +0200 (CEST) Subject: [pypy-svn] r15488 - pypy/extradoc/sprintinfo Message-ID: <20050731204810.C70C227B61@code1.codespeak.net> Author: pedronis Date: Sun Jul 31 22:48:09 2005 New Revision: 15488 Modified: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt Log: problem about id used as hashes being frozen and then invalid Modified: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt (original) +++ pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt Sun Jul 31 22:48:09 2005 @@ -13,6 +13,9 @@ - rtyper problem: exceptions are no longer always at the end of a code block because of the lowlevel rewriting +- translation problem: frozen ids used as hashes are broken + in the post-translation program + - move bits around in the annotator to make different uses more pluggable From cfbolz at codespeak.net Sun Jul 31 22:51:03 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 22:51:03 +0200 (CEST) Subject: [pypy-svn] r15489 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20050731205103.B9AB727B61@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 22:50:58 2005 New Revision: 15489 Added: pypy/dist/pypy/rpython/memory/lltypesimulation.py pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py Modified: pypy/dist/pypy/rpython/memory/lladdress.py pypy/dist/pypy/rpython/memory/simulator.py Log: started writing an implementation of lltype ptrs that use the memory simulator. It is a bit crooked and for now only Structs with primitive types. Modified: pypy/dist/pypy/rpython/memory/lladdress.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lladdress.py (original) +++ pypy/dist/pypy/rpython/memory/lladdress.py Sun Jul 31 22:50:58 2005 @@ -36,6 +36,13 @@ def __repr__(self): return "" % self.intaddress + + def _load(self, fmt): + return simulator.getstruct(fmt, self.intaddress) + + def _store(self, fmt, *values): + simulator.setstruct(fmt, self.intaddress, *values) + class _accessor(object): def __init__(self, addr): self.intaddress = addr.intaddress @@ -96,3 +103,4 @@ "char": lltype.Char, "address": Address, } + Added: pypy/dist/pypy/rpython/memory/lltypesimulation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/lltypesimulation.py Sun Jul 31 22:50:58 2005 @@ -0,0 +1,82 @@ +from pypy.rpython.memory import lladdress +from pypy.rpython import lltype + +import struct + +primitive_to_fmt = {lltype.Signed: "i", + lltype.Unsigned: "I", + lltype.Char: "c", + } + +def get_layout(TYPE): + layout = {} + if isinstance(TYPE, lltype.Primitive): + return primitive_to_fmt[TYPE] + if isinstance(TYPE, lltype.Ptr): + return "P" + if isinstance(TYPE, lltype.Struct): + curr = 0 + for name in TYPE._names: + layout[name] = curr + curr += get_size(TYPE._flds[name]) + layout["_size"] = curr + return layout + else: + assert 0, "not yet implemented" + +def get_size(TYPE): + if isinstance(TYPE, lltype.Primitive): + return struct.calcsize(primitive_to_fmt[TYPE]) + elif isinstance(TYPE, lltype.Ptr): + return struct.calcsize("P") + elif isinstance(TYPE, lltype.Struct): + return get_layout(TYPE)["_size"] + else: + assert 0, "not yet implemented" + +# this class is intended to replace the _ptr class in lltype +# using the memory simulator +class SimulatorPtr(object): + def __init__(self, TYPE, address): + self.__dict__['_TYPE'] = TYPE + self.__dict__['_T'] = TYPE.TO + self.__dict__['_address'] = address + self.__dict__['_layout'] = get_layout(TYPE.TO) + self._zero_initialize() + + def _zero_initialize(self): + size = get_size(self._T) + self._address._store("c" * size, *(["\x00"] * size)) + + def __getattr__(self, field_name): + if isinstance(self._T, lltype.Struct): + offset = self._layout[field_name] + if field_name in self._T._flds: + T = self._T._flds[field_name] + base = self._layout[field_name] + if isinstance(T, lltype.Primitive): + return (self._address + offset)._load(primitive_to_fmt[T])[0] + else: + assert 0, "not implemented" + raise AttributeError, ("%r instance has no field %r" % (self._T, + field_name)) + + def __setattr__(self, field_name, value): + if isinstance(self._T, lltype.Struct): + if field_name in self._T._flds: + T = self._T._flds[field_name] + base = self._layout[field_name] + if isinstance(T, lltype.Primitive): + (self._address + base)._store(primitive_to_fmt[T], value) + return + else: + assert 0, "not implemented" + raise AttributeError, ("%r instance has no field %r" % (self._T, + field_name)) + + +# for now use the simulators raw_malloc +def malloc(T, n=None, immortal=False): + size = get_size(T) + address = lladdress.raw_malloc(size) + return SimulatorPtr(lltype.Ptr(T), address) Modified: pypy/dist/pypy/rpython/memory/simulator.py ============================================================================== --- pypy/dist/pypy/rpython/memory/simulator.py (original) +++ pypy/dist/pypy/rpython/memory/simulator.py Sun Jul 31 22:50:58 2005 @@ -29,7 +29,7 @@ assert offset >= 0 if self.freed: raise MemorySimulatorError, "trying to access free memory" - if offset + size >= self.size: + if offset + size > self.size: raise MemorySimulatorError, "trying to access memory between blocks" if "u" in self.status[offset: offset+size]: raise MemorySimulatorError, "trying to access uninitialized memory" @@ -39,7 +39,7 @@ assert offset >= 0 if self.freed: raise MemorySimulatorError, "trying to access free memory" - if offset + len(value) >= self.size: + if offset + len(value) > self.size: raise MemorySimulatorError, "trying to access memory between blocks" a = array.array("c") a.fromstring(value) @@ -47,6 +47,7 @@ s.fromstring("i" * len(value)) self.memory[offset:offset + len(value)] = a self.status[offset:offset + len(value)] = s + assert len(self.memory) == self.size class MemorySimulator(object): def __init__(self): Added: pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/memory/test/test_lltypesimulation.py Sun Jul 31 22:50:58 2005 @@ -0,0 +1,35 @@ +from pypy.rpython.memory.lltypesimulation import * +from pypy.rpython.lltype import GcStruct, Ptr, Signed, Char + +def test_struct(): + S0 = GcStruct("s0", ('a', Signed), ('b', Signed), ('c', Char)) + s0 = malloc(S0) + print s0 + assert s0.a == 0 + assert s0.b == 0 + assert s0.c == '\x00' + s0.a = 42 + s0.b = 43 + s0.c = 'x' + assert s0.a == 42 + assert s0.b == 43 + assert s0.c == 'x' + s0.a = 1 + s0.b = s0.a + assert s0.a == 1 + assert s0.b == 1 + +def DONOTtest_array(): + Ar = lltype.GcArray(('v', Signed)) + x = malloc(Ar,0) + print x + assert len(x) == 0 + x = malloc(Ar,3) + print x + assert typeOf(x) == Ptr(Ar) + assert typeOf(x[0].v) == Signed + assert x[0].v == 0 + x[0].v = 1 + x[1].v = 2 + x[2].v = 3 + assert [x[z].v for z in range(3)] == [1, 2, 3] From rxe at codespeak.net Sun Jul 31 23:07:24 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sun, 31 Jul 2005 23:07:24 +0200 (CEST) Subject: [pypy-svn] r15490 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050731210724.BCCE527B61@code1.codespeak.net> Author: rxe Date: Sun Jul 31 23:07:22 2005 New Revision: 15490 Modified: pypy/dist/pypy/translator/llvm2/arraynode.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/opwriter.py pypy/dist/pypy/translator/llvm2/test/test_typed.py Log: An implementation of array of voids. Cleanup required (when I get home). Modified: pypy/dist/pypy/translator/llvm2/arraynode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/arraynode.py (original) +++ pypy/dist/pypy/translator/llvm2/arraynode.py Sun Jul 31 23:07:22 2005 @@ -49,6 +49,16 @@ self.constructor_decl, fromtype) +class VoidArrayTypeNode(LLVMNode): + + def __init__(self, db, array): + assert isinstance(array, lltype.Array) + self.ref = "%arraytype.Void" + + def writedatatypedecl(self, codewriter): + td = "%s = type { int }" % self.ref + codewriter.append(td) + class ArrayNode(ConstantLLVMNode): """ An arraynode. Elements can be a primitive, @@ -159,3 +169,31 @@ if len(items) == 0 or items[-1] != chr(0): items = items + [chr(0)] return [self.db.repr_constant(v)[1] for v in items] + +class VoidArrayNode(ConstantLLVMNode): + + def __init__(self, db, value): + assert isinstance(lltype.typeOf(value), lltype.Array) + self.ref = self.make_ref('%arrayinstance', '') + self.value = value + + def get_length(self): + """ returns logical length of array """ + items = self.value.items + return len(items) + + def get_typerepr(self): + return "{ int }" + + def get_arrayvalues(self): + return [] + + def constantvalue(self): + value = "int %s" % (self.get_length(),) + s = "%s {%s}" % (self.get_typerepr(), value) + return s + + def writeglobalconstants(self, codewriter): + p, c = lltype.parentlink(self.value) + if p is None: + codewriter.globalinstance(self.ref, self.constantvalue()) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jul 31 23:07:22 2005 @@ -4,7 +4,7 @@ from pypy.translator.llvm2.structnode import StructNode, StructVarsizeNode, \ StructTypeNode, StructVarsizeTypeNode from pypy.translator.llvm2.arraynode import ArrayNode, StrArrayNode, \ - ArrayTypeNode + VoidArrayNode, ArrayTypeNode, VoidArrayTypeNode from pypy.translator.llvm2.opaquenode import OpaqueNode, OpaqueTypeNode from pypy.translator.llvm2.node import ConstantLLVMNode from pypy.rpython import lltype @@ -124,6 +124,8 @@ elif isinstance(type_, lltype.Array): if type_ is STR.chars: node = StrArrayNode(self, value) + elif type_.OF is lltype.Void: + node = VoidArrayNode(self, value) else: node = ArrayNode(self, value) @@ -195,7 +197,10 @@ self.addpending(type_, FuncTypeNode(self, type_)) elif isinstance(type_, lltype.Array): - self.addpending(type_, ArrayTypeNode(self, type_)) + if type_.OF is lltype.Void: + self.addpending(type_, VoidArrayTypeNode(self, type_)) + else: + self.addpending(type_, ArrayTypeNode(self, type_)) elif isinstance(type_, lltype.OpaqueType): self.addpending(type_, OpaqueTypeNode(self, type_)) Modified: pypy/dist/pypy/translator/llvm2/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm2/opwriter.py Sun Jul 31 23:07:22 2005 @@ -135,7 +135,14 @@ self.db.repr_arg_type(op.args[0]), self.db.repr_arg(op.args[0]), "true") - + + def uint_invert(self, op): + self.codewriter.binaryop("xor", + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + 1) + def binaryop(self, op): name = self.binary_operations[op.opname] assert len(op.args) == 2 @@ -306,9 +313,19 @@ arg_type = op.args[0] assert (isinstance(arg_type, Constant) and isinstance(arg_type.value, (lltype.Array, lltype.Struct))) + #XXX unclean - struct_type = self.db.obj2node[arg_type.value].ref - struct_cons = self.db.obj2node[arg_type.value].constructor_ref + node = self.db.obj2node[arg_type.value] + + #XXX AAARRRRRRRRRGFFFFFFFFFFFFGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHH + from pypy.translator.llvm2.arraynode import VoidArrayTypeNode + if isinstance(node, VoidArrayTypeNode): + type_ = node.ref + self.codewriter.malloc(targetvar, type_, atomic=is_atomic(node)) + return + + struct_type = node.ref + struct_cons = node.constructor_ref argrefs = self.db.repr_arg_multi(op.args[1:]) argtypes = self.db.repr_arg_type_multi(op.args[1:]) self.codewriter.call(targetvar, struct_type + "*", struct_cons, @@ -356,13 +373,14 @@ index = self.db.repr_arg(op.args[1]) indextype = self.db.repr_arg_type(op.args[1]) tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, arraytype, array, - ("uint", 1), (indextype, index)) targetvar = self.db.repr_arg(op.result) targettype = self.db.repr_arg_type(op.result) - #XXX These should skip too if the case comes up - assert targettype != "void" - self.codewriter.load(targetvar, targettype, tmpvar) + if targettype != "void": + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) + self.codewriter.load(targetvar, targettype, tmpvar) + else: + self.codewriter.comment("***Skipping operation getarrayitem()***") def getarraysubstruct(self, op): array, arraytype = self.db.repr_argwithtype(op.args[0]) @@ -378,14 +396,17 @@ indextype = self.db.repr_arg_type(op.args[1]) tmpvar = self.db.repr_tmpvar() - self.codewriter.getelementptr(tmpvar, arraytype, array, - ("uint", 1), (indextype, index)) valuevar = self.db.repr_arg(op.args[2]) valuetype = self.db.repr_arg_type(op.args[2]) #XXX These should skip too if the case comes up - assert valuetype != "void" - self.codewriter.store(valuetype, valuevar, tmpvar) + if valuetype != "void": + self.codewriter.getelementptr(tmpvar, arraytype, array, + ("uint", 1), (indextype, index)) + self.codewriter.store(valuetype, valuevar, tmpvar) + else: + self.codewriter.comment("***Skipping operation setarrayitem()***") + def getarraysize(self, op): array, arraytype = self.db.repr_argwithtype(op.args[0]) Modified: pypy/dist/pypy/translator/llvm2/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_typed.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_typed.py Sun Jul 31 23:07:22 2005 @@ -55,19 +55,27 @@ assert result def test_is(): - py.test.skip("array type of void") def testfn(): l1 = [] return l1 is l1 fn = compile_function(testfn, []) result = fn() - assert result is True + assert result == True def testfn(): l1 = [] - return l1 is None + return l1 == None fn = compile_function(testfn, []) result = fn() - assert result is False + 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(i, j): @@ -203,7 +211,7 @@ # floats def test_float_operations(): - py.test.skip("strangness with llvm rem operation...") + py.test.skip("llvm rem operation doesnt seem to work...") def func(x, y): z = x + y / 2.1 * x z = z % 60.0 @@ -257,8 +265,8 @@ f = compile_function(wrapper, [int]) assert f(42) -def test_float2int(): - py.test.skip("XXX dont understand") +def Xtest_float2int(): + """ RTyper is cheating....""" def fn(f): return str(f) def wrapper(): @@ -269,7 +277,7 @@ assert f() def test_uint_arith(): - py.test.skip("uint_invert operation missing") + py.test.skip("uint_floordiv_zer operation missing (raises)") def fn(i): try: return ~(i*(i+1))/(i-1) From cfbolz at codespeak.net Sun Jul 31 23:23:51 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Jul 2005 23:23:51 +0200 (CEST) Subject: [pypy-svn] r15491 - pypy/dist/pypy/rpython/memory Message-ID: <20050731212351.7906027B61@code1.codespeak.net> Author: cfbolz Date: Sun Jul 31 23:23:50 2005 New Revision: 15491 Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py Log: as per samuele's suggestion I change the name of SimulatorPtr to make it more similar to _ptr. Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/lltypesimulation.py (original) +++ pypy/dist/pypy/rpython/memory/lltypesimulation.py Sun Jul 31 23:23:50 2005 @@ -36,7 +36,7 @@ # this class is intended to replace the _ptr class in lltype # using the memory simulator -class SimulatorPtr(object): +class simulatorptr(object): def __init__(self, TYPE, address): self.__dict__['_TYPE'] = TYPE self.__dict__['_T'] = TYPE.TO @@ -79,4 +79,4 @@ def malloc(T, n=None, immortal=False): size = get_size(T) address = lladdress.raw_malloc(size) - return SimulatorPtr(lltype.Ptr(T), address) + return simulatorptr(lltype.Ptr(T), address) From pedronis at codespeak.net Sun Jul 31 23:43:20 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 31 Jul 2005 23:43:20 +0200 (CEST) Subject: [pypy-svn] r15492 - pypy/extradoc/sprintinfo Message-ID: <20050731214320.10D2727B61@code1.codespeak.net> Author: pedronis Date: Sun Jul 31 23:43:18 2005 New Revision: 15492 Modified: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt Log: found out that stroring instances bound methods on instances confuses the annotator resulting in blocked blocks Modified: pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt ============================================================================== --- pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt (original) +++ pypy/extradoc/sprintinfo/Hildes_to_Heidel.txt Sun Jul 31 23:43:18 2005 @@ -43,6 +43,32 @@ - support producing a windows binary, choose a suitable compiler +other issues +--------------------- + +storing bound method on instances confuses the annotator (we can probably live with this limitation +right now, I'm not sure but it may require a large refactoring to support this) + +>>> class H: +... def h(): +... pass +... +>>> class C: +... def __init__(self, func): +... self.f = func +... def do(self): +... self.f() +... +>>> def g(): +... h = H() +... c = C(h.h) +... c.do() +... +>>> t=Translator(g) +>>> t.annotate([]) + + + additional wild ideas ---------------------